summaryrefslogtreecommitdiff
path: root/chromium/tools
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@theqtcompany.com>2016-07-14 17:41:05 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2016-08-04 12:37:36 +0000
commit399c965b6064c440ddcf4015f5f8e9d131c7a0a6 (patch)
tree6b06b60ff365abef0e13b3503d593a0df48d20e8 /chromium/tools
parent7366110654eec46f21b6824f302356426f48cd74 (diff)
downloadqtwebengine-chromium-399c965b6064c440ddcf4015f5f8e9d131c7a0a6.tar.gz
BASELINE: Update Chromium to 52.0.2743.76 and Ninja to 1.7.1
Change-Id: I382f51b959689505a60f8b707255ecb344f7d8b4 Reviewed-by: Michael Brüning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/tools')
-rw-r--r--chromium/tools/battor_agent/BUILD.gn4
-rw-r--r--chromium/tools/battor_agent/battor_agent.cc2
-rw-r--r--chromium/tools/battor_agent/battor_agent.gyp3
-rw-r--r--chromium/tools/battor_agent/battor_agent_bin.cc162
-rw-r--r--chromium/tools/battor_agent/battor_agent_unittest.cc2
-rw-r--r--chromium/tools/battor_agent/battor_connection_impl.cc66
-rw-r--r--chromium/tools/battor_agent/battor_connection_impl.h6
-rw-r--r--chromium/tools/battor_agent/battor_connection_impl_unittest.cc2
-rw-r--r--chromium/tools/battor_agent/battor_protocol_types_unittest.cc27
-rw-r--r--chromium/tools/battor_agent/serial_utils.cc29
-rw-r--r--chromium/tools/battor_agent/serial_utils.h20
-rw-r--r--chromium/tools/battor_agent/serial_utils_unittest.cc36
-rw-r--r--chromium/tools/cfi/blacklist.txt16
-rwxr-xr-xchromium/tools/checkbins/checkbins.py1
-rwxr-xr-xchromium/tools/checklicenses/checklicenses.py62
-rw-r--r--chromium/tools/chrome_proxy/common/chrome_proxy_measurements.py21
-rw-r--r--chromium/tools/chrome_proxy/common/inspector_network.py8
-rw-r--r--chromium/tools/chrome_proxy/integration_tests/chrome_proxy_benchmark.py23
-rw-r--r--chromium/tools/chrome_proxy/integration_tests/chrome_proxy_measurements.py90
-rw-r--r--chromium/tools/chrome_proxy/integration_tests/chrome_proxy_metrics.py42
-rw-r--r--chromium/tools/chrome_proxy/integration_tests/chrome_proxy_pagesets/lo_fi_cache.py32
-rw-r--r--chromium/tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp21
-rw-r--r--chromium/tools/clang/blink_gc_plugin/BlinkGCPluginConsumer.cpp596
-rw-r--r--chromium/tools/clang/blink_gc_plugin/BlinkGCPluginConsumer.h110
-rw-r--r--chromium/tools/clang/blink_gc_plugin/BlinkGCPluginOptions.h6
-rw-r--r--chromium/tools/clang/blink_gc_plugin/CMakeLists.txt1
-rw-r--r--chromium/tools/clang/blink_gc_plugin/CheckFieldsVisitor.cpp60
-rw-r--r--chromium/tools/clang/blink_gc_plugin/CheckFieldsVisitor.h15
-rw-r--r--chromium/tools/clang/blink_gc_plugin/Config.h9
-rw-r--r--chromium/tools/clang/blink_gc_plugin/DiagnosticsReporter.cpp527
-rw-r--r--chromium/tools/clang/blink_gc_plugin/DiagnosticsReporter.h137
-rw-r--r--chromium/tools/clang/blink_gc_plugin/Edge.h7
-rw-r--r--chromium/tools/clang/blink_gc_plugin/OWNERS3
-rw-r--r--chromium/tools/clang/blink_gc_plugin/RecordInfo.cpp18
-rw-r--r--chromium/tools/clang/blink_gc_plugin/RecordInfo.h1
-rwxr-xr-xchromium/tools/clang/scripts/blink_gc_plugin_flags.py14
-rwxr-xr-xchromium/tools/clang/scripts/update.py53
-rw-r--r--chromium/tools/copyright_scanner/third_party_files_whitelist.txt3
-rw-r--r--chromium/tools/cygprofile/cygprofile.cc59
-rwxr-xr-xchromium/tools/export_tarball/export_tarball.py197
-rwxr-xr-xchromium/tools/export_tarball/export_v8_tarball.py135
-rw-r--r--chromium/tools/findit/OWNERS1
-rw-r--r--chromium/tools/findit/blame.py165
-rw-r--r--chromium/tools/findit/chromium_deps.py240
-rw-r--r--chromium/tools/findit/chromium_deps_unittest.py189
-rw-r--r--chromium/tools/findit/common/__init__.py4
-rw-r--r--chromium/tools/findit/common/cacert.pem2186
-rw-r--r--chromium/tools/findit/common/http_client.py31
-rw-r--r--chromium/tools/findit/common/http_client_local.py253
-rw-r--r--chromium/tools/findit/common/http_client_local_unittest.py15
-rw-r--r--chromium/tools/findit/common/utils.py68
-rw-r--r--chromium/tools/findit/component_dictionary.py122
-rw-r--r--chromium/tools/findit/config.ini26
-rw-r--r--chromium/tools/findit/crash_utils.py570
-rw-r--r--chromium/tools/findit/deps_config.json17
-rw-r--r--chromium/tools/findit/findit_for_clusterfuzz.py224
-rw-r--r--chromium/tools/findit/findit_for_crash.py664
-rw-r--r--chromium/tools/findit/git_repository_parser.py293
-rw-r--r--chromium/tools/findit/match_set.py128
-rw-r--r--chromium/tools/findit/repository_parser_interface.py58
-rw-r--r--chromium/tools/findit/result.py19
-rwxr-xr-xchromium/tools/findit/run_all_tests.py18
-rw-r--r--chromium/tools/findit/stacktrace.py321
-rw-r--r--chromium/tools/findit/svn_repository_parser.py250
-rw-r--r--chromium/tools/gdb/gdb_chrome.py2
-rwxr-xr-xchromium/tools/generate_shim_headers/generate_shim_headers.py6
-rw-r--r--chromium/tools/gn/BUILD.gn8
-rw-r--r--chromium/tools/gn/DEPS3
-rw-r--r--chromium/tools/gn/args.cc22
-rw-r--r--chromium/tools/gn/bin/gn-format.py2
-rwxr-xr-xchromium/tools/gn/bin/roll_gn.py3
-rw-r--r--chromium/tools/gn/binary_target_generator.cc28
-rw-r--r--chromium/tools/gn/binary_target_generator.h1
-rwxr-xr-xchromium/tools/gn/bootstrap/bootstrap.py40
-rw-r--r--chromium/tools/gn/bundle_data.cc26
-rw-r--r--chromium/tools/gn/bundle_data.h49
-rw-r--r--chromium/tools/gn/bundle_file_rule.cc8
-rw-r--r--chromium/tools/gn/command_desc.cc596
-rw-r--r--chromium/tools/gn/command_format.cc39
-rw-r--r--chromium/tools/gn/command_gen.cc72
-rw-r--r--chromium/tools/gn/command_ls.cc9
-rw-r--r--chromium/tools/gn/command_refs.cc14
-rw-r--r--chromium/tools/gn/commands.cc22
-rw-r--r--chromium/tools/gn/commands.h6
-rw-r--r--chromium/tools/gn/config_values.cc1
-rw-r--r--chromium/tools/gn/config_values.h11
-rw-r--r--chromium/tools/gn/config_values_generator.cc1
-rw-r--r--chromium/tools/gn/create_bundle_target_generator.cc24
-rw-r--r--chromium/tools/gn/create_bundle_target_generator.h6
-rw-r--r--chromium/tools/gn/docs/cookbook.md21
-rw-r--r--chromium/tools/gn/docs/reference.md385
-rw-r--r--chromium/tools/gn/example/build/toolchain/BUILD.gn14
-rw-r--r--chromium/tools/gn/function_foreach.cc7
-rw-r--r--chromium/tools/gn/function_forward_variables_from.cc16
-rw-r--r--chromium/tools/gn/function_forward_variables_from_unittest.cc60
-rw-r--r--chromium/tools/gn/function_toolchain.cc67
-rw-r--r--chromium/tools/gn/functions.cc2
-rw-r--r--chromium/tools/gn/functions_target.cc5
-rw-r--r--chromium/tools/gn/gn.gyp6
-rw-r--r--chromium/tools/gn/gn_main.cc9
-rw-r--r--chromium/tools/gn/group_target_generator_unittest.cc46
-rw-r--r--chromium/tools/gn/import_manager.cc100
-rw-r--r--chromium/tools/gn/import_manager.h11
-rw-r--r--chromium/tools/gn/input_file_manager.cc30
-rw-r--r--chromium/tools/gn/input_file_manager.h7
-rw-r--r--chromium/tools/gn/loader.cc54
-rw-r--r--chromium/tools/gn/loader.h5
-rw-r--r--chromium/tools/gn/location.h5
-rw-r--r--chromium/tools/gn/misc/emacs/gn-mode.el19
-rw-r--r--chromium/tools/gn/ninja_binary_target_writer.cc53
-rw-r--r--chromium/tools/gn/ninja_binary_target_writer.h2
-rw-r--r--chromium/tools/gn/ninja_binary_target_writer_unittest.cc152
-rw-r--r--chromium/tools/gn/ninja_build_writer.cc308
-rw-r--r--chromium/tools/gn/ninja_build_writer.h7
-rw-r--r--chromium/tools/gn/ninja_build_writer_unittest.cc6
-rw-r--r--chromium/tools/gn/ninja_create_bundle_target_writer.cc11
-rw-r--r--chromium/tools/gn/ninja_create_bundle_target_writer_unittest.cc63
-rw-r--r--chromium/tools/gn/parse_tree.cc24
-rw-r--r--chromium/tools/gn/parse_tree.h18
-rw-r--r--chromium/tools/gn/parser.cc4
-rw-r--r--chromium/tools/gn/qt_creator_writer.cc174
-rw-r--r--chromium/tools/gn/qt_creator_writer.h56
-rw-r--r--chromium/tools/gn/runtime_deps.cc9
-rw-r--r--chromium/tools/gn/runtime_deps_unittest.cc106
-rw-r--r--chromium/tools/gn/scheduler.cc7
-rw-r--r--chromium/tools/gn/scope.cc25
-rw-r--r--chromium/tools/gn/scope.h7
-rw-r--r--chromium/tools/gn/setup.cc33
-rw-r--r--chromium/tools/gn/setup.h2
-rw-r--r--chromium/tools/gn/source_file_type.cc3
-rw-r--r--chromium/tools/gn/substitution_type.cc17
-rw-r--r--chromium/tools/gn/substitution_type.h5
-rw-r--r--chromium/tools/gn/substitution_writer.cc21
-rw-r--r--chromium/tools/gn/substitution_writer_unittest.cc42
-rw-r--r--chromium/tools/gn/switches.cc42
-rw-r--r--chromium/tools/gn/switches.h22
-rw-r--r--chromium/tools/gn/target.cc60
-rw-r--r--chromium/tools/gn/target.h8
-rw-r--r--chromium/tools/gn/target_generator.cc1
-rw-r--r--chromium/tools/gn/target_unittest.cc68
-rw-r--r--chromium/tools/gn/test_with_scope.cc23
-rw-r--r--chromium/tools/gn/test_with_scope.h7
-rw-r--r--chromium/tools/gn/tool.h9
-rw-r--r--chromium/tools/gn/variables.cc80
-rw-r--r--chromium/tools/gn/variables.h12
-rw-r--r--chromium/tools/gn/visual_studio_writer.cc188
-rw-r--r--chromium/tools/gn/visual_studio_writer.h22
-rw-r--r--chromium/tools/gn/visual_studio_writer_unittest.cc53
-rw-r--r--chromium/tools/gn/xcode_object.cc858
-rw-r--r--chromium/tools/gn/xcode_object.h392
-rw-r--r--chromium/tools/gn/xcode_writer.cc432
-rw-r--r--chromium/tools/gn/xcode_writer.h97
-rw-r--r--chromium/tools/grit/OWNERS1
-rw-r--r--chromium/tools/grit/grit_rule.gni7
-rw-r--r--chromium/tools/gritsettings/resource_ids8
-rw-r--r--chromium/tools/gyp/pylib/gyp/MSVSSettings.py1
-rw-r--r--chromium/tools/gyp/pylib/gyp/generator/msvs.py32
-rw-r--r--chromium/tools/gyp/pylib/gyp/generator/ninja.py3
-rw-r--r--chromium/tools/gyp/pylib/gyp/generator/xcode.py13
-rwxr-xr-xchromium/tools/gyp/pylib/gyp/mac_tool.py17
-rwxr-xr-xchromium/tools/gyp/pylib/gyp/win_tool.py18
-rw-r--r--chromium/tools/gyp/pylib/gyp/xcode_emulation.py65
-rw-r--r--chromium/tools/gyp/pylib/gyp/xcodeproj_file.py6
-rw-r--r--chromium/tools/gyp/test/ios/framework/framework.gyp4
-rw-r--r--chromium/tools/gyp/test/mac/xcuitest/test.gyp69
-rw-r--r--chromium/tools/gyp/test/win/compiler-flags/compile-as-winrt.gyp20
-rw-r--r--chromium/tools/idl_parser/OWNERS3
-rwxr-xr-xchromium/tools/idl_parser/idl_parser.py4
-rw-r--r--chromium/tools/imagediff/BUILD.gn39
-rwxr-xr-xchromium/tools/include_tracer.py1
-rw-r--r--chromium/tools/ipc_fuzzer/BUILD.gn37
-rw-r--r--chromium/tools/ipc_fuzzer/fuzzer/BUILD.gn28
-rw-r--r--chromium/tools/ipc_fuzzer/fuzzer/fuzzer.cc29
-rw-r--r--chromium/tools/ipc_fuzzer/ipc_fuzzer.gni16
-rw-r--r--chromium/tools/ipc_fuzzer/message_dump/BUILD.gn13
-rw-r--r--chromium/tools/ipc_fuzzer/message_lib/BUILD.gn44
-rw-r--r--chromium/tools/ipc_fuzzer/message_lib/DEPS1
-rw-r--r--chromium/tools/ipc_fuzzer/message_lib/all_messages.h2
-rw-r--r--chromium/tools/ipc_fuzzer/message_lib/message_lib.gyp2
-rw-r--r--chromium/tools/ipc_fuzzer/message_replay/BUILD.gn16
-rw-r--r--chromium/tools/ipc_fuzzer/message_replay/replay_process.cc3
-rw-r--r--chromium/tools/ipc_fuzzer/message_tools/BUILD.gn25
-rw-r--r--chromium/tools/json_schema_compiler/cc_generator.py40
-rw-r--r--chromium/tools/json_schema_compiler/util.cc4
-rwxr-xr-xchromium/tools/licenses.py13
-rwxr-xr-xchromium/tools/mb/mb.py219
-rw-r--r--chromium/tools/mb/mb_config.pyl1519
-rwxr-xr-xchromium/tools/mb/mb_unittest.py55
-rwxr-xr-x[-rw-r--r--]chromium/tools/md_browser/md_browser.py22
-rw-r--r--chromium/tools/origin_trials/OWNERS4
-rw-r--r--chromium/tools/origin_trials/eftest.key2
-rwxr-xr-xchromium/tools/polymer/generate_compiled_resources_gyp.py8
-rwxr-xr-xchromium/tools/roll_angle.py16
-rwxr-xr-xchromium/tools/roll_webgl_conformance.py21
-rwxr-xr-xchromium/tools/roll_webrtc.py53
-rwxr-xr-xchromium/tools/valgrind/chrome_tests.py4
-rw-r--r--chromium/tools/valgrind/drmemory/suppressions.txt40
-rw-r--r--chromium/tools/valgrind/drmemory/suppressions_full.txt86
-rw-r--r--chromium/tools/valgrind/gtest_exclude/base_unittests.gtest.txt4
-rw-r--r--chromium/tools/valgrind/gtest_exclude/browser_tests.gtest-drmemory.txt10
-rw-r--r--chromium/tools/valgrind/gtest_exclude/cc_unittests.gtest-drmemory_win32.txt1
-rw-r--r--chromium/tools/valgrind/gtest_exclude/components_unittests.gtest.txt3
-rw-r--r--chromium/tools/valgrind/gtest_exclude/content_browsertests.gtest-drmemory.txt14
-rw-r--r--chromium/tools/valgrind/gtest_exclude/content_unittests.gtest-drmemory_win32.txt3
-rw-r--r--chromium/tools/valgrind/gtest_exclude/net_unittests.gtest-drmemory_win32.txt6
-rw-r--r--chromium/tools/valgrind/gtest_exclude/remoting_unittests.gtest-drmemory_win32.txt3
-rw-r--r--chromium/tools/valgrind/gtest_exclude/unit_tests.gtest-drmemory_win32.txt3
-rw-r--r--chromium/tools/valgrind/memcheck/suppressions.txt107
-rw-r--r--chromium/tools/valgrind/memcheck/suppressions_linux.txt15
-rw-r--r--chromium/tools/vim/ninja-build.vim14
-rw-r--r--chromium/tools/vim/ninja_output.py24
211 files changed, 7539 insertions, 9186 deletions
diff --git a/chromium/tools/battor_agent/BUILD.gn b/chromium/tools/battor_agent/BUILD.gn
index 41f89e7dafa..bba270ec0c0 100644
--- a/chromium/tools/battor_agent/BUILD.gn
+++ b/chromium/tools/battor_agent/BUILD.gn
@@ -14,6 +14,7 @@ executable("battor_agent") {
deps = [
":battor_agent_lib",
"//base",
+ "//build/win:default_exe_manifest",
"//device/serial",
"//mojo/public/c/system:for_shared_library",
]
@@ -33,6 +34,8 @@ source_set("battor_agent_lib") {
"battor_finder.h",
"battor_sample_converter.cc",
"battor_sample_converter.h",
+ "serial_utils.cc",
+ "serial_utils.h",
]
deps = [
"//base",
@@ -47,6 +50,7 @@ test("battor_agent_unittests") {
"battor_connection_impl_unittest.cc",
"battor_protocol_types_unittest.cc",
"battor_sample_converter_unittest.cc",
+ "serial_utils_unittest.cc",
]
deps = [
":battor_agent_lib",
diff --git a/chromium/tools/battor_agent/battor_agent.cc b/chromium/tools/battor_agent/battor_agent.cc
index 323da5175e4..708192d1791 100644
--- a/chromium/tools/battor_agent/battor_agent.cc
+++ b/chromium/tools/battor_agent/battor_agent.cc
@@ -7,7 +7,7 @@
#include <iomanip>
#include "base/bind.h"
-#include "base/thread_task_runner_handle.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "tools/battor_agent/battor_connection_impl.h"
#include "tools/battor_agent/battor_sample_converter.h"
diff --git a/chromium/tools/battor_agent/battor_agent.gyp b/chromium/tools/battor_agent/battor_agent.gyp
index 974fbdefcf2..e726b9a5d4e 100644
--- a/chromium/tools/battor_agent/battor_agent.gyp
+++ b/chromium/tools/battor_agent/battor_agent.gyp
@@ -39,6 +39,8 @@
'battor_finder.h',
'battor_sample_converter.cc',
'battor_sample_converter.h',
+ 'serial_utils.cc',
+ 'serial_utils.h',
],
'dependencies': [
'../../base/base.gyp:base',
@@ -65,6 +67,7 @@
'battor_connection_impl_unittest.cc',
'battor_protocol_types_unittest.cc',
'battor_sample_converter_unittest.cc',
+ 'serial_utils_unittest.cc',
],
},
],
diff --git a/chromium/tools/battor_agent/battor_agent_bin.cc b/chromium/tools/battor_agent/battor_agent_bin.cc
index 7424d1ddb46..a4d783efa52 100644
--- a/chromium/tools/battor_agent/battor_agent_bin.cc
+++ b/chromium/tools/battor_agent/battor_agent_bin.cc
@@ -42,9 +42,11 @@
#include "base/command_line.h"
#include "base/location.h"
#include "base/logging.h"
+#include "base/run_loop.h"
#include "base/strings/string_tokenizer.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "tools/battor_agent/battor_agent.h"
#include "tools/battor_agent/battor_error.h"
#include "tools/battor_agent/battor_finder.h"
@@ -57,7 +59,6 @@ namespace {
const char kIoThreadName[] = "BattOr IO Thread";
const char kFileThreadName[] = "BattOr File Thread";
-const char kUiThreadName[] = "BattOr UI Thread";
const char kUsage[] =
"Start the battor_agent shell with:\n"
@@ -107,11 +108,7 @@ std::vector<std::string> TokenizeString(std::string cmd) {
// use a BattOrAgent to communicate with a BattOr.
class BattOrAgentBin : public BattOrAgent::Listener {
public:
- BattOrAgentBin()
- : done_(false, false),
- io_thread_(kIoThreadName),
- file_thread_(kFileThreadName),
- ui_thread_(kUiThreadName) {}
+ BattOrAgentBin() : io_thread_(kIoThreadName), file_thread_(kFileThreadName) {}
~BattOrAgentBin() { DCHECK(!agent_); }
@@ -127,43 +124,10 @@ class BattOrAgentBin : public BattOrAgent::Listener {
SetUp(path);
- std::string cmd;
- for (;;) {
- std::getline(std::cin, cmd);
-
- if (cmd == "StartTracing") {
- StartTracing();
- } else if (cmd.find("StopTracing") != std::string::npos) {
- std::vector<std::string> tokens = TokenizeString(cmd);
- if (tokens.size() == 1 && tokens[0] == "StopTracing") {
- // No path given.
- StopTracing();
- } else if (tokens.size() == 2 && tokens[0] == "StopTracing") {
- // Path given.
- StopTracing(tokens[1]);
- } else {
- std::cout << "Invalid StopTracing command." << endl;
- std::cout << kUsage << endl;
- continue;
- }
- break;
- } else if (cmd == "SupportsExplicitClockSync") {
- PrintSupportsExplicitClockSync();
- } else if (cmd.find("RecordClockSyncMarker") != std::string::npos) {
- std::vector<std::string> tokens = TokenizeString(cmd);
- if (tokens.size() != 2 || tokens[0] != "RecordClockSyncMarker") {
- std::cout << "Invalid RecordClockSyncMarker command." << endl;
- std::cout << kUsage << endl;
- continue;
- }
-
- RecordClockSyncMarker(tokens[1]);
- } else if (cmd == "Exit") {
- break;
- } else {
- std::cout << kUsage << endl;
- }
- }
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::Bind(&BattOrAgentBin::RunNextCommand, base::Unretained(this)));
+ ui_thread_run_loop_.Run();
TearDown();
return 0;
@@ -171,8 +135,6 @@ class BattOrAgentBin : public BattOrAgent::Listener {
// Performs any setup necessary for the BattOr binary to run.
void SetUp(const std::string& path) {
- // TODO(charliea): Investigate whether it's possible to replace this
- // separate thread with a combination of MessageLoopForIO and RunLoop.
base::Thread::Options io_thread_options;
io_thread_options.message_loop_type = base::MessageLoopForIO::TYPE_IO;
if (!io_thread_.StartWithOptions(io_thread_options)) {
@@ -181,23 +143,73 @@ class BattOrAgentBin : public BattOrAgent::Listener {
io_thread_.task_runner()->PostTask(
FROM_HERE,
- base::Bind(&BattOrAgentBin::CreateAgent, base::Unretained(this), path));
- done_.Wait();
+ base::Bind(&BattOrAgentBin::CreateAgent, base::Unretained(this), path,
+ base::ThreadTaskRunnerHandle::Get()));
}
// Performs any cleanup necessary after the BattOr binary is done running.
void TearDown() {
+ base::WaitableEvent done(false, false);
io_thread_.task_runner()->PostTask(
+ FROM_HERE, base::Bind(&BattOrAgentBin::DeleteAgent,
+ base::Unretained(this), &done));
+ done.Wait();
+ }
+
+ void RunNextCommand() {
+ std::string cmd;
+ std::getline(std::cin, cmd);
+
+ if (cmd == "StartTracing") {
+ StartTracing();
+ } else if (cmd.find("StopTracing") != std::string::npos) {
+ std::vector<std::string> tokens = TokenizeString(cmd);
+
+ if (tokens[0] != "StopTracing" || tokens.size() > 2) {
+ std::cout << "Invalid StopTracing command." << endl;
+ std::cout << kUsage << endl;
+ PostRunNextCommand();
+ return;
+ }
+
+ // tokens[1] contains the optional output file argument, which allows
+ // users to dump the trace to a file instead instead of to STDOUT.
+ std::string trace_output_file =
+ tokens.size() == 2 ? tokens[1] : std::string();
+
+ StopTracing(trace_output_file);
+ } else if (cmd == "SupportsExplicitClockSync") {
+ PrintSupportsExplicitClockSync();
+ PostRunNextCommand();
+ } else if (cmd.find("RecordClockSyncMarker") != std::string::npos) {
+ std::vector<std::string> tokens = TokenizeString(cmd);
+ if (tokens.size() != 2 || tokens[0] != "RecordClockSyncMarker") {
+ std::cout << "Invalid RecordClockSyncMarker command." << endl;
+ std::cout << kUsage << endl;
+ PostRunNextCommand();
+ return;
+ }
+
+ RecordClockSyncMarker(tokens[1]);
+ } else if (cmd == "Exit" || std::cin.eof()) {
+ ui_thread_message_loop_.task_runner()->PostTask(
+ FROM_HERE, ui_thread_run_loop_.QuitClosure());
+ } else {
+ std::cout << kUsage << endl;
+ PostRunNextCommand();
+ }
+ }
+
+ void PostRunNextCommand() {
+ ui_thread_message_loop_.task_runner()->PostTask(
FROM_HERE,
- base::Bind(&BattOrAgentBin::DeleteAgent, base::Unretained(this)));
- done_.Wait();
+ base::Bind(&BattOrAgentBin::RunNextCommand, base::Unretained(this)));
}
void StartTracing() {
io_thread_.task_runner()->PostTask(
FROM_HERE,
base::Bind(&BattOrAgent::StartTracing, base::Unretained(agent_.get())));
- done_.Wait();
}
void OnStartTracingComplete(BattOrError error) override {
@@ -206,16 +218,14 @@ class BattOrAgentBin : public BattOrAgent::Listener {
else
HandleError(error);
- done_.Signal();
+ PostRunNextCommand();
}
- void StopTracing(const std::string& path = "") {
- trace_output_file_ = path;
+ void StopTracing(const std::string& trace_output_file) {
+ trace_output_file_ = trace_output_file;
io_thread_.task_runner()->PostTask(
FROM_HERE,
base::Bind(&BattOrAgent::StopTracing, base::Unretained(agent_.get())));
- done_.Wait();
- trace_output_file_ = std::string();
}
void OnStopTracingComplete(const std::string& trace,
@@ -223,8 +233,7 @@ class BattOrAgentBin : public BattOrAgent::Listener {
if (error == BATTOR_ERROR_NONE) {
if (trace_output_file_.empty()) {
std::cout << trace;
- }
- else {
+ } else {
std::ofstream trace_stream(trace_output_file_);
if (!trace_stream.is_open()) {
std::cout << "Tracing output file could not be opened." << endl;
@@ -238,14 +247,14 @@ class BattOrAgentBin : public BattOrAgent::Listener {
HandleError(error);
}
- done_.Signal();
+ ui_thread_message_loop_.task_runner()->PostTask(
+ FROM_HERE, ui_thread_run_loop_.QuitClosure());
}
void RecordClockSyncMarker(const std::string& marker) {
io_thread_.task_runner()->PostTask(
FROM_HERE, base::Bind(&BattOrAgent::RecordClockSyncMarker,
base::Unretained(agent_.get()), marker));
- done_.Wait();
}
void OnRecordClockSyncMarkerComplete(BattOrError error) override {
@@ -254,51 +263,46 @@ class BattOrAgentBin : public BattOrAgent::Listener {
else
HandleError(error);
- done_.Signal();
+ PostRunNextCommand();
}
// Postable task for creating the BattOrAgent. Because the BattOrAgent has
// uber thread safe dependencies, all interactions with it, including creating
// and deleting it, MUST happen on the IO thread.
- void CreateAgent(const std::string& path) {
- // In Chrome, we already have file and UI threads running. Because the
- // Chrome serial libraries rely on having those threads available, we have
- // to spin up our own because we're in a separate binary.
+ void CreateAgent(
+ const std::string& path,
+ scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner) {
+ // In Chrome, we already have a file thread running. Because the Chrome
+ // serial library relies on having it available, we have to spin up our own.
if (!file_thread_.Start())
ExitFromThreadStartFailure(kFileThreadName);
- base::Thread::Options ui_thread_options;
- ui_thread_options.message_loop_type = base::MessageLoopForIO::TYPE_UI;
- if (!ui_thread_.StartWithOptions(ui_thread_options)) {
- ExitFromThreadStartFailure(kUiThreadName);
- }
-
agent_.reset(new BattOrAgent(path, this, file_thread_.task_runner(),
- ui_thread_.task_runner()));
- done_.Signal();
+ ui_thread_task_runner));
}
// Postable task for deleting the BattOrAgent. See the comment for
// CreateAgent() above regarding why this is necessary.
- void DeleteAgent() {
- agent_.reset(nullptr);
- done_.Signal();
+ void DeleteAgent(base::WaitableEvent* done) {
+ agent_.reset();
+ done->Signal();
}
private:
- // Event signaled when an async task has finished executing.
- base::WaitableEvent done_;
+ // NOTE: ui_thread_message_loop_ must appear before ui_thread_run_loop_ here
+ // because ui_thread_run_loop_ checks for the current MessageLoop during
+ // initialization.
+ base::MessageLoopForUI ui_thread_message_loop_;
+ base::RunLoop ui_thread_run_loop_;
// Threads needed for serial communication.
base::Thread io_thread_;
base::Thread file_thread_;
- base::Thread ui_thread_;
// The agent capable of asynchronously communicating with the BattOr.
std::unique_ptr<BattOrAgent> agent_;
std::string trace_output_file_;
-
};
} // namespace battor
diff --git a/chromium/tools/battor_agent/battor_agent_unittest.cc b/chromium/tools/battor_agent/battor_agent_unittest.cc
index 3b6c54338a1..008877514f0 100644
--- a/chromium/tools/battor_agent/battor_agent_unittest.cc
+++ b/chromium/tools/battor_agent/battor_agent_unittest.cc
@@ -5,7 +5,7 @@
#include "tools/battor_agent/battor_agent.h"
#include "base/test/test_simple_task_runner.h"
-#include "base/thread_task_runner_handle.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "tools/battor_agent/battor_protocol_types.h"
diff --git a/chromium/tools/battor_agent/battor_connection_impl.cc b/chromium/tools/battor_agent/battor_connection_impl.cc
index cce643a6e18..357ad6c3a99 100644
--- a/chromium/tools/battor_agent/battor_connection_impl.cc
+++ b/chromium/tools/battor_agent/battor_connection_impl.cc
@@ -6,18 +6,26 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
+#include "base/command_line.h"
#include "base/memory/ptr_util.h"
-#include "base/thread_task_runner_handle.h"
+#include "base/strings/stringprintf.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "device/serial/buffer.h"
#include "device/serial/serial_io_handler.h"
#include "net/base/io_buffer.h"
+#include "tools/battor_agent/serial_utils.h"
+using base::StringPrintf;
using std::vector;
namespace battor {
namespace {
+// The command line switch used to specify a file to which serial communication
+// is logged.
+const char kSerialLogPathSwitch[] = "battor-serial-log";
+
// Serial configuration parameters for the BattOr.
const uint32_t kBattOrBitrate = 2000000;
const device::serial::DataBits kBattOrDataBits =
@@ -58,7 +66,15 @@ BattOrConnectionImpl::BattOrConnectionImpl(
: BattOrConnection(listener),
path_(path),
file_thread_task_runner_(file_thread_task_runner),
- ui_thread_task_runner_(ui_thread_task_runner) {}
+ ui_thread_task_runner_(ui_thread_task_runner) {
+ std::string serial_log_path =
+ base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+ kSerialLogPathSwitch);
+ if (!serial_log_path.empty()) {
+ serial_log_.open(serial_log_path.c_str(),
+ std::fstream::out | std::fstream::trunc);
+ }
+}
BattOrConnectionImpl::~BattOrConnectionImpl() {}
@@ -78,11 +94,15 @@ void BattOrConnectionImpl::Open() {
options.cts_flow_control = kBattOrCtsFlowControl;
options.has_cts_flow_control = kBattOrHasCtsFlowControl;
+ LogSerial("Opening serial connection.");
io_handler_->Open(path_, options,
base::Bind(&BattOrConnectionImpl::OnOpened, AsWeakPtr()));
}
void BattOrConnectionImpl::OnOpened(bool success) {
+ LogSerial(StringPrintf("Serial connection open finished with success: %d.",
+ success));
+
if (!success)
Close();
@@ -92,6 +112,7 @@ void BattOrConnectionImpl::OnOpened(bool success) {
}
void BattOrConnectionImpl::Close() {
+ LogSerial("Serial connection closed.");
io_handler_ = nullptr;
}
@@ -119,6 +140,8 @@ void BattOrConnectionImpl::SendBytes(BattOrMessageType type,
data.push_back(BATTOR_CONTROL_BYTE_END);
+ LogSerial(StringPrintf("Bytes sent: %s.", CharVectorToString(data).c_str()));
+
pending_write_length_ = data.size();
io_handler_->Write(base::WrapUnique(new device::SendBuffer(
data, base::Bind(&BattOrConnectionImpl::OnBytesSent, AsWeakPtr()))));
@@ -134,7 +157,9 @@ void BattOrConnectionImpl::ReadMessage(BattOrMessageType type) {
std::unique_ptr<vector<char>> bytes(new vector<char>());
bytes->reserve(max_bytes_to_read);
+ LogSerial("Checking if a complete message is in the 'already read' buffer.");
if (ParseMessage(&parsed_type, bytes.get())) {
+ LogSerial("Complete message found.");
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::Bind(&Listener::OnMessageRead, base::Unretained(listener_), true,
@@ -142,6 +167,7 @@ void BattOrConnectionImpl::ReadMessage(BattOrMessageType type) {
return;
}
+ LogSerial("No complete message found.");
BeginReadBytes(max_bytes_to_read - already_read_buffer_.size());
}
@@ -156,6 +182,9 @@ scoped_refptr<device::SerialIoHandler> BattOrConnectionImpl::CreateIoHandler() {
}
void BattOrConnectionImpl::BeginReadBytes(size_t max_bytes_to_read) {
+ LogSerial(
+ StringPrintf("Starting read of up to %zu bytes.", max_bytes_to_read));
+
pending_read_buffer_ =
make_scoped_refptr(new net::IOBuffer(max_bytes_to_read));
@@ -169,13 +198,25 @@ void BattOrConnectionImpl::BeginReadBytes(size_t max_bytes_to_read) {
void BattOrConnectionImpl::OnBytesRead(int bytes_read,
device::serial::ReceiveError error) {
- if (bytes_read == 0 || error != device::serial::ReceiveError::NONE) {
+ if (error != device::serial::ReceiveError::NONE) {
+ LogSerial(StringPrintf("Read failed with error code: %d.",
+ static_cast<int>(error)));
+ EndReadBytes(false, BATTOR_MESSAGE_TYPE_CONTROL, nullptr);
+ return;
+ }
+
+ if (bytes_read == 0) {
// If we didn't have a message before, and we weren't able to read any
// additional bytes, then there's no valid message available.
+ LogSerial("Read failed due to no bytes being read.");
EndReadBytes(false, BATTOR_MESSAGE_TYPE_CONTROL, nullptr);
return;
}
+ LogSerial(StringPrintf(
+ "%d more bytes read: %s.", bytes_read,
+ CharArrayToString(pending_read_buffer_->data(), bytes_read).c_str()));
+
already_read_buffer_.insert(already_read_buffer_.end(),
pending_read_buffer_->data(),
pending_read_buffer_->data() + bytes_read);
@@ -185,14 +226,14 @@ void BattOrConnectionImpl::OnBytesRead(int bytes_read,
bytes->reserve(GetMaxBytesForMessageType(pending_read_message_type_));
if (!ParseMessage(&type, bytes.get())) {
- // Even after reading the max number of bytes, we still don't have a valid
- // message.
+ LogSerial(
+ "Read failed due to having no complete message after max read length.");
EndReadBytes(false, BATTOR_MESSAGE_TYPE_CONTROL, nullptr);
return;
}
if (type != pending_read_message_type_) {
- // We received a complete message, but it wasn't the type we were expecting.
+ LogSerial("Read failed due to receiving a message of the wrong type.");
EndReadBytes(false, BATTOR_MESSAGE_TYPE_CONTROL, nullptr);
return;
}
@@ -200,10 +241,11 @@ void BattOrConnectionImpl::OnBytesRead(int bytes_read,
EndReadBytes(true, type, std::move(bytes));
}
-void BattOrConnectionImpl::EndReadBytes(
- bool success,
- BattOrMessageType type,
- std::unique_ptr<std::vector<char>> bytes) {
+void BattOrConnectionImpl::EndReadBytes(bool success,
+ BattOrMessageType type,
+ std::unique_ptr<vector<char>> bytes) {
+ LogSerial(StringPrintf("Read finished with success: %d.", success));
+
pending_read_buffer_ = nullptr;
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
@@ -273,4 +315,8 @@ void BattOrConnectionImpl::OnBytesSent(int bytes_sent,
base::Bind(&Listener::OnBytesSent, base::Unretained(listener_), success));
}
+void BattOrConnectionImpl::LogSerial(const std::string& str) {
+ serial_log_ << str << std::endl << std::endl;
+}
+
} // namespace battor
diff --git a/chromium/tools/battor_agent/battor_connection_impl.h b/chromium/tools/battor_agent/battor_connection_impl.h
index e0ce5a20ffa..0631451beda 100644
--- a/chromium/tools/battor_agent/battor_connection_impl.h
+++ b/chromium/tools/battor_agent/battor_connection_impl.h
@@ -5,6 +5,7 @@
#ifndef TOOLS_BATTOR_AGENT_BATTOR_CONNECTION_IMPL_H_
#define TOOLS_BATTOR_AGENT_BATTOR_CONNECTION_IMPL_H_
+#include <fstream>
#include <vector>
#include "base/callback_forward.h"
@@ -75,6 +76,9 @@ class BattOrConnectionImpl
// Internal callback for when bytes are sent.
void OnBytesSent(int bytes_sent, device::serial::SendError error);
+ // Appends |str| to the serial log file if it exists.
+ void LogSerial(const std::string& str);
+
// The path of the BattOr.
std::string path_;
@@ -93,6 +97,8 @@ class BattOrConnectionImpl
scoped_refptr<base::SingleThreadTaskRunner> file_thread_task_runner_;
scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner_;
+ std::fstream serial_log_;
+
DISALLOW_COPY_AND_ASSIGN(BattOrConnectionImpl);
};
diff --git a/chromium/tools/battor_agent/battor_connection_impl_unittest.cc b/chromium/tools/battor_agent/battor_connection_impl_unittest.cc
index 233e7e66db4..4e19ee123c5 100644
--- a/chromium/tools/battor_agent/battor_connection_impl_unittest.cc
+++ b/chromium/tools/battor_agent/battor_connection_impl_unittest.cc
@@ -9,7 +9,7 @@
#include "base/memory/ptr_util.h"
#include "base/memory/weak_ptr.h"
#include "base/test/test_simple_task_runner.h"
-#include "base/thread_task_runner_handle.h"
+#include "base/threading/thread_task_runner_handle.h"
#include "device/serial/serial.mojom.h"
#include "device/serial/test_serial_io_handler.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/tools/battor_agent/battor_protocol_types_unittest.cc b/chromium/tools/battor_agent/battor_protocol_types_unittest.cc
index 46416cdd44b..cdd9ec109a2 100644
--- a/chromium/tools/battor_agent/battor_protocol_types_unittest.cc
+++ b/chromium/tools/battor_agent/battor_protocol_types_unittest.cc
@@ -8,6 +8,7 @@
#include <string>
#include "testing/gtest/include/gtest/gtest.h"
+#include "tools/battor_agent/serial_utils.h"
using namespace testing;
@@ -15,22 +16,6 @@ namespace battor {
namespace {
-// Prints the character array as hex to a comma-separated list.
-std::string CharArrayToFormattedString(const unsigned char* arr,
- size_t length) {
- std::string s;
-
- char num_buff[6];
- for (size_t i = 0; i < length; ++i) {
- // We use sprintf because stringstream's hex support wants to print our
- // characters as signed.
- sprintf(num_buff, "0x%02hhx,", arr[i]);
- s += num_buff;
- }
-
- return s;
-}
-
const BattOrEEPROM kUnserializedEEPROM{
{0, 0, 0, 1}, 2, "serialno", 3, 4, 5, 6, 7, 8, 9, 10, 11,
12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 24,
@@ -55,12 +40,12 @@ TEST(BattOrProtocolTypeTest, EEPROMSerializesCorrectly) {
// the EEPROM will change in the future and we'll need to update the
// serialized version when it does, it makes sense to print the bytes as a
// string that can just be copied and pasted into kSerializedEEPROM.
- const unsigned char* eeprom_bytes =
- reinterpret_cast<const unsigned char*>(&kUnserializedEEPROM);
+ const char* eeprom_bytes =
+ reinterpret_cast<const char*>(&kUnserializedEEPROM);
- ASSERT_EQ(
- CharArrayToFormattedString(kSerializedEEPROM, sizeof(kSerializedEEPROM)),
- CharArrayToFormattedString(eeprom_bytes, sizeof(kUnserializedEEPROM)));
+ ASSERT_EQ(CharArrayToString(reinterpret_cast<const char*>(kSerializedEEPROM),
+ sizeof(kSerializedEEPROM)),
+ CharArrayToString(eeprom_bytes, sizeof(kUnserializedEEPROM)));
}
} // namespace battor
diff --git a/chromium/tools/battor_agent/serial_utils.cc b/chromium/tools/battor_agent/serial_utils.cc
new file mode 100644
index 00000000000..a40a333dac1
--- /dev/null
+++ b/chromium/tools/battor_agent/serial_utils.cc
@@ -0,0 +1,29 @@
+// 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/battor_agent/serial_utils.h"
+
+namespace battor {
+
+std::string CharVectorToString(const std::vector<char> data) {
+ std::string s;
+
+ // Reserve enough bytes for '0x', the two data characters, a space, and a null
+ // terminating byte.
+ char num_buff[6];
+ for (char d : data) {
+ // We use sprintf because stringstream's hex support wants to print our
+ // characters as signed.
+ sprintf(num_buff, "0x%02hhx ", d);
+ s += num_buff;
+ }
+
+ return s.substr(0, s.size() - 1);
+}
+
+std::string CharArrayToString(const char* bytes, size_t len) {
+ return CharVectorToString(std::vector<char>(bytes, bytes + len));
+}
+
+} // namespace battor
diff --git a/chromium/tools/battor_agent/serial_utils.h b/chromium/tools/battor_agent/serial_utils.h
new file mode 100644
index 00000000000..ae1e6cc7944
--- /dev/null
+++ b/chromium/tools/battor_agent/serial_utils.h
@@ -0,0 +1,20 @@
+// 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_BATTOR_AGENT_SERIAL_UTILS_H_
+#define TOOLS_BATTOR_AGENT_SERIAL_UTILS_H_
+
+#include <string>
+#include <vector>
+
+namespace battor {
+
+// Prints |bytes| as a space separated list of hex numbers (e.g. {'A', 'J'}
+// would return "0x41 0x4A").
+std::string CharArrayToString(const char* bytes, size_t len);
+std::string CharVectorToString(const std::vector<char> bytes);
+
+} // namespace battor
+
+#endif // TOOLS_BATTOR_AGENT_SERIAL_UTILS_H_
diff --git a/chromium/tools/battor_agent/serial_utils_unittest.cc b/chromium/tools/battor_agent/serial_utils_unittest.cc
new file mode 100644
index 00000000000..608b52fff2d
--- /dev/null
+++ b/chromium/tools/battor_agent/serial_utils_unittest.cc
@@ -0,0 +1,36 @@
+// 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/battor_agent/serial_utils.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+using namespace testing;
+
+namespace battor {
+
+TEST(SerialUtilsTest, CharVectorToStringLengthZero) {
+ EXPECT_EQ("", CharVectorToString(std::vector<char>()));
+}
+
+TEST(SerialUtilsTest, CharVectorToStringLengthOne) {
+ EXPECT_EQ("0x41", CharVectorToString(std::vector<char>({'A'})));
+}
+
+TEST(SerialUtilsTest, CharVectorToStringLengthTwo) {
+ EXPECT_EQ("0x41 0x4a",
+ CharVectorToString(std::vector<char>({'A', 'J'})));
+}
+
+TEST(SerialUtilsTest, CharArrayToStringLengthOne) {
+ const char arr[] = {'A'};
+ EXPECT_EQ("0x41", CharArrayToString(arr, sizeof(arr)));
+}
+
+TEST(SerialUtilsTest, CharArrayToStringLengthTwo) {
+ const char arr[] = {'A', 'J'};
+ EXPECT_EQ("0x41 0x4a", CharArrayToString(arr, sizeof(arr)));
+}
+
+} // namespace battor
diff --git a/chromium/tools/cfi/blacklist.txt b/chromium/tools/cfi/blacklist.txt
index ab60ab63256..cb0b24f1305 100644
--- a/chromium/tools/cfi/blacklist.txt
+++ b/chromium/tools/cfi/blacklist.txt
@@ -18,22 +18,6 @@ type:*SkBlockComRef*
# https://crbug.com/517959
type:*NoAddRefRelease*
-# All mojo::test:: types.
-# They are loaded from libmojo_public_test_support.so
-# https://crbug.com/515347
-type:mojo::test::*
-
-# All types and sources from libclearkeycdm.so.
-# See https://crbug.com/557969
-type:media::CdmVideoDecoder
-type:media::ClearKeyCdm
-type:media::FakeCdmVideoDecoder
-type:media::FFmpegCdmAudioDecoder
-type:media::FFmpegCdmVideoDecoder
-type:media::LibvpxCdmVideoDecoder
-src:*external_clear_key*
-type:cdm::*
-
# invalid downcasts for IPC messages
# https://crbug.com/520760
src:*nacl_message_scanner.cc*
diff --git a/chromium/tools/checkbins/checkbins.py b/chromium/tools/checkbins/checkbins.py
index 74ed0ae821a..ec955781b0b 100755
--- a/chromium/tools/checkbins/checkbins.py
+++ b/chromium/tools/checkbins/checkbins.py
@@ -31,6 +31,7 @@ MACHINE_TYPE_AMD64 = 0x8664
# Windows guru for advice.
EXCLUDED_FILES = ['chrome_frame_mini_installer.exe',
'mini_installer.exe',
+ 'next_version_mini_installer.exe',
'wow_helper.exe'
]
diff --git a/chromium/tools/checklicenses/checklicenses.py b/chromium/tools/checklicenses/checklicenses.py
index cfd418b2e7f..94611a901da 100755
--- a/chromium/tools/checklicenses/checklicenses.py
+++ b/chromium/tools/checklicenses/checklicenses.py
@@ -37,6 +37,7 @@ WHITELISTED_LICENSES = [
'Apache (v2.0) BSD (2 clause)',
'Apache (v2.0) BSD-like',
'Apache (v2.0) GPL (v2)',
+ 'Apache (v2.0) ISC',
'Apache (v2.0)',
'Apple MIT', # https://fedoraproject.org/wiki/Licensing/Apple_MIT_License
'BSD (2 clause) ISC',
@@ -76,6 +77,7 @@ WHITELISTED_LICENSES = [
'LGPL (v3 or later)',
'MIT/X11 (BSD like) LGPL (v2.1 or later)',
'MIT/X11 (BSD like)',
+ 'MIT/X11 (BSD like) Public domain MIT/X11 (BSD like)',
'MPL (v1.0) LGPL (v2 or later)',
'MPL (v1.1) BSD (3 clause) GPL (v2) LGPL (v2.1 or later)',
'MPL (v1.1) BSD (3 clause) LGPL (v2.1 or later)',
@@ -143,10 +145,10 @@ PATH_SPECIFIC_WHITELISTED_LICENSES = {
'chrome/common/extensions/docs/server2/third_party': [
'UNKNOWN',
],
- 'courgette/third_party/bsdiff_create.cc': [ # http://crbug.com/98095
+ 'courgette/third_party/bsdiff/bsdiff_create.cc': [ # http://crbug.com/98095
'UNKNOWN',
],
- 'courgette/third_party/qsufsort.h': [ # http://crbug.com/98095
+ 'courgette/third_party/bsdiff/qsufsort.h': [ # http://crbug.com/98095
'UNKNOWN',
],
'native_client': [ # http://crbug.com/98099
@@ -184,18 +186,46 @@ PATH_SPECIFIC_WHITELISTED_LICENSES = {
'UNKNOWN',
],
+ # http://crbug.com/603946
+ # https://github.com/google/oauth2client/issues/331
+ # Just imports googleapiclient. Chromite is not shipped.
+ 'third_party/chromite/third_party/apiclient': [
+ 'UNKNOWN',
+ ],
+
+ # http://crbug.com/603946
+ # https://github.com/google/google-api-python-client/issues/216
+ # Apache (v2.0) license. Chromite is not shipped.
+ 'third_party/chromite/third_party/googleapiclient/channel.py': [
+ 'UNKNOWN',
+ ],
+
# http://crbug.com/222828
# http://bugs.python.org/issue17514
'third_party/chromite/third_party/argparse.py': [
'UNKNOWN',
],
+ # http://crbug.com/603939
+ # https://github.com/jcgregorio/httplib2/issues/307
+ # MIT license. Chromite is not shipped.
+ 'third_party/chromite/third_party/httplib2': [
+ 'UNKNOWN',
+ ],
+
# http://crbug.com/326117
# https://bitbucket.org/chrisatlee/poster/issue/21
'third_party/chromite/third_party/poster': [
'UNKNOWN',
],
+ # http://crbug.com/603944
+ # https://github.com/kennethreitz/requests/issues/1610
+ # Apache (v2.0) license. Chromite is not shipped
+ 'third_party/chromite/third_party/requests': [
+ 'UNKNOWN',
+ ],
+
# http://crbug.com/333508
'buildtools/clang_format/script': [
'UNKNOWN',
@@ -346,6 +376,10 @@ PATH_SPECIFIC_WHITELISTED_LICENSES = {
'GPL (v3 or later)',
'UNKNOWN', # http://crbug.com/98123
],
+ 'third_party/flatbuffers': [
+ # https://github.com/google/flatbuffers/issues/3872
+ 'UNKNOWN',
+ ],
'third_party/fontconfig': [
# https://bugs.freedesktop.org/show_bug.cgi?id=73401
'UNKNOWN',
@@ -385,9 +419,6 @@ PATH_SPECIFIC_WHITELISTED_LICENSES = {
'third_party/lcov/contrib/galaxy/genflat.pl': [
'GPL (v2 or later)',
],
- 'third_party/libjingle/source/talk': [ # http://crbug.com/98310
- 'UNKNOWN',
- ],
'third_party/libjpeg_turbo': [ # http://crbug.com/98314
'UNKNOWN',
],
@@ -492,12 +523,14 @@ PATH_SPECIFIC_WHITELISTED_LICENSES = {
'UNKNOWN',
],
+ # https://github.com/google/google-api-python-client/issues/216
# Apache v2.0.
'tools/swarming_client/third_party/googleapiclient': [
'UNKNOWN',
],
# http://crbug.com/334668
+ # https://github.com/jcgregorio/httplib2/issues/307
# MIT license.
'tools/swarming_client/third_party/httplib2': [
'UNKNOWN',
@@ -616,6 +649,25 @@ PATH_SPECIFIC_WHITELISTED_LICENSES = {
# https://sourceforge.net/p/pyserial/feature-requests/35/
'UNKNOWN',
],
+ # Not shipped, GPL license but some header files contain no licensing info.
+ 'third_party/logilab/logilab/astroid': [
+ 'GPL (v2 or later)',
+ # https://github.com/PyCQA/astroid/issues/336
+ 'UNKNOWN',
+ ],
+ # Not shipped, GPL license but some header files contain no licensing info.
+ 'third_party/logilab/logilab/common': [
+ 'GPL (v2 or later)',
+ # Look for email by nednguyen@google.com in May 5th in
+ # https://lists.logilab.org/pipermail/python-projects/
+ 'UNKNOWN',
+ ],
+ # Not shipped, GPL license but some header files contain no licensing info.
+ 'third_party/pylint': [
+ 'GPL (v2 or later)',
+ # https://github.com/PyCQA/pylint/issues/894
+ 'UNKNOWN',
+ ],
}
EXCLUDED_PATHS = [
diff --git a/chromium/tools/chrome_proxy/common/chrome_proxy_measurements.py b/chromium/tools/chrome_proxy/common/chrome_proxy_measurements.py
index 097c3273c1b..21a3f5587c3 100644
--- a/chromium/tools/chrome_proxy/common/chrome_proxy_measurements.py
+++ b/chromium/tools/chrome_proxy/common/chrome_proxy_measurements.py
@@ -67,20 +67,33 @@ class ChromeProxyValidation(page_test.PageTest):
# Value of the extra via header. |None| if no extra via header is expected.
extra_via_header = None
- def __init__(self, restart_after_each_page=False, metrics=None):
+ def __init__(self, restart_after_each_page=False, metrics=None,
+ clear_cache_before_each_run=True):
super(ChromeProxyValidation, self).__init__(
- needs_browser_restart_after_each_page=restart_after_each_page)
+ needs_browser_restart_after_each_page=restart_after_each_page,
+ clear_cache_before_each_run=clear_cache_before_each_run)
self._metrics = metrics
self._page = None
def CustomizeBrowserOptions(self, options):
# Enable the chrome proxy (data reduction proxy).
options.AppendExtraBrowserArgs('--enable-spdy-proxy-auth')
+ self._is_chrome_proxy_enabled = True
+
+ # Disable quic option, otherwise request headers won't be visible.
+ options.AppendExtraBrowserArgs('--disable-quic')
+
+ def DisableChromeProxy(self):
+ self.options.browser_options.extra_browser_args.discard(
+ '--enable-spdy-proxy-auth')
+ self._is_chrome_proxy_enabled = False
def WillNavigateToPage(self, page, tab):
- WaitForViaHeader(tab)
+ if self._is_chrome_proxy_enabled:
+ WaitForViaHeader(tab)
- tab.ClearCache(force=True)
+ if self.clear_cache_before_each_run:
+ tab.ClearCache(force=True)
assert self._metrics
self._metrics.Start(page, tab)
diff --git a/chromium/tools/chrome_proxy/common/inspector_network.py b/chromium/tools/chrome_proxy/common/inspector_network.py
index 051a8fb909d..dee22d37269 100644
--- a/chromium/tools/chrome_proxy/common/inspector_network.py
+++ b/chromium/tools/chrome_proxy/common/inspector_network.py
@@ -158,7 +158,7 @@ class InspectorNetwork(object):
'method': 'Network.clearBrowserCache'
}, timeout)
- def StartMonitoringNetwork(self):
+ def StartMonitoringNetwork(self, timeout=60):
"""Starts monitoring network notifications and recording HTTP responses."""
self.ClearResponseData()
self._inspector_websocket.RegisterDomain(
@@ -167,14 +167,14 @@ class InspectorNetwork(object):
request = {
'method': 'Network.enable'
}
- self._inspector_websocket.SyncRequest(request)
+ self._inspector_websocket.SyncRequest(request, timeout)
- def StopMonitoringNetwork(self):
+ def StopMonitoringNetwork(self, timeout=60):
"""Stops monitoring network notifications and recording HTTP responses."""
request = {
'method': 'Network.disable'
}
- self._inspector_websocket.SyncRequest(request)
+ self._inspector_websocket.SyncRequest(request, timeout)
# There may be queued messages that don't appear until the SyncRequest
# happens. Wait to unregister until after sending the disable command.
self._inspector_websocket.UnregisterDomain('Network')
diff --git a/chromium/tools/chrome_proxy/integration_tests/chrome_proxy_benchmark.py b/chromium/tools/chrome_proxy/integration_tests/chrome_proxy_benchmark.py
index 8129f4dc81e..875e1143f3b 100644
--- a/chromium/tools/chrome_proxy/integration_tests/chrome_proxy_benchmark.py
+++ b/chromium/tools/chrome_proxy/integration_tests/chrome_proxy_benchmark.py
@@ -32,6 +32,28 @@ class ChromeProxyLoFi(ChromeProxyBenchmark):
@benchmark.Disabled(*WEBVIEW_PLATFORMS)
+class ChromeProxyCacheLoFiDisabled(ChromeProxyBenchmark):
+ tag = 'cache_lo_fi_disabled'
+ test = measurements.ChromeProxyCacheLoFiDisabled
+ page_set = pagesets.LoFiCacheStorySet
+
+ @classmethod
+ def Name(cls):
+ return 'chrome_proxy_benchmark.lo_fi.cache_lo_fi_disabled'
+
+
+@benchmark.Disabled(*WEBVIEW_PLATFORMS)
+class ChromeProxyCacheProxyDisabled(ChromeProxyBenchmark):
+ tag = 'cache_proxy_disabled'
+ test = measurements.ChromeProxyCacheProxyDisabled
+ page_set = pagesets.LoFiCacheStorySet
+
+ @classmethod
+ def Name(cls):
+ return 'chrome_proxy_benchmark.lo_fi.cache_proxy_disabled'
+
+
+@benchmark.Disabled(*WEBVIEW_PLATFORMS)
class ChromeProxyPreviewLoFi(ChromeProxyBenchmark):
tag = 'lo_fi_preview'
test = measurements.ChromeProxyLoFiPreview
@@ -285,4 +307,3 @@ class ChromeProxyVideoAudio(benchmark.Benchmark):
@classmethod
def Name(cls):
return 'chrome_proxy_benchmark.video.audio'
-
diff --git a/chromium/tools/chrome_proxy/integration_tests/chrome_proxy_measurements.py b/chromium/tools/chrome_proxy/integration_tests/chrome_proxy_measurements.py
index 2af7ec70b37..c9ce789fca3 100644
--- a/chromium/tools/chrome_proxy/integration_tests/chrome_proxy_measurements.py
+++ b/chromium/tools/chrome_proxy/integration_tests/chrome_proxy_measurements.py
@@ -10,7 +10,7 @@ from common import chrome_proxy_measurements as measurements
from common.chrome_proxy_measurements import ChromeProxyValidation
from integration_tests import chrome_proxy_metrics as metrics
from metrics import loading
-from telemetry.core import exceptions
+from telemetry.core import exceptions, util
from telemetry.page import page_test
@@ -279,6 +279,94 @@ class ChromeProxyLoFi(ChromeProxyValidation):
def AddResults(self, tab, results):
self._metrics.AddResultsForLoFi(tab, results)
+class ChromeProxyCacheLoFiDisabled(ChromeProxyValidation):
+ """
+ Correctness measurement for Lo-Fi placeholder is not loaded from cache when a
+ page is reloaded with LoFi disabled. First a test page is opened with LoFi and
+ chrome proxy enabled. This allows Chrome to cache the LoFi placeholder image.
+ The browser is restarted with LoFi disabled and the same test page is loaded.
+ This second page load should not pick the LoFi placeholder from cache and
+ original image should be loaded. This test should be run with
+ --profile-type=default command line for the same user profile and cache to be
+ used across the two page loads.
+ """
+
+ def __init__(self):
+ super(ChromeProxyCacheLoFiDisabled, self).__init__(
+ restart_after_each_page=True,
+ metrics=metrics.ChromeProxyMetric(),
+ clear_cache_before_each_run=False)
+
+ def AddResults(self, tab, results):
+ self._metrics.AddResultsForLoFiCache(tab, results, self._is_lo_fi_enabled)
+
+ def WillStartBrowser(self, platform):
+ super(ChromeProxyCacheLoFiDisabled, self).WillStartBrowser(platform)
+ if not self._page:
+ # First page load, enable LoFi and chrome proxy.
+ self.options.AppendExtraBrowserArgs(
+ '--data-reduction-proxy-lo-fi=always-on')
+ self._is_lo_fi_enabled = True
+ else:
+ # Second page load, disable LoFi. Chrome proxy is still enabled.
+ self.options.browser_options.extra_browser_args.discard(
+ '--data-reduction-proxy-lo-fi=always-on')
+ self._is_lo_fi_enabled = False
+
+ def WillNavigateToPage(self, page, tab):
+ super(ChromeProxyCacheLoFiDisabled, self).WillNavigateToPage(page, tab)
+ if self._is_lo_fi_enabled:
+ # Clear cache for the first page to pick LoFi image from server.
+ tab.ClearCache(force=True)
+
+ def DidNavigateToPage(self, page, tab):
+ if not self._is_lo_fi_enabled:
+ tab.ExecuteJavaScript('window.location.reload()')
+ util.WaitFor(tab.HasReachedQuiescence, 3)
+
+class ChromeProxyCacheProxyDisabled(ChromeProxyValidation):
+ """
+ Correctness measurement for Lo-Fi placeholder is not loaded from cache when a
+ page is reloaded with data reduction proxy disabled. First a test page is
+ opened with LoFi and chrome proxy enabled. This allows Chrome to cache the
+ LoFi placeholder image. The browser is restarted with chrome proxy disabled
+ and the same test page is loaded. This second page load should not pick the
+ LoFi placeholder from cache and original image should be loaded. This test
+ should be run with --profile-type=default command line for the same user
+ profile and cache to be used across the two page loads.
+ """
+
+ def __init__(self):
+ super(ChromeProxyCacheProxyDisabled, self).__init__(
+ restart_after_each_page=True,
+ metrics=metrics.ChromeProxyMetric(),
+ clear_cache_before_each_run=False)
+
+ def AddResults(self, tab, results):
+ self._metrics.AddResultsForLoFiCache(tab, results,
+ self._is_chrome_proxy_enabled)
+
+ def WillStartBrowser(self, platform):
+ super(ChromeProxyCacheProxyDisabled, self).WillStartBrowser(platform)
+ if not self._page:
+ # First page load, enable LoFi and chrome proxy.
+ self.options.AppendExtraBrowserArgs(
+ '--data-reduction-proxy-lo-fi=always-on')
+ else:
+ # Second page load, disable chrome proxy. LoFi is still enabled.
+ self.DisableChromeProxy()
+
+ def WillNavigateToPage(self, page, tab):
+ super(ChromeProxyCacheProxyDisabled, self).WillNavigateToPage(page, tab)
+ if self._is_chrome_proxy_enabled:
+ # Clear cache for the first page to pick LoFi image from server.
+ tab.ClearCache(force=True)
+
+ def DidNavigateToPage(self, page, tab):
+ if not self._is_chrome_proxy_enabled:
+ tab.ExecuteJavaScript('window.location.reload()')
+ util.WaitFor(tab.HasReachedQuiescence, 3)
+
class ChromeProxyLoFiPreview(ChromeProxyValidation):
"""Correctness measurement for Lo-Fi preview in Chrome-Proxy header."""
diff --git a/chromium/tools/chrome_proxy/integration_tests/chrome_proxy_metrics.py b/chromium/tools/chrome_proxy/integration_tests/chrome_proxy_metrics.py
index 4dd4846f52e..ed543e6cb63 100644
--- a/chromium/tools/chrome_proxy/integration_tests/chrome_proxy_metrics.py
+++ b/chromium/tools/chrome_proxy/integration_tests/chrome_proxy_metrics.py
@@ -256,6 +256,48 @@ class ChromeProxyMetric(network_metrics.NetworkMetric):
results.current_page, 'lo_fi_response', 'count', lo_fi_response_count))
super(ChromeProxyMetric, self).AddResults(tab, results)
+
+ def AddResultsForLoFiCache(self, tab, results, is_lo_fi):
+ request_count = 0
+ response_count = 0
+
+ for resp in self.IterResponses(tab):
+ if not resp.response.url.endswith('png'):
+ continue
+ if not resp.response.request_headers:
+ continue
+
+ if is_lo_fi != resp.HasChromeProxyLoFiRequest():
+ raise ChromeProxyMetricException, (
+ '%s: LoFi %s expected in request header.' % (resp.response.url,
+ '' if is_lo_fi else 'not'))
+ else:
+ request_count += 1
+
+ if is_lo_fi != resp.HasChromeProxyLoFiResponse():
+ raise ChromeProxyMetricException, (
+ '%s: LoFi %s expected in response header.' % (resp.response.url,
+ '' if is_lo_fi else 'not'))
+ else:
+ response_count += 1
+
+ if is_lo_fi != (resp.content_length < 100):
+ raise ChromeProxyMetricException, (
+ 'Image %s is %d bytes. Expecting %s than 100 bytes.' %
+ (resp.response.url, resp.content_length,
+ 'less' if is_lo_fi else 'more'))
+
+ if request_count == 0:
+ raise ChromeProxyMetricException, (
+ 'Expected at least one %s LoFi request, but zero such requests were '
+ 'sent.' % ('' if is_lo_fi else 'non'))
+ if response_count == 0:
+ raise ChromeProxyMetricException, (
+ 'Expected at least one %s LoFi response, but zero such responses '
+ 'were received.' % ('' if is_lo_fi else 'non'))
+
+ super(ChromeProxyMetric, self).AddResults(tab, results)
+
def AddResultsForLoFiPreview(self, tab, results):
lo_fi_preview_request_count = 0
lo_fi_preview_exp_request_count = 0
diff --git a/chromium/tools/chrome_proxy/integration_tests/chrome_proxy_pagesets/lo_fi_cache.py b/chromium/tools/chrome_proxy/integration_tests/chrome_proxy_pagesets/lo_fi_cache.py
new file mode 100644
index 00000000000..2cfa341da19
--- /dev/null
+++ b/chromium/tools/chrome_proxy/integration_tests/chrome_proxy_pagesets/lo_fi_cache.py
@@ -0,0 +1,32 @@
+# 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.
+
+from telemetry.page import page as page_module
+from telemetry import story
+
+
+class LoFiPageCache(page_module.Page):
+ """
+ A test page for the chrome proxy Lo-Fi cache tests.
+ Checks that LoFi placeholder images are not loaded from cache on page reloads
+ when LoFi mode is disabled or data reduction proxy is disabled.
+ """
+
+ def __init__(self, url, page_set):
+ super(LoFiPageCache, self).__init__(url=url, page_set=page_set)
+
+
+class LoFiCacheStorySet(story.StorySet):
+ """ Chrome proxy test sites """
+
+ def __init__(self):
+ super(LoFiCacheStorySet, self).__init__()
+
+ urls_list = [
+ 'http://check.googlezip.net/cacheable/test.html',
+ 'http://check.googlezip.net/cacheable/test.html',
+ ]
+
+ for url in urls_list:
+ self.AddStory(LoFiPageCache(url, self))
diff --git a/chromium/tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp b/chromium/tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp
index b8d0a44573f..d60d73f9d6b 100644
--- a/chromium/tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp
+++ b/chromium/tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp
@@ -29,26 +29,19 @@ class BlinkGCPluginAction : public PluginASTAction {
return llvm::make_unique<BlinkGCPluginConsumer>(instance, options_);
}
- virtual bool ParseArgs(const CompilerInstance& instance,
+ virtual bool ParseArgs(const CompilerInstance&,
const std::vector<std::string>& args) {
- bool parsed = true;
-
- for (size_t i = 0; i < args.size() && parsed; ++i) {
- if (args[i] == "enable-oilpan") {
- options_.enable_oilpan = true;
- } else if (args[i] == "dump-graph") {
+ for (const auto& arg : args) {
+ if (arg == "dump-graph") {
options_.dump_graph = true;
- } else if (args[i] == "warn-raw-ptr") {
- options_.warn_raw_ptr = true;
- } else if (args[i] == "warn-unneeded-finalizer") {
+ } else if (arg == "warn-unneeded-finalizer") {
options_.warn_unneeded_finalizer = true;
} else {
- parsed = false;
- llvm::errs() << "Unknown blink-gc-plugin argument: " << args[i] << "\n";
+ llvm::errs() << "Unknown blink-gc-plugin argument: " << arg << "\n";
+ return false;
}
}
-
- return parsed;
+ return true;
}
private:
diff --git a/chromium/tools/clang/blink_gc_plugin/BlinkGCPluginConsumer.cpp b/chromium/tools/clang/blink_gc_plugin/BlinkGCPluginConsumer.cpp
index 7c90ddd3504..1a32defcc42 100644
--- a/chromium/tools/clang/blink_gc_plugin/BlinkGCPluginConsumer.cpp
+++ b/chromium/tools/clang/blink_gc_plugin/BlinkGCPluginConsumer.cpp
@@ -8,6 +8,9 @@
#include <set>
#include "CheckDispatchVisitor.h"
+#include "CheckFieldsVisitor.h"
+#include "CheckFinalizerVisitor.h"
+#include "CheckGCRootsVisitor.h"
#include "CheckTraceVisitor.h"
#include "CollectVisitor.h"
#include "JsonWriter.h"
@@ -19,136 +22,6 @@ using namespace clang;
namespace {
-const char kClassMustLeftMostlyDeriveGC[] =
- "[blink-gc] Class %0 must derive its GC base in the left-most position.";
-
-const char kClassRequiresTraceMethod[] =
- "[blink-gc] Class %0 requires a trace method.";
-
-const char kBaseRequiresTracing[] =
- "[blink-gc] Base class %0 of derived class %1 requires tracing.";
-
-const char kBaseRequiresTracingNote[] =
- "[blink-gc] Untraced base class %0 declared here:";
-
-const char kFieldsRequireTracing[] =
- "[blink-gc] Class %0 has untraced fields that require tracing.";
-
-const char kFieldRequiresTracingNote[] =
- "[blink-gc] Untraced field %0 declared here:";
-
-const char kClassContainsInvalidFields[] =
- "[blink-gc] Class %0 contains invalid fields.";
-
-const char kClassContainsGCRoot[] =
- "[blink-gc] Class %0 contains GC root in field %1.";
-
-const char kClassRequiresFinalization[] =
- "[blink-gc] Class %0 requires finalization.";
-
-const char kClassDoesNotRequireFinalization[] =
- "[blink-gc] Class %0 may not require finalization.";
-
-const char kFinalizerAccessesFinalizedField[] =
- "[blink-gc] Finalizer %0 accesses potentially finalized field %1.";
-
-const char kFinalizerAccessesEagerlyFinalizedField[] =
- "[blink-gc] Finalizer %0 accesses eagerly finalized field %1.";
-
-const char kRawPtrToGCManagedClassNote[] =
- "[blink-gc] Raw pointer field %0 to a GC managed class declared here:";
-
-const char kRefPtrToGCManagedClassNote[] =
- "[blink-gc] RefPtr field %0 to a GC managed class declared here:";
-
-const char kReferencePtrToGCManagedClassNote[] =
- "[blink-gc] Reference pointer field %0 to a GC managed class"
- " declared here:";
-
-const char kOwnPtrToGCManagedClassNote[] =
- "[blink-gc] OwnPtr field %0 to a GC managed class declared here:";
-
-const char kMemberToGCUnmanagedClassNote[] =
- "[blink-gc] Member field %0 to non-GC managed class declared here:";
-
-const char kStackAllocatedFieldNote[] =
- "[blink-gc] Stack-allocated field %0 declared here:";
-
-const char kMemberInUnmanagedClassNote[] =
- "[blink-gc] Member field %0 in unmanaged class declared here:";
-
-const char kPartObjectToGCDerivedClassNote[] =
- "[blink-gc] Part-object field %0 to a GC derived class declared here:";
-
-const char kPartObjectContainsGCRootNote[] =
- "[blink-gc] Field %0 with embedded GC root in %1 declared here:";
-
-const char kFieldContainsGCRootNote[] =
- "[blink-gc] Field %0 defining a GC root declared here:";
-
-const char kOverriddenNonVirtualTrace[] =
- "[blink-gc] Class %0 overrides non-virtual trace of base class %1.";
-
-const char kOverriddenNonVirtualTraceNote[] =
- "[blink-gc] Non-virtual trace method declared here:";
-
-const char kMissingTraceDispatchMethod[] =
- "[blink-gc] Class %0 is missing manual trace dispatch.";
-
-const char kMissingFinalizeDispatchMethod[] =
- "[blink-gc] Class %0 is missing manual finalize dispatch.";
-
-const char kVirtualAndManualDispatch[] =
- "[blink-gc] Class %0 contains or inherits virtual methods"
- " but implements manual dispatching.";
-
-const char kMissingTraceDispatch[] =
- "[blink-gc] Missing dispatch to class %0 in manual trace dispatch.";
-
-const char kMissingFinalizeDispatch[] =
- "[blink-gc] Missing dispatch to class %0 in manual finalize dispatch.";
-
-const char kFinalizedFieldNote[] =
- "[blink-gc] Potentially finalized field %0 declared here:";
-
-const char kEagerlyFinalizedFieldNote[] =
- "[blink-gc] Field %0 having eagerly finalized value, declared here:";
-
-const char kUserDeclaredDestructorNote[] =
- "[blink-gc] User-declared destructor declared here:";
-
-const char kUserDeclaredFinalizerNote[] =
- "[blink-gc] User-declared finalizer declared here:";
-
-const char kBaseRequiresFinalizationNote[] =
- "[blink-gc] Base class %0 requiring finalization declared here:";
-
-const char kFieldRequiresFinalizationNote[] =
- "[blink-gc] Field %0 requiring finalization declared here:";
-
-const char kManualDispatchMethodNote[] =
- "[blink-gc] Manual dispatch %0 declared here:";
-
-const char kDerivesNonStackAllocated[] =
- "[blink-gc] Stack-allocated class %0 derives class %1"
- " which is not stack allocated.";
-
-const char kClassOverridesNew[] =
- "[blink-gc] Garbage collected class %0"
- " is not permitted to override its new operator.";
-
-const char kClassDeclaresPureVirtualTrace[] =
- "[blink-gc] Garbage collected class %0"
- " is not permitted to declare a pure-virtual trace method.";
-
-const char kLeftMostBaseMustBePolymorphic[] =
- "[blink-gc] Left-most base class %0 of derived class %1"
- " must be polymorphic.";
-
-const char kBaseClassMustDeclareVirtualTrace[] =
- "[blink-gc] Left-most base class %0 of derived class %1"
- " must define a virtual trace method.";
-
// Use a local RAV implementation to simply collect all FunctionDecls marked for
// late template parsing. This happens with the flag -fdelayed-template-parsing,
// which is on by default in MSVC-compatible mode.
@@ -193,7 +66,7 @@ BlinkGCPluginConsumer::BlinkGCPluginConsumer(
clang::CompilerInstance& instance,
const BlinkGCPluginOptions& options)
: instance_(instance),
- diagnostic_(instance.getDiagnostics()),
+ reporter_(instance),
options_(options),
json_(0) {
// Only check structures in the blink and WebKit namespaces.
@@ -201,99 +74,11 @@ BlinkGCPluginConsumer::BlinkGCPluginConsumer(
// Ignore GC implementation files.
options_.ignored_directories.push_back("/heap/");
-
- // Register warning/error messages.
- diag_class_must_left_mostly_derive_gc_ = diagnostic_.getCustomDiagID(
- getErrorLevel(), kClassMustLeftMostlyDeriveGC);
- diag_class_requires_trace_method_ =
- diagnostic_.getCustomDiagID(getErrorLevel(), kClassRequiresTraceMethod);
- diag_base_requires_tracing_ =
- diagnostic_.getCustomDiagID(getErrorLevel(), kBaseRequiresTracing);
- diag_fields_require_tracing_ =
- diagnostic_.getCustomDiagID(getErrorLevel(), kFieldsRequireTracing);
- diag_class_contains_invalid_fields_ = diagnostic_.getCustomDiagID(
- getErrorLevel(), kClassContainsInvalidFields);
- diag_class_contains_invalid_fields_warning_ = diagnostic_.getCustomDiagID(
- getErrorLevel(), kClassContainsInvalidFields);
- diag_class_contains_gc_root_ =
- diagnostic_.getCustomDiagID(getErrorLevel(), kClassContainsGCRoot);
- diag_class_requires_finalization_ = diagnostic_.getCustomDiagID(
- getErrorLevel(), kClassRequiresFinalization);
- diag_class_does_not_require_finalization_ = diagnostic_.getCustomDiagID(
- DiagnosticsEngine::Warning, kClassDoesNotRequireFinalization);
- diag_finalizer_accesses_finalized_field_ = diagnostic_.getCustomDiagID(
- getErrorLevel(), kFinalizerAccessesFinalizedField);
- diag_finalizer_eagerly_finalized_field_ = diagnostic_.getCustomDiagID(
- getErrorLevel(), kFinalizerAccessesEagerlyFinalizedField);
- diag_overridden_non_virtual_trace_ = diagnostic_.getCustomDiagID(
- getErrorLevel(), kOverriddenNonVirtualTrace);
- diag_missing_trace_dispatch_method_ = diagnostic_.getCustomDiagID(
- getErrorLevel(), kMissingTraceDispatchMethod);
- diag_missing_finalize_dispatch_method_ = diagnostic_.getCustomDiagID(
- getErrorLevel(), kMissingFinalizeDispatchMethod);
- diag_virtual_and_manual_dispatch_ =
- diagnostic_.getCustomDiagID(getErrorLevel(), kVirtualAndManualDispatch);
- diag_missing_trace_dispatch_ =
- diagnostic_.getCustomDiagID(getErrorLevel(), kMissingTraceDispatch);
- diag_missing_finalize_dispatch_ =
- diagnostic_.getCustomDiagID(getErrorLevel(), kMissingFinalizeDispatch);
- diag_derives_non_stack_allocated_ =
- diagnostic_.getCustomDiagID(getErrorLevel(), kDerivesNonStackAllocated);
- diag_class_overrides_new_ =
- diagnostic_.getCustomDiagID(getErrorLevel(), kClassOverridesNew);
- diag_class_declares_pure_virtual_trace_ = diagnostic_.getCustomDiagID(
- getErrorLevel(), kClassDeclaresPureVirtualTrace);
- diag_left_most_base_must_be_polymorphic_ = diagnostic_.getCustomDiagID(
- getErrorLevel(), kLeftMostBaseMustBePolymorphic);
- diag_base_class_must_declare_virtual_trace_ = diagnostic_.getCustomDiagID(
- getErrorLevel(), kBaseClassMustDeclareVirtualTrace);
-
- // Register note messages.
- diag_base_requires_tracing_note_ = diagnostic_.getCustomDiagID(
- DiagnosticsEngine::Note, kBaseRequiresTracingNote);
- diag_field_requires_tracing_note_ = diagnostic_.getCustomDiagID(
- DiagnosticsEngine::Note, kFieldRequiresTracingNote);
- diag_raw_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID(
- DiagnosticsEngine::Note, kRawPtrToGCManagedClassNote);
- diag_ref_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID(
- DiagnosticsEngine::Note, kRefPtrToGCManagedClassNote);
- diag_reference_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID(
- DiagnosticsEngine::Note, kReferencePtrToGCManagedClassNote);
- diag_own_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID(
- DiagnosticsEngine::Note, kOwnPtrToGCManagedClassNote);
- diag_member_to_gc_unmanaged_class_note_ = diagnostic_.getCustomDiagID(
- DiagnosticsEngine::Note, kMemberToGCUnmanagedClassNote);
- diag_stack_allocated_field_note_ = diagnostic_.getCustomDiagID(
- DiagnosticsEngine::Note, kStackAllocatedFieldNote);
- diag_member_in_unmanaged_class_note_ = diagnostic_.getCustomDiagID(
- DiagnosticsEngine::Note, kMemberInUnmanagedClassNote);
- diag_part_object_to_gc_derived_class_note_ = diagnostic_.getCustomDiagID(
- DiagnosticsEngine::Note, kPartObjectToGCDerivedClassNote);
- diag_part_object_contains_gc_root_note_ = diagnostic_.getCustomDiagID(
- DiagnosticsEngine::Note, kPartObjectContainsGCRootNote);
- diag_field_contains_gc_root_note_ = diagnostic_.getCustomDiagID(
- DiagnosticsEngine::Note, kFieldContainsGCRootNote);
- diag_finalized_field_note_ = diagnostic_.getCustomDiagID(
- DiagnosticsEngine::Note, kFinalizedFieldNote);
- diag_eagerly_finalized_field_note_ = diagnostic_.getCustomDiagID(
- DiagnosticsEngine::Note, kEagerlyFinalizedFieldNote);
- diag_user_declared_destructor_note_ = diagnostic_.getCustomDiagID(
- DiagnosticsEngine::Note, kUserDeclaredDestructorNote);
- diag_user_declared_finalizer_note_ = diagnostic_.getCustomDiagID(
- DiagnosticsEngine::Note, kUserDeclaredFinalizerNote);
- diag_base_requires_finalization_note_ = diagnostic_.getCustomDiagID(
- DiagnosticsEngine::Note, kBaseRequiresFinalizationNote);
- diag_field_requires_finalization_note_ = diagnostic_.getCustomDiagID(
- DiagnosticsEngine::Note, kFieldRequiresFinalizationNote);
- diag_overridden_non_virtual_trace_note_ = diagnostic_.getCustomDiagID(
- DiagnosticsEngine::Note, kOverriddenNonVirtualTraceNote);
- diag_manual_dispatch_method_note_ = diagnostic_.getCustomDiagID(
- DiagnosticsEngine::Note, kManualDispatchMethodNote);
}
void BlinkGCPluginConsumer::HandleTranslationUnit(ASTContext& context) {
// Don't run the plugin if the compilation unit is already invalid.
- if (diagnostic_.hasErrorOccurred())
+ if (reporter_.hasErrorOccurred())
return;
ParseFunctionTemplates(context.getTranslationUnitDecl());
@@ -395,14 +180,14 @@ void BlinkGCPluginConsumer::CheckClass(RecordInfo* info) {
if (info->IsStackAllocated()) {
for (auto& base : info->GetBases())
if (!base.second.info()->IsStackAllocated())
- ReportDerivesNonStackAllocated(info, &base.second);
+ reporter_.DerivesNonStackAllocated(info, &base.second);
}
if (CXXMethodDecl* trace = info->GetTraceMethod()) {
if (trace->isPure())
- ReportClassDeclaresPureVirtualTrace(info, trace);
+ reporter_.ClassDeclaresPureVirtualTrace(info, trace);
} else if (info->RequiresTraceMethod()) {
- ReportClassRequiresTraceMethod(info);
+ reporter_.ClassRequiresTraceMethod(info);
}
// Check polymorphic classes that are GC-derived or have a trace method.
@@ -414,9 +199,9 @@ void BlinkGCPluginConsumer::CheckClass(RecordInfo* info) {
}
{
- CheckFieldsVisitor visitor(options_);
+ CheckFieldsVisitor visitor;
if (visitor.ContainsInvalidFields(info))
- ReportClassContainsInvalidFields(info, visitor.invalid_fields());
+ reporter_.ClassContainsInvalidFields(info, visitor.invalid_fields());
}
if (info->IsGCDerived()) {
@@ -425,13 +210,13 @@ void BlinkGCPluginConsumer::CheckClass(RecordInfo* info) {
CheckDispatch(info);
if (CXXMethodDecl* newop = info->DeclaresNewOperator())
if (!Config::IsIgnoreAnnotated(newop))
- ReportClassOverridesNew(info, newop);
+ reporter_.ClassOverridesNew(info, newop);
}
{
CheckGCRootsVisitor visitor;
if (visitor.ContainsGCRoots(info))
- ReportClassContainsGCRoots(info, visitor.gc_roots());
+ reporter_.ClassContainsGCRoots(info, visitor.gc_roots());
}
if (info->NeedsFinalization())
@@ -515,7 +300,7 @@ void BlinkGCPluginConsumer::CheckPolymorphicClass(
if (trace->isVirtual())
return;
}
- ReportBaseClassMustDeclareVirtualTrace(info, left_most);
+ reporter_.BaseClassMustDeclareVirtualTrace(info, left_most);
return;
}
@@ -531,13 +316,13 @@ void BlinkGCPluginConsumer::CheckPolymorphicClass(
if (CXXRecordDecl* next_left_most = GetLeftMostBase(next_base)) {
if (DeclaresVirtualMethods(next_left_most))
return;
- ReportLeftMostBaseMustBePolymorphic(info, next_left_most);
+ reporter_.LeftMostBaseMustBePolymorphic(info, next_left_most);
return;
}
}
}
}
- ReportLeftMostBaseMustBePolymorphic(info, left_most);
+ reporter_.LeftMostBaseMustBePolymorphic(info, left_most);
}
}
@@ -569,7 +354,7 @@ void BlinkGCPluginConsumer::CheckLeftMostDerived(RecordInfo* info) {
if (!left_most)
return;
if (!Config::IsGCBase(left_most->getName()))
- ReportClassMustLeftMostlyDeriveGC(info);
+ reporter_.ClassMustLeftMostlyDeriveGC(info);
}
void BlinkGCPluginConsumer::CheckDispatch(RecordInfo* info) {
@@ -585,18 +370,18 @@ void BlinkGCPluginConsumer::CheckDispatch(RecordInfo* info) {
// Check that dispatch methods are defined at the base.
if (base == info->record()) {
if (!trace_dispatch)
- ReportMissingTraceDispatchMethod(info);
+ reporter_.MissingTraceDispatchMethod(info);
if (finalized && !finalize_dispatch)
- ReportMissingFinalizeDispatchMethod(info);
+ reporter_.MissingFinalizeDispatchMethod(info);
if (!finalized && finalize_dispatch) {
- ReportClassRequiresFinalization(info);
- NoteUserDeclaredFinalizer(finalize_dispatch);
+ reporter_.ClassRequiresFinalization(info);
+ reporter_.NoteUserDeclaredFinalizer(finalize_dispatch);
}
}
// Check that classes implementing manual dispatch do not have vtables.
if (info->record()->isPolymorphic()) {
- ReportVirtualAndManualDispatch(
+ reporter_.VirtualAndManualDispatch(
info, trace_dispatch ? trace_dispatch : finalize_dispatch);
}
@@ -612,14 +397,14 @@ void BlinkGCPluginConsumer::CheckDispatch(RecordInfo* info) {
CheckDispatchVisitor visitor(info);
visitor.TraverseStmt(defn->getBody());
if (!visitor.dispatched_to_receiver())
- ReportMissingTraceDispatch(defn, info);
+ reporter_.MissingTraceDispatch(defn, info);
}
if (finalized && finalize_dispatch && finalize_dispatch->isDefined(defn)) {
CheckDispatchVisitor visitor(info);
visitor.TraverseStmt(defn->getBody());
if (!visitor.dispatched_to_receiver())
- ReportMissingFinalizeDispatch(defn, info);
+ reporter_.MissingFinalizeDispatch(defn, info);
}
}
@@ -633,7 +418,7 @@ void BlinkGCPluginConsumer::CheckFinalization(RecordInfo* info) {
CheckFinalizerVisitor visitor(&cache_, info->IsEagerlyFinalized());
visitor.TraverseCXXMethodDecl(dtor);
if (!visitor.finalized_fields().empty()) {
- ReportFinalizerAccessesFinalizedFields(
+ reporter_.FinalizerAccessesFinalizedFields(
dtor, visitor.finalized_fields());
}
}
@@ -646,31 +431,57 @@ void BlinkGCPluginConsumer::CheckFinalization(RecordInfo* info) {
// Report the finalization error, and proceed to print possible causes for
// the finalization requirement.
- ReportClassRequiresFinalization(info);
+ reporter_.ClassRequiresFinalization(info);
if (dtor && dtor->isUserProvided())
- NoteUserDeclaredDestructor(dtor);
+ reporter_.NoteUserDeclaredDestructor(dtor);
for (auto& base : info->GetBases())
if (base.second.info()->NeedsFinalization())
- NoteBaseRequiresFinalization(&base.second);
+ reporter_.NoteBaseRequiresFinalization(&base.second);
for (auto& field : info->GetFields())
if (field.second.edge()->NeedsFinalization())
- NoteField(&field.second, diag_field_requires_finalization_note_);
+ reporter_.NoteFieldRequiresFinalization(&field.second);
}
void BlinkGCPluginConsumer::CheckUnneededFinalization(RecordInfo* info) {
if (!HasNonEmptyFinalizer(info))
- ReportClassDoesNotRequireFinalization(info);
+ reporter_.ClassDoesNotRequireFinalization(info);
}
bool BlinkGCPluginConsumer::HasNonEmptyFinalizer(RecordInfo* info) {
CXXDestructorDecl* dtor = info->record()->getDestructor();
+
+ // If the destructor is virtual (or one of the bases are by way of the
+ // recursive call below), consider this class as having a non-empty
+ // finalizer. Not doing so runs counter to standard C++ reflexes like
+ //
+ // class A : public GarbageCollectedMixin {
+ // public:
+ // virtual ~A() { };
+ // virtual void f() = 0;
+ // };
+ // class B : public GarbageCollectedFinalized<B>, public A {
+ // USING_GARBAGE_COLLECTED_MIXIN(B);
+ // public:
+ // ~B() override { }
+ // void f() override { }
+ // };
+ //
+ // and it is considered a step too far to report a warning for such
+ // explicit usage of empty destructors.
+ if (dtor && dtor->isVirtual())
+ return true;
+
if (dtor && dtor->isUserProvided()) {
if (!dtor->hasBody() || !EmptyStmtVisitor::isEmpty(dtor->getBody()))
return true;
}
+
+ if (info->GetFinalizeDispatchMethod())
+ return true;
+
for (auto& base : info->GetBases())
if (HasNonEmptyFinalizer(base.second.info()))
return true;
@@ -724,7 +535,7 @@ void BlinkGCPluginConsumer::CheckTraceMethod(
if (trace_type == Config::TRACE_METHOD) {
for (auto& base : parent->GetBases())
if (CXXMethodDecl* other = base.second.info()->InheritsNonVirtualTrace())
- ReportOverriddenNonVirtualTrace(parent, trace, other);
+ reporter_.OverriddenNonVirtualTrace(parent, trace, other);
}
CheckTraceVisitor visitor(trace, parent, &cache_);
@@ -738,12 +549,12 @@ void BlinkGCPluginConsumer::CheckTraceMethod(
for (auto& base : parent->GetBases())
if (!base.second.IsProperlyTraced())
- ReportBaseRequiresTracing(parent, trace, base.first);
+ reporter_.BaseRequiresTracing(parent, trace, base.first);
for (auto& field : parent->GetFields()) {
if (!field.second.IsProperlyTraced()) {
// Discontinue once an untraced-field error is found.
- ReportFieldsRequireTracing(parent, trace);
+ reporter_.FieldsRequireTracing(parent, trace);
break;
}
}
@@ -834,11 +645,6 @@ void BlinkGCPluginConsumer::DumpClass(RecordInfo* info) {
GetLocString(field.second.field()->getLocStart()));
}
-DiagnosticsEngine::Level BlinkGCPluginConsumer::getErrorLevel() {
- return diagnostic_.getWarningsAsErrors() ? DiagnosticsEngine::Error
- : DiagnosticsEngine::Warning;
-}
-
std::string BlinkGCPluginConsumer::GetLocString(SourceLocation loc) {
const SourceManager& source_manager = instance_.getSourceManager();
PresumedLoc ploc = source_manager.getPresumedLoc(loc);
@@ -913,289 +719,3 @@ bool BlinkGCPluginConsumer::GetFilename(SourceLocation loc,
*filename = ploc.getFilename();
return true;
}
-
-DiagnosticBuilder BlinkGCPluginConsumer::ReportDiagnostic(
- SourceLocation location,
- unsigned diag_id) {
- SourceManager& manager = instance_.getSourceManager();
- FullSourceLoc full_loc(location, manager);
- return diagnostic_.Report(full_loc, diag_id);
-}
-
-void BlinkGCPluginConsumer::ReportClassMustLeftMostlyDeriveGC(
- RecordInfo* info) {
- ReportDiagnostic(info->record()->getInnerLocStart(),
- diag_class_must_left_mostly_derive_gc_)
- << info->record();
-}
-
-void BlinkGCPluginConsumer::ReportClassRequiresTraceMethod(RecordInfo* info) {
- ReportDiagnostic(info->record()->getInnerLocStart(),
- diag_class_requires_trace_method_)
- << info->record();
-
- for (auto& base : info->GetBases())
- if (base.second.NeedsTracing().IsNeeded())
- NoteBaseRequiresTracing(&base.second);
-
- for (auto& field : info->GetFields())
- if (!field.second.IsProperlyTraced())
- NoteFieldRequiresTracing(info, field.first);
-}
-
-void BlinkGCPluginConsumer::ReportBaseRequiresTracing(
- RecordInfo* derived,
- CXXMethodDecl* trace,
- CXXRecordDecl* base) {
- ReportDiagnostic(trace->getLocStart(), diag_base_requires_tracing_)
- << base << derived->record();
-}
-
-void BlinkGCPluginConsumer::ReportFieldsRequireTracing(
- RecordInfo* info,
- CXXMethodDecl* trace) {
- ReportDiagnostic(trace->getLocStart(), diag_fields_require_tracing_)
- << info->record();
- for (auto& field : info->GetFields())
- if (!field.second.IsProperlyTraced())
- NoteFieldRequiresTracing(info, field.first);
-}
-
-void BlinkGCPluginConsumer::ReportClassContainsInvalidFields(
- RecordInfo* info,
- const CheckFieldsVisitor::Errors& errors) {
- bool only_warnings = options_.warn_raw_ptr;
- for (auto& error : errors)
- if (!CheckFieldsVisitor::IsWarning(error.second))
- only_warnings = false;
-
- ReportDiagnostic(info->record()->getLocStart(),
- only_warnings ?
- diag_class_contains_invalid_fields_warning_ :
- diag_class_contains_invalid_fields_)
- << info->record();
-
- for (auto& error : errors) {
- unsigned note;
- if (CheckFieldsVisitor::IsRawPtrError(error.second)) {
- note = diag_raw_ptr_to_gc_managed_class_note_;
- } else if (CheckFieldsVisitor::IsReferencePtrError(error.second)) {
- note = diag_reference_ptr_to_gc_managed_class_note_;
- } else if (error.second == CheckFieldsVisitor::kRefPtrToGCManaged) {
- note = diag_ref_ptr_to_gc_managed_class_note_;
- } else if (error.second == CheckFieldsVisitor::kOwnPtrToGCManaged) {
- note = diag_own_ptr_to_gc_managed_class_note_;
- } else if (error.second == CheckFieldsVisitor::kMemberToGCUnmanaged) {
- note = diag_member_to_gc_unmanaged_class_note_;
- } else if (error.second == CheckFieldsVisitor::kMemberInUnmanaged) {
- note = diag_member_in_unmanaged_class_note_;
- } else if (error.second == CheckFieldsVisitor::kPtrFromHeapToStack) {
- note = diag_stack_allocated_field_note_;
- } else if (error.second == CheckFieldsVisitor::kGCDerivedPartObject) {
- note = diag_part_object_to_gc_derived_class_note_;
- } else {
- assert(false && "Unknown field error");
- }
- NoteField(error.first, note);
- }
-}
-
-void BlinkGCPluginConsumer::ReportClassContainsGCRoots(
- RecordInfo* info,
- const CheckGCRootsVisitor::Errors& errors) {
- for (auto& error : errors) {
- FieldPoint* point = nullptr;
- for (FieldPoint* path : error) {
- if (!point) {
- point = path;
- ReportDiagnostic(info->record()->getLocStart(),
- diag_class_contains_gc_root_)
- << info->record() << point->field();
- continue;
- }
- NotePartObjectContainsGCRoot(point);
- point = path;
- }
- NoteFieldContainsGCRoot(point);
- }
-}
-
-void BlinkGCPluginConsumer::ReportFinalizerAccessesFinalizedFields(
- CXXMethodDecl* dtor,
- const CheckFinalizerVisitor::Errors& errors) {
- for (auto& error : errors) {
- bool as_eagerly_finalized = error.as_eagerly_finalized;
- unsigned diag_error = as_eagerly_finalized ?
- diag_finalizer_eagerly_finalized_field_ :
- diag_finalizer_accesses_finalized_field_;
- unsigned diag_note = as_eagerly_finalized ?
- diag_eagerly_finalized_field_note_ :
- diag_finalized_field_note_;
- ReportDiagnostic(error.member->getLocStart(), diag_error)
- << dtor << error.field->field();
- NoteField(error.field, diag_note);
- }
-}
-
-void BlinkGCPluginConsumer::ReportClassRequiresFinalization(RecordInfo* info) {
- ReportDiagnostic(info->record()->getInnerLocStart(),
- diag_class_requires_finalization_)
- << info->record();
-}
-
-void BlinkGCPluginConsumer::ReportClassDoesNotRequireFinalization(
- RecordInfo* info) {
- ReportDiagnostic(info->record()->getInnerLocStart(),
- diag_class_does_not_require_finalization_)
- << info->record();
-}
-
-void BlinkGCPluginConsumer::ReportOverriddenNonVirtualTrace(
- RecordInfo* info,
- CXXMethodDecl* trace,
- CXXMethodDecl* overridden) {
- ReportDiagnostic(trace->getLocStart(), diag_overridden_non_virtual_trace_)
- << info->record() << overridden->getParent();
- NoteOverriddenNonVirtualTrace(overridden);
-}
-
-void BlinkGCPluginConsumer::ReportMissingTraceDispatchMethod(RecordInfo* info) {
- ReportMissingDispatchMethod(info, diag_missing_trace_dispatch_method_);
-}
-
-void BlinkGCPluginConsumer::ReportMissingFinalizeDispatchMethod(
- RecordInfo* info) {
- ReportMissingDispatchMethod(info, diag_missing_finalize_dispatch_method_);
-}
-
-void BlinkGCPluginConsumer::ReportMissingDispatchMethod(
- RecordInfo* info,
- unsigned error) {
- ReportDiagnostic(info->record()->getInnerLocStart(), error)
- << info->record();
-}
-
-void BlinkGCPluginConsumer::ReportVirtualAndManualDispatch(
- RecordInfo* info,
- CXXMethodDecl* dispatch) {
- ReportDiagnostic(info->record()->getInnerLocStart(),
- diag_virtual_and_manual_dispatch_)
- << info->record();
- NoteManualDispatchMethod(dispatch);
-}
-
-void BlinkGCPluginConsumer::ReportMissingTraceDispatch(
- const FunctionDecl* dispatch,
- RecordInfo* receiver) {
- ReportMissingDispatch(dispatch, receiver, diag_missing_trace_dispatch_);
-}
-
-void BlinkGCPluginConsumer::ReportMissingFinalizeDispatch(
- const FunctionDecl* dispatch,
- RecordInfo* receiver) {
- ReportMissingDispatch(dispatch, receiver, diag_missing_finalize_dispatch_);
-}
-
-void BlinkGCPluginConsumer::ReportMissingDispatch(
- const FunctionDecl* dispatch,
- RecordInfo* receiver,
- unsigned error) {
- ReportDiagnostic(dispatch->getLocStart(), error) << receiver->record();
-}
-
-void BlinkGCPluginConsumer::ReportDerivesNonStackAllocated(
- RecordInfo* info,
- BasePoint* base) {
- ReportDiagnostic(base->spec().getLocStart(),
- diag_derives_non_stack_allocated_)
- << info->record() << base->info()->record();
-}
-
-void BlinkGCPluginConsumer::ReportClassOverridesNew(
- RecordInfo* info,
- CXXMethodDecl* newop) {
- ReportDiagnostic(newop->getLocStart(), diag_class_overrides_new_)
- << info->record();
-}
-
-void BlinkGCPluginConsumer::ReportClassDeclaresPureVirtualTrace(
- RecordInfo* info,
- CXXMethodDecl* trace) {
- ReportDiagnostic(trace->getLocStart(),
- diag_class_declares_pure_virtual_trace_)
- << info->record();
-}
-
-void BlinkGCPluginConsumer::ReportLeftMostBaseMustBePolymorphic(
- RecordInfo* derived,
- CXXRecordDecl* base) {
- ReportDiagnostic(base->getLocStart(),
- diag_left_most_base_must_be_polymorphic_)
- << base << derived->record();
-}
-
-void BlinkGCPluginConsumer::ReportBaseClassMustDeclareVirtualTrace(
- RecordInfo* derived,
- CXXRecordDecl* base) {
- ReportDiagnostic(base->getLocStart(),
- diag_base_class_must_declare_virtual_trace_)
- << base << derived->record();
-}
-
-void BlinkGCPluginConsumer::NoteManualDispatchMethod(CXXMethodDecl* dispatch) {
- ReportDiagnostic(dispatch->getLocStart(),
- diag_manual_dispatch_method_note_)
- << dispatch;
-}
-
-void BlinkGCPluginConsumer::NoteBaseRequiresTracing(BasePoint* base) {
- ReportDiagnostic(base->spec().getLocStart(),
- diag_base_requires_tracing_note_)
- << base->info()->record();
-}
-
-void BlinkGCPluginConsumer::NoteFieldRequiresTracing(
- RecordInfo* holder,
- FieldDecl* field) {
- NoteField(field, diag_field_requires_tracing_note_);
-}
-
-void BlinkGCPluginConsumer::NotePartObjectContainsGCRoot(FieldPoint* point) {
- FieldDecl* field = point->field();
- ReportDiagnostic(field->getLocStart(),
- diag_part_object_contains_gc_root_note_)
- << field << field->getParent();
-}
-
-void BlinkGCPluginConsumer::NoteFieldContainsGCRoot(FieldPoint* point) {
- NoteField(point, diag_field_contains_gc_root_note_);
-}
-
-void BlinkGCPluginConsumer::NoteUserDeclaredDestructor(CXXMethodDecl* dtor) {
- ReportDiagnostic(dtor->getLocStart(), diag_user_declared_destructor_note_);
-}
-
-void BlinkGCPluginConsumer::NoteUserDeclaredFinalizer(CXXMethodDecl* dtor) {
- ReportDiagnostic(dtor->getLocStart(), diag_user_declared_finalizer_note_);
-}
-
-void BlinkGCPluginConsumer::NoteBaseRequiresFinalization(BasePoint* base) {
- ReportDiagnostic(base->spec().getLocStart(),
- diag_base_requires_finalization_note_)
- << base->info()->record();
-}
-
-void BlinkGCPluginConsumer::NoteField(FieldPoint* point, unsigned note) {
- NoteField(point->field(), note);
-}
-
-void BlinkGCPluginConsumer::NoteField(FieldDecl* field, unsigned note) {
- ReportDiagnostic(field->getLocStart(), note) << field;
-}
-
-void BlinkGCPluginConsumer::NoteOverriddenNonVirtualTrace(
- CXXMethodDecl* overridden) {
- ReportDiagnostic(overridden->getLocStart(),
- diag_overridden_non_virtual_trace_note_)
- << overridden;
-}
diff --git a/chromium/tools/clang/blink_gc_plugin/BlinkGCPluginConsumer.h b/chromium/tools/clang/blink_gc_plugin/BlinkGCPluginConsumer.h
index d0b49d89bf2..bcfb3afbd59 100644
--- a/chromium/tools/clang/blink_gc_plugin/BlinkGCPluginConsumer.h
+++ b/chromium/tools/clang/blink_gc_plugin/BlinkGCPluginConsumer.h
@@ -8,10 +8,8 @@
#include <string>
#include "BlinkGCPluginOptions.h"
-#include "CheckFieldsVisitor.h"
-#include "CheckFinalizerVisitor.h"
-#include "CheckGCRootsVisitor.h"
#include "Config.h"
+#include "DiagnosticsReporter.h"
#include "clang/AST/AST.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/Basic/Diagnostic.h"
@@ -75,7 +73,7 @@ class BlinkGCPluginConsumer : public clang::ASTConsumer {
std::string GetLocString(clang::SourceLocation loc);
- bool IsIgnored(RecordInfo* record);
+ bool IsIgnored(RecordInfo* info);
bool IsIgnoredClass(RecordInfo* info);
@@ -85,113 +83,11 @@ class BlinkGCPluginConsumer : public clang::ASTConsumer {
bool GetFilename(clang::SourceLocation loc, std::string* filename);
- clang::DiagnosticBuilder ReportDiagnostic(
- clang::SourceLocation location,
- unsigned diag_id);
-
- void ReportClassMustLeftMostlyDeriveGC(RecordInfo* info);
- void ReportClassRequiresTraceMethod(RecordInfo* info);
- void ReportBaseRequiresTracing(RecordInfo* derived,
- clang::CXXMethodDecl* trace,
- clang::CXXRecordDecl* base);
- void ReportFieldsRequireTracing(RecordInfo* info,
- clang::CXXMethodDecl* trace);
- void ReportClassContainsInvalidFields(
- RecordInfo* info,
- const CheckFieldsVisitor::Errors& errors);
- void ReportClassContainsGCRoots(RecordInfo* info,
- const CheckGCRootsVisitor::Errors& errors);
- void ReportFinalizerAccessesFinalizedFields(
- clang::CXXMethodDecl* dtor,
- const CheckFinalizerVisitor::Errors& errors);
- void ReportClassRequiresFinalization(RecordInfo* info);
- void ReportClassDoesNotRequireFinalization(RecordInfo* info);
- void ReportClassMustDeclareGCMixinTraceMethod(RecordInfo* info);
- void ReportOverriddenNonVirtualTrace(RecordInfo* info,
- clang::CXXMethodDecl* trace,
- clang::CXXMethodDecl* overridden);
- void ReportMissingTraceDispatchMethod(RecordInfo* info);
- void ReportMissingFinalizeDispatchMethod(RecordInfo* info);
- void ReportMissingDispatchMethod(RecordInfo* info, unsigned error);
- void ReportVirtualAndManualDispatch(RecordInfo* info,
- clang::CXXMethodDecl* dispatch);
- void ReportMissingTraceDispatch(const clang::FunctionDecl* dispatch,
- RecordInfo* receiver);
- void ReportMissingFinalizeDispatch(const clang::FunctionDecl* dispatch,
- RecordInfo* receiver);
- void ReportMissingDispatch(const clang::FunctionDecl* dispatch,
- RecordInfo* receiver,
- unsigned error);
- void ReportDerivesNonStackAllocated(RecordInfo* info, BasePoint* base);
- void ReportClassOverridesNew(RecordInfo* info, clang::CXXMethodDecl* newop);
- void ReportClassDeclaresPureVirtualTrace(RecordInfo* info,
- clang::CXXMethodDecl* trace);
- void ReportLeftMostBaseMustBePolymorphic(RecordInfo* derived,
- clang::CXXRecordDecl* base);
- void ReportBaseClassMustDeclareVirtualTrace(RecordInfo* derived,
- clang::CXXRecordDecl* base);
- void NoteManualDispatchMethod(clang::CXXMethodDecl* dispatch);
- void NoteBaseRequiresTracing(BasePoint* base);
- void NoteFieldRequiresTracing(RecordInfo* holder, clang::FieldDecl* field);
- void NotePartObjectContainsGCRoot(FieldPoint* point);
- void NoteFieldContainsGCRoot(FieldPoint* point);
- void NoteUserDeclaredDestructor(clang::CXXMethodDecl* dtor);
- void NoteUserDeclaredFinalizer(clang::CXXMethodDecl* dtor);
- void NoteBaseRequiresFinalization(BasePoint* base);
- void NoteField(FieldPoint* point, unsigned note);
- void NoteField(clang::FieldDecl* field, unsigned note);
- void NoteOverriddenNonVirtualTrace(clang::CXXMethodDecl* overridden);
-
- unsigned diag_class_must_left_mostly_derive_gc_;
- unsigned diag_class_requires_trace_method_;
- unsigned diag_base_requires_tracing_;
- unsigned diag_fields_require_tracing_;
- unsigned diag_class_contains_invalid_fields_;
- unsigned diag_class_contains_invalid_fields_warning_;
- unsigned diag_class_contains_gc_root_;
- unsigned diag_class_requires_finalization_;
- unsigned diag_class_does_not_require_finalization_;
- unsigned diag_finalizer_accesses_finalized_field_;
- unsigned diag_finalizer_eagerly_finalized_field_;
- unsigned diag_overridden_non_virtual_trace_;
- unsigned diag_missing_trace_dispatch_method_;
- unsigned diag_missing_finalize_dispatch_method_;
- unsigned diag_virtual_and_manual_dispatch_;
- unsigned diag_missing_trace_dispatch_;
- unsigned diag_missing_finalize_dispatch_;
- unsigned diag_derives_non_stack_allocated_;
- unsigned diag_class_overrides_new_;
- unsigned diag_class_declares_pure_virtual_trace_;
- unsigned diag_left_most_base_must_be_polymorphic_;
- unsigned diag_base_class_must_declare_virtual_trace_;
-
- unsigned diag_base_requires_tracing_note_;
- unsigned diag_field_requires_tracing_note_;
- unsigned diag_raw_ptr_to_gc_managed_class_note_;
- unsigned diag_ref_ptr_to_gc_managed_class_note_;
- unsigned diag_reference_ptr_to_gc_managed_class_note_;
- unsigned diag_own_ptr_to_gc_managed_class_note_;
- unsigned diag_member_to_gc_unmanaged_class_note_;
- unsigned diag_stack_allocated_field_note_;
- unsigned diag_member_in_unmanaged_class_note_;
- unsigned diag_part_object_to_gc_derived_class_note_;
- unsigned diag_part_object_contains_gc_root_note_;
- unsigned diag_field_contains_gc_root_note_;
- unsigned diag_finalized_field_note_;
- unsigned diag_eagerly_finalized_field_note_;
- unsigned diag_user_declared_destructor_note_;
- unsigned diag_user_declared_finalizer_note_;
- unsigned diag_base_requires_finalization_note_;
- unsigned diag_field_requires_finalization_note_;
- unsigned diag_overridden_non_virtual_trace_note_;
- unsigned diag_manual_dispatch_method_note_;
-
clang::CompilerInstance& instance_;
- clang::DiagnosticsEngine& diagnostic_;
+ DiagnosticsReporter reporter_;
BlinkGCPluginOptions options_;
RecordCache cache_;
JsonWriter* json_;
};
-
#endif // TOOLS_BLINK_GC_PLUGIN_BLINK_GC_PLUGIN_CONSUMER_H_
diff --git a/chromium/tools/clang/blink_gc_plugin/BlinkGCPluginOptions.h b/chromium/tools/clang/blink_gc_plugin/BlinkGCPluginOptions.h
index 812d3a64eee..b941f086456 100644
--- a/chromium/tools/clang/blink_gc_plugin/BlinkGCPluginOptions.h
+++ b/chromium/tools/clang/blink_gc_plugin/BlinkGCPluginOptions.h
@@ -11,13 +11,9 @@
struct BlinkGCPluginOptions {
BlinkGCPluginOptions()
- : enable_oilpan(false),
- dump_graph(false),
- warn_raw_ptr(false),
+ : dump_graph(false),
warn_unneeded_finalizer(false) {}
- bool enable_oilpan;
bool dump_graph;
- bool warn_raw_ptr;
bool warn_unneeded_finalizer;
std::set<std::string> ignored_classes;
std::set<std::string> checked_namespaces;
diff --git a/chromium/tools/clang/blink_gc_plugin/CMakeLists.txt b/chromium/tools/clang/blink_gc_plugin/CMakeLists.txt
index 60ad1e52a74..009807b4164 100644
--- a/chromium/tools/clang/blink_gc_plugin/CMakeLists.txt
+++ b/chromium/tools/clang/blink_gc_plugin/CMakeLists.txt
@@ -10,6 +10,7 @@ set(plugin_sources
CheckTraceVisitor.cpp
CollectVisitor.cpp
Config.cpp
+ DiagnosticsReporter.cpp
Edge.cpp
RecordInfo.cpp)
diff --git a/chromium/tools/clang/blink_gc_plugin/CheckFieldsVisitor.cpp b/chromium/tools/clang/blink_gc_plugin/CheckFieldsVisitor.cpp
index 558637c9c19..e5d69f0b897 100644
--- a/chromium/tools/clang/blink_gc_plugin/CheckFieldsVisitor.cpp
+++ b/chromium/tools/clang/blink_gc_plugin/CheckFieldsVisitor.cpp
@@ -9,9 +9,8 @@
#include "BlinkGCPluginOptions.h"
#include "RecordInfo.h"
-CheckFieldsVisitor::CheckFieldsVisitor(const BlinkGCPluginOptions& options)
- : options_(options),
- current_(0),
+CheckFieldsVisitor::CheckFieldsVisitor()
+ : current_(0),
stack_allocated_host_(false) {
}
@@ -85,38 +84,19 @@ void CheckFieldsVisitor::AtValue(Value* edge) {
if (!Parent() || !edge->value()->IsGCAllocated())
return;
- // In transition mode, disallow OwnPtr<T>, RawPtr<T> to GC allocated T's,
- // also disallow T* in stack-allocated types.
- if (options_.enable_oilpan) {
- if (Parent()->IsOwnPtr() ||
- Parent()->IsRawPtrClass() ||
- (stack_allocated_host_ && Parent()->IsRawPtr())) {
- invalid_fields_.push_back(std::make_pair(
- current_, InvalidSmartPtr(Parent())));
- return;
- }
- if (options_.warn_raw_ptr && Parent()->IsRawPtr()) {
- if (static_cast<RawPtr*>(Parent())->HasReferenceType()) {
- invalid_fields_.push_back(std::make_pair(
- current_, kReferencePtrToGCManagedWarning));
- } else {
- invalid_fields_.push_back(std::make_pair(
- current_, kRawPtrToGCManagedWarning));
- }
- }
- return;
- }
-
- if (Parent()->IsRawPtr() || Parent()->IsOwnPtr()) {
+ // Disallow OwnPtr<T>, RefPtr<T> and T* to stack-allocated types.
+ if (Parent()->IsOwnPtr() ||
+ Parent()->IsRefPtr() ||
+ (stack_allocated_host_ && Parent()->IsRawPtr())) {
invalid_fields_.push_back(std::make_pair(
current_, InvalidSmartPtr(Parent())));
return;
}
-
- if (Parent()->IsRefPtr() && !edge->value()->IsGCRefCounted()) {
- invalid_fields_.push_back(std::make_pair(
- current_, InvalidSmartPtr(Parent())));
- return;
+ if (Parent()->IsRawPtr()) {
+ RawPtr* rawPtr = static_cast<RawPtr*>(Parent());
+ Error error = rawPtr->HasReferenceType() ?
+ kReferencePtrToGCManaged : kRawPtrToGCManaged;
+ invalid_fields_.push_back(std::make_pair(current_, error));
}
}
@@ -125,24 +105,6 @@ void CheckFieldsVisitor::AtCollection(Collection* edge) {
invalid_fields_.push_back(std::make_pair(current_, kOwnPtrToGCManaged));
}
-bool CheckFieldsVisitor::IsWarning(Error error) {
- if (error == kRawPtrToGCManagedWarning)
- return true;
- if (error == kReferencePtrToGCManagedWarning)
- return true;
- return false;
-}
-
-bool CheckFieldsVisitor::IsRawPtrError(Error error) {
- return (error == kRawPtrToGCManaged ||
- error == kRawPtrToGCManagedWarning);
-}
-
-bool CheckFieldsVisitor::IsReferencePtrError(Error error) {
- return (error == kReferencePtrToGCManaged ||
- error == kReferencePtrToGCManagedWarning);
-}
-
CheckFieldsVisitor::Error CheckFieldsVisitor::InvalidSmartPtr(Edge* ptr) {
if (ptr->IsRawPtr()) {
if (static_cast<RawPtr*>(ptr)->HasReferenceType())
diff --git a/chromium/tools/clang/blink_gc_plugin/CheckFieldsVisitor.h b/chromium/tools/clang/blink_gc_plugin/CheckFieldsVisitor.h
index e0c36a2d89d..4fddede3808 100644
--- a/chromium/tools/clang/blink_gc_plugin/CheckFieldsVisitor.h
+++ b/chromium/tools/clang/blink_gc_plugin/CheckFieldsVisitor.h
@@ -13,8 +13,8 @@ struct BlinkGCPluginOptions;
class FieldPoint;
// This visitor checks that the fields of a class are "well formed".
-// - OwnPtr, RefPtr and RawPtr must not point to a GC derived types.
-// - Part objects must not be GC derived types.
+// - OwnPtr and RefPtr must not point to a GC derived type.
+// - Part objects must not be a GC derived type.
// - An on-heap class must never contain GC roots.
// - Only stack-allocated types may point to stack-allocated types.
@@ -22,10 +22,8 @@ class CheckFieldsVisitor : public RecursiveEdgeVisitor {
public:
enum Error {
kRawPtrToGCManaged,
- kRawPtrToGCManagedWarning,
kRefPtrToGCManaged,
kReferencePtrToGCManaged,
- kReferencePtrToGCManagedWarning,
kOwnPtrToGCManaged,
kMemberToGCUnmanaged,
kMemberInUnmanaged,
@@ -33,9 +31,9 @@ class CheckFieldsVisitor : public RecursiveEdgeVisitor {
kGCDerivedPartObject
};
- typedef std::vector<std::pair<FieldPoint*, Error> > Errors;
+ using Errors = std::vector<std::pair<FieldPoint*, Error>>;
- explicit CheckFieldsVisitor(const BlinkGCPluginOptions& options);
+ CheckFieldsVisitor();
Errors& invalid_fields();
@@ -45,14 +43,9 @@ class CheckFieldsVisitor : public RecursiveEdgeVisitor {
void AtValue(Value* edge) override;
void AtCollection(Collection* edge) override;
- static bool IsWarning(Error error);
- static bool IsRawPtrError(Error error);
- static bool IsReferencePtrError(Error error);
-
private:
Error InvalidSmartPtr(Edge* ptr);
- const BlinkGCPluginOptions& options_;
FieldPoint* current_;
bool stack_allocated_host_;
bool managed_host_;
diff --git a/chromium/tools/clang/blink_gc_plugin/Config.h b/chromium/tools/clang/blink_gc_plugin/Config.h
index 7ca8ea4c0f1..8d331e5581e 100644
--- a/chromium/tools/clang/blink_gc_plugin/Config.h
+++ b/chromium/tools/clang/blink_gc_plugin/Config.h
@@ -133,14 +133,7 @@ class Config {
}
static bool IsGCFinalizedBase(const std::string& name) {
- return name == "GarbageCollectedFinalized" ||
- name == "RefCountedGarbageCollected" ||
- name == "ThreadSafeRefCountedGarbageCollected";
- }
-
- static bool IsGCRefCountedBase(const std::string& name) {
- return name == "RefCountedGarbageCollected" ||
- name == "ThreadSafeRefCountedGarbageCollected";
+ return name == "GarbageCollectedFinalized";
}
static bool IsGCBase(const std::string& name) {
diff --git a/chromium/tools/clang/blink_gc_plugin/DiagnosticsReporter.cpp b/chromium/tools/clang/blink_gc_plugin/DiagnosticsReporter.cpp
new file mode 100644
index 00000000000..0057d80da58
--- /dev/null
+++ b/chromium/tools/clang/blink_gc_plugin/DiagnosticsReporter.cpp
@@ -0,0 +1,527 @@
+// 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 "DiagnosticsReporter.h"
+
+using namespace clang;
+
+namespace {
+
+const char kClassMustLeftMostlyDeriveGC[] =
+ "[blink-gc] Class %0 must derive its GC base in the left-most position.";
+
+const char kClassRequiresTraceMethod[] =
+ "[blink-gc] Class %0 requires a trace method.";
+
+const char kBaseRequiresTracing[] =
+ "[blink-gc] Base class %0 of derived class %1 requires tracing.";
+
+const char kBaseRequiresTracingNote[] =
+ "[blink-gc] Untraced base class %0 declared here:";
+
+const char kFieldsRequireTracing[] =
+ "[blink-gc] Class %0 has untraced fields that require tracing.";
+
+const char kFieldRequiresTracingNote[] =
+ "[blink-gc] Untraced field %0 declared here:";
+
+const char kClassContainsInvalidFields[] =
+ "[blink-gc] Class %0 contains invalid fields.";
+
+const char kClassContainsGCRoot[] =
+ "[blink-gc] Class %0 contains GC root in field %1.";
+
+const char kClassRequiresFinalization[] =
+ "[blink-gc] Class %0 requires finalization.";
+
+const char kClassDoesNotRequireFinalization[] =
+ "[blink-gc] Class %0 may not require finalization.";
+
+const char kFinalizerAccessesFinalizedField[] =
+ "[blink-gc] Finalizer %0 accesses potentially finalized field %1.";
+
+const char kFinalizerAccessesEagerlyFinalizedField[] =
+ "[blink-gc] Finalizer %0 accesses eagerly finalized field %1.";
+
+const char kRawPtrToGCManagedClassNote[] =
+ "[blink-gc] Raw pointer field %0 to a GC managed class declared here:";
+
+const char kRefPtrToGCManagedClassNote[] =
+ "[blink-gc] RefPtr field %0 to a GC managed class declared here:";
+
+const char kReferencePtrToGCManagedClassNote[] =
+ "[blink-gc] Reference pointer field %0 to a GC managed class"
+ " declared here:";
+
+const char kOwnPtrToGCManagedClassNote[] =
+ "[blink-gc] OwnPtr field %0 to a GC managed class declared here:";
+
+const char kMemberToGCUnmanagedClassNote[] =
+ "[blink-gc] Member field %0 to non-GC managed class declared here:";
+
+const char kStackAllocatedFieldNote[] =
+ "[blink-gc] Stack-allocated field %0 declared here:";
+
+const char kMemberInUnmanagedClassNote[] =
+ "[blink-gc] Member field %0 in unmanaged class declared here:";
+
+const char kPartObjectToGCDerivedClassNote[] =
+ "[blink-gc] Part-object field %0 to a GC derived class declared here:";
+
+const char kPartObjectContainsGCRootNote[] =
+ "[blink-gc] Field %0 with embedded GC root in %1 declared here:";
+
+const char kFieldContainsGCRootNote[] =
+ "[blink-gc] Field %0 defining a GC root declared here:";
+
+const char kOverriddenNonVirtualTrace[] =
+ "[blink-gc] Class %0 overrides non-virtual trace of base class %1.";
+
+const char kOverriddenNonVirtualTraceNote[] =
+ "[blink-gc] Non-virtual trace method declared here:";
+
+const char kMissingTraceDispatchMethod[] =
+ "[blink-gc] Class %0 is missing manual trace dispatch.";
+
+const char kMissingFinalizeDispatchMethod[] =
+ "[blink-gc] Class %0 is missing manual finalize dispatch.";
+
+const char kVirtualAndManualDispatch[] =
+ "[blink-gc] Class %0 contains or inherits virtual methods"
+ " but implements manual dispatching.";
+
+const char kMissingTraceDispatch[] =
+ "[blink-gc] Missing dispatch to class %0 in manual trace dispatch.";
+
+const char kMissingFinalizeDispatch[] =
+ "[blink-gc] Missing dispatch to class %0 in manual finalize dispatch.";
+
+const char kFinalizedFieldNote[] =
+ "[blink-gc] Potentially finalized field %0 declared here:";
+
+const char kEagerlyFinalizedFieldNote[] =
+ "[blink-gc] Field %0 having eagerly finalized value, declared here:";
+
+const char kUserDeclaredDestructorNote[] =
+ "[blink-gc] User-declared destructor declared here:";
+
+const char kUserDeclaredFinalizerNote[] =
+ "[blink-gc] User-declared finalizer declared here:";
+
+const char kBaseRequiresFinalizationNote[] =
+ "[blink-gc] Base class %0 requiring finalization declared here:";
+
+const char kFieldRequiresFinalizationNote[] =
+ "[blink-gc] Field %0 requiring finalization declared here:";
+
+const char kManualDispatchMethodNote[] =
+ "[blink-gc] Manual dispatch %0 declared here:";
+
+const char kDerivesNonStackAllocated[] =
+ "[blink-gc] Stack-allocated class %0 derives class %1"
+ " which is not stack allocated.";
+
+const char kClassOverridesNew[] =
+ "[blink-gc] Garbage collected class %0"
+ " is not permitted to override its new operator.";
+
+const char kClassDeclaresPureVirtualTrace[] =
+ "[blink-gc] Garbage collected class %0"
+ " is not permitted to declare a pure-virtual trace method.";
+
+const char kLeftMostBaseMustBePolymorphic[] =
+ "[blink-gc] Left-most base class %0 of derived class %1"
+ " must be polymorphic.";
+
+const char kBaseClassMustDeclareVirtualTrace[] =
+ "[blink-gc] Left-most base class %0 of derived class %1"
+ " must define a virtual trace method.";
+
+} // namespace
+
+DiagnosticBuilder DiagnosticsReporter::ReportDiagnostic(
+ SourceLocation location,
+ unsigned diag_id) {
+ SourceManager& manager = instance_.getSourceManager();
+ FullSourceLoc full_loc(location, manager);
+ return diagnostic_.Report(full_loc, diag_id);
+}
+
+DiagnosticsReporter::DiagnosticsReporter(
+ clang::CompilerInstance& instance)
+ : instance_(instance),
+ diagnostic_(instance.getDiagnostics())
+{
+ // Register warning/error messages.
+ diag_class_must_left_mostly_derive_gc_ = diagnostic_.getCustomDiagID(
+ getErrorLevel(), kClassMustLeftMostlyDeriveGC);
+ diag_class_requires_trace_method_ =
+ diagnostic_.getCustomDiagID(getErrorLevel(), kClassRequiresTraceMethod);
+ diag_base_requires_tracing_ =
+ diagnostic_.getCustomDiagID(getErrorLevel(), kBaseRequiresTracing);
+ diag_fields_require_tracing_ =
+ diagnostic_.getCustomDiagID(getErrorLevel(), kFieldsRequireTracing);
+ diag_class_contains_invalid_fields_ = diagnostic_.getCustomDiagID(
+ getErrorLevel(), kClassContainsInvalidFields);
+ diag_class_contains_gc_root_ =
+ diagnostic_.getCustomDiagID(getErrorLevel(), kClassContainsGCRoot);
+ diag_class_requires_finalization_ = diagnostic_.getCustomDiagID(
+ getErrorLevel(), kClassRequiresFinalization);
+ diag_class_does_not_require_finalization_ = diagnostic_.getCustomDiagID(
+ DiagnosticsEngine::Warning, kClassDoesNotRequireFinalization);
+ diag_finalizer_accesses_finalized_field_ = diagnostic_.getCustomDiagID(
+ getErrorLevel(), kFinalizerAccessesFinalizedField);
+ diag_finalizer_eagerly_finalized_field_ = diagnostic_.getCustomDiagID(
+ getErrorLevel(), kFinalizerAccessesEagerlyFinalizedField);
+ diag_overridden_non_virtual_trace_ = diagnostic_.getCustomDiagID(
+ getErrorLevel(), kOverriddenNonVirtualTrace);
+ diag_missing_trace_dispatch_method_ = diagnostic_.getCustomDiagID(
+ getErrorLevel(), kMissingTraceDispatchMethod);
+ diag_missing_finalize_dispatch_method_ = diagnostic_.getCustomDiagID(
+ getErrorLevel(), kMissingFinalizeDispatchMethod);
+ diag_virtual_and_manual_dispatch_ =
+ diagnostic_.getCustomDiagID(getErrorLevel(), kVirtualAndManualDispatch);
+ diag_missing_trace_dispatch_ =
+ diagnostic_.getCustomDiagID(getErrorLevel(), kMissingTraceDispatch);
+ diag_missing_finalize_dispatch_ =
+ diagnostic_.getCustomDiagID(getErrorLevel(), kMissingFinalizeDispatch);
+ diag_derives_non_stack_allocated_ =
+ diagnostic_.getCustomDiagID(getErrorLevel(), kDerivesNonStackAllocated);
+ diag_class_overrides_new_ =
+ diagnostic_.getCustomDiagID(getErrorLevel(), kClassOverridesNew);
+ diag_class_declares_pure_virtual_trace_ = diagnostic_.getCustomDiagID(
+ getErrorLevel(), kClassDeclaresPureVirtualTrace);
+ diag_left_most_base_must_be_polymorphic_ = diagnostic_.getCustomDiagID(
+ getErrorLevel(), kLeftMostBaseMustBePolymorphic);
+ diag_base_class_must_declare_virtual_trace_ = diagnostic_.getCustomDiagID(
+ getErrorLevel(), kBaseClassMustDeclareVirtualTrace);
+
+ // Register note messages.
+ diag_base_requires_tracing_note_ = diagnostic_.getCustomDiagID(
+ DiagnosticsEngine::Note, kBaseRequiresTracingNote);
+ diag_field_requires_tracing_note_ = diagnostic_.getCustomDiagID(
+ DiagnosticsEngine::Note, kFieldRequiresTracingNote);
+ diag_raw_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID(
+ DiagnosticsEngine::Note, kRawPtrToGCManagedClassNote);
+ diag_ref_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID(
+ DiagnosticsEngine::Note, kRefPtrToGCManagedClassNote);
+ diag_reference_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID(
+ DiagnosticsEngine::Note, kReferencePtrToGCManagedClassNote);
+ diag_own_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID(
+ DiagnosticsEngine::Note, kOwnPtrToGCManagedClassNote);
+ diag_member_to_gc_unmanaged_class_note_ = diagnostic_.getCustomDiagID(
+ DiagnosticsEngine::Note, kMemberToGCUnmanagedClassNote);
+ diag_stack_allocated_field_note_ = diagnostic_.getCustomDiagID(
+ DiagnosticsEngine::Note, kStackAllocatedFieldNote);
+ diag_member_in_unmanaged_class_note_ = diagnostic_.getCustomDiagID(
+ DiagnosticsEngine::Note, kMemberInUnmanagedClassNote);
+ diag_part_object_to_gc_derived_class_note_ = diagnostic_.getCustomDiagID(
+ DiagnosticsEngine::Note, kPartObjectToGCDerivedClassNote);
+ diag_part_object_contains_gc_root_note_ = diagnostic_.getCustomDiagID(
+ DiagnosticsEngine::Note, kPartObjectContainsGCRootNote);
+ diag_field_contains_gc_root_note_ = diagnostic_.getCustomDiagID(
+ DiagnosticsEngine::Note, kFieldContainsGCRootNote);
+ diag_finalized_field_note_ = diagnostic_.getCustomDiagID(
+ DiagnosticsEngine::Note, kFinalizedFieldNote);
+ diag_eagerly_finalized_field_note_ = diagnostic_.getCustomDiagID(
+ DiagnosticsEngine::Note, kEagerlyFinalizedFieldNote);
+ diag_user_declared_destructor_note_ = diagnostic_.getCustomDiagID(
+ DiagnosticsEngine::Note, kUserDeclaredDestructorNote);
+ diag_user_declared_finalizer_note_ = diagnostic_.getCustomDiagID(
+ DiagnosticsEngine::Note, kUserDeclaredFinalizerNote);
+ diag_base_requires_finalization_note_ = diagnostic_.getCustomDiagID(
+ DiagnosticsEngine::Note, kBaseRequiresFinalizationNote);
+ diag_field_requires_finalization_note_ = diagnostic_.getCustomDiagID(
+ DiagnosticsEngine::Note, kFieldRequiresFinalizationNote);
+ diag_overridden_non_virtual_trace_note_ = diagnostic_.getCustomDiagID(
+ DiagnosticsEngine::Note, kOverriddenNonVirtualTraceNote);
+ diag_manual_dispatch_method_note_ = diagnostic_.getCustomDiagID(
+ DiagnosticsEngine::Note, kManualDispatchMethodNote);
+}
+
+bool DiagnosticsReporter::hasErrorOccurred() const
+{
+ return diagnostic_.hasErrorOccurred();
+}
+
+DiagnosticsEngine::Level DiagnosticsReporter::getErrorLevel() const {
+ return diagnostic_.getWarningsAsErrors() ? DiagnosticsEngine::Error
+ : DiagnosticsEngine::Warning;
+}
+
+void DiagnosticsReporter::ClassMustLeftMostlyDeriveGC(
+ RecordInfo* info) {
+ ReportDiagnostic(info->record()->getInnerLocStart(),
+ diag_class_must_left_mostly_derive_gc_)
+ << info->record();
+}
+
+void DiagnosticsReporter::ClassRequiresTraceMethod(RecordInfo* info) {
+ ReportDiagnostic(info->record()->getInnerLocStart(),
+ diag_class_requires_trace_method_)
+ << info->record();
+
+ for (auto& base : info->GetBases())
+ if (base.second.NeedsTracing().IsNeeded())
+ NoteBaseRequiresTracing(&base.second);
+
+ for (auto& field : info->GetFields())
+ if (!field.second.IsProperlyTraced())
+ NoteFieldRequiresTracing(info, field.first);
+}
+
+void DiagnosticsReporter::BaseRequiresTracing(
+ RecordInfo* derived,
+ CXXMethodDecl* trace,
+ CXXRecordDecl* base) {
+ ReportDiagnostic(trace->getLocStart(), diag_base_requires_tracing_)
+ << base << derived->record();
+}
+
+void DiagnosticsReporter::FieldsRequireTracing(
+ RecordInfo* info,
+ CXXMethodDecl* trace) {
+ ReportDiagnostic(trace->getLocStart(), diag_fields_require_tracing_)
+ << info->record();
+ for (auto& field : info->GetFields())
+ if (!field.second.IsProperlyTraced())
+ NoteFieldRequiresTracing(info, field.first);
+}
+
+void DiagnosticsReporter::ClassContainsInvalidFields(
+ RecordInfo* info,
+ const CheckFieldsVisitor::Errors& errors) {
+
+ ReportDiagnostic(info->record()->getLocStart(),
+ diag_class_contains_invalid_fields_)
+ << info->record();
+
+ for (auto& error : errors) {
+ unsigned note;
+ if (error.second == CheckFieldsVisitor::kRawPtrToGCManaged) {
+ note = diag_raw_ptr_to_gc_managed_class_note_;
+ } else if (error.second == CheckFieldsVisitor::kRefPtrToGCManaged) {
+ note = diag_ref_ptr_to_gc_managed_class_note_;
+ } else if (error.second == CheckFieldsVisitor::kReferencePtrToGCManaged) {
+ note = diag_reference_ptr_to_gc_managed_class_note_;
+ } else if (error.second == CheckFieldsVisitor::kOwnPtrToGCManaged) {
+ note = diag_own_ptr_to_gc_managed_class_note_;
+ } else if (error.second == CheckFieldsVisitor::kMemberToGCUnmanaged) {
+ note = diag_member_to_gc_unmanaged_class_note_;
+ } else if (error.second == CheckFieldsVisitor::kMemberInUnmanaged) {
+ note = diag_member_in_unmanaged_class_note_;
+ } else if (error.second == CheckFieldsVisitor::kPtrFromHeapToStack) {
+ note = diag_stack_allocated_field_note_;
+ } else if (error.second == CheckFieldsVisitor::kGCDerivedPartObject) {
+ note = diag_part_object_to_gc_derived_class_note_;
+ } else {
+ assert(false && "Unknown field error");
+ }
+ NoteField(error.first, note);
+ }
+}
+
+void DiagnosticsReporter::ClassContainsGCRoots(
+ RecordInfo* info,
+ const CheckGCRootsVisitor::Errors& errors) {
+ for (auto& error : errors) {
+ FieldPoint* point = nullptr;
+ for (FieldPoint* path : error) {
+ if (!point) {
+ point = path;
+ ReportDiagnostic(info->record()->getLocStart(),
+ diag_class_contains_gc_root_)
+ << info->record() << point->field();
+ continue;
+ }
+ NotePartObjectContainsGCRoot(point);
+ point = path;
+ }
+ NoteFieldContainsGCRoot(point);
+ }
+}
+
+void DiagnosticsReporter::FinalizerAccessesFinalizedFields(
+ CXXMethodDecl* dtor,
+ const CheckFinalizerVisitor::Errors& errors) {
+ for (auto& error : errors) {
+ bool as_eagerly_finalized = error.as_eagerly_finalized;
+ unsigned diag_error = as_eagerly_finalized ?
+ diag_finalizer_eagerly_finalized_field_ :
+ diag_finalizer_accesses_finalized_field_;
+ unsigned diag_note = as_eagerly_finalized ?
+ diag_eagerly_finalized_field_note_ :
+ diag_finalized_field_note_;
+ ReportDiagnostic(error.member->getLocStart(), diag_error)
+ << dtor << error.field->field();
+ NoteField(error.field, diag_note);
+ }
+}
+
+void DiagnosticsReporter::ClassRequiresFinalization(RecordInfo* info) {
+ ReportDiagnostic(info->record()->getInnerLocStart(),
+ diag_class_requires_finalization_)
+ << info->record();
+}
+
+void DiagnosticsReporter::ClassDoesNotRequireFinalization(
+ RecordInfo* info) {
+ ReportDiagnostic(info->record()->getInnerLocStart(),
+ diag_class_does_not_require_finalization_)
+ << info->record();
+}
+
+void DiagnosticsReporter::OverriddenNonVirtualTrace(
+ RecordInfo* info,
+ CXXMethodDecl* trace,
+ CXXMethodDecl* overridden) {
+ ReportDiagnostic(trace->getLocStart(), diag_overridden_non_virtual_trace_)
+ << info->record() << overridden->getParent();
+ NoteOverriddenNonVirtualTrace(overridden);
+}
+
+void DiagnosticsReporter::MissingTraceDispatchMethod(RecordInfo* info) {
+ ReportMissingDispatchMethod(info, diag_missing_trace_dispatch_method_);
+}
+
+void DiagnosticsReporter::MissingFinalizeDispatchMethod(
+ RecordInfo* info) {
+ ReportMissingDispatchMethod(info, diag_missing_finalize_dispatch_method_);
+}
+
+void DiagnosticsReporter::ReportMissingDispatchMethod(
+ RecordInfo* info,
+ unsigned error) {
+ ReportDiagnostic(info->record()->getInnerLocStart(), error)
+ << info->record();
+}
+
+void DiagnosticsReporter::VirtualAndManualDispatch(
+ RecordInfo* info,
+ CXXMethodDecl* dispatch) {
+ ReportDiagnostic(info->record()->getInnerLocStart(),
+ diag_virtual_and_manual_dispatch_)
+ << info->record();
+ NoteManualDispatchMethod(dispatch);
+}
+
+void DiagnosticsReporter::MissingTraceDispatch(
+ const FunctionDecl* dispatch,
+ RecordInfo* receiver) {
+ ReportMissingDispatch(dispatch, receiver, diag_missing_trace_dispatch_);
+}
+
+void DiagnosticsReporter::MissingFinalizeDispatch(
+ const FunctionDecl* dispatch,
+ RecordInfo* receiver) {
+ ReportMissingDispatch(dispatch, receiver, diag_missing_finalize_dispatch_);
+}
+
+void DiagnosticsReporter::ReportMissingDispatch(
+ const FunctionDecl* dispatch,
+ RecordInfo* receiver,
+ unsigned error) {
+ ReportDiagnostic(dispatch->getLocStart(), error) << receiver->record();
+}
+
+void DiagnosticsReporter::DerivesNonStackAllocated(
+ RecordInfo* info,
+ BasePoint* base) {
+ ReportDiagnostic(base->spec().getLocStart(),
+ diag_derives_non_stack_allocated_)
+ << info->record() << base->info()->record();
+}
+
+void DiagnosticsReporter::ClassOverridesNew(
+ RecordInfo* info,
+ CXXMethodDecl* newop) {
+ ReportDiagnostic(newop->getLocStart(), diag_class_overrides_new_)
+ << info->record();
+}
+
+void DiagnosticsReporter::ClassDeclaresPureVirtualTrace(
+ RecordInfo* info,
+ CXXMethodDecl* trace) {
+ ReportDiagnostic(trace->getLocStart(),
+ diag_class_declares_pure_virtual_trace_)
+ << info->record();
+}
+
+void DiagnosticsReporter::LeftMostBaseMustBePolymorphic(
+ RecordInfo* derived,
+ CXXRecordDecl* base) {
+ ReportDiagnostic(base->getLocStart(),
+ diag_left_most_base_must_be_polymorphic_)
+ << base << derived->record();
+}
+
+void DiagnosticsReporter::BaseClassMustDeclareVirtualTrace(
+ RecordInfo* derived,
+ CXXRecordDecl* base) {
+ ReportDiagnostic(base->getLocStart(),
+ diag_base_class_must_declare_virtual_trace_)
+ << base << derived->record();
+}
+
+void DiagnosticsReporter::NoteManualDispatchMethod(CXXMethodDecl* dispatch) {
+ ReportDiagnostic(dispatch->getLocStart(),
+ diag_manual_dispatch_method_note_)
+ << dispatch;
+}
+
+void DiagnosticsReporter::NoteBaseRequiresTracing(BasePoint* base) {
+ ReportDiagnostic(base->spec().getLocStart(),
+ diag_base_requires_tracing_note_)
+ << base->info()->record();
+}
+
+void DiagnosticsReporter::NoteFieldRequiresTracing(
+ RecordInfo* holder,
+ FieldDecl* field) {
+ NoteField(field, diag_field_requires_tracing_note_);
+}
+
+void DiagnosticsReporter::NotePartObjectContainsGCRoot(FieldPoint* point) {
+ FieldDecl* field = point->field();
+ ReportDiagnostic(field->getLocStart(),
+ diag_part_object_contains_gc_root_note_)
+ << field << field->getParent();
+}
+
+void DiagnosticsReporter::NoteFieldContainsGCRoot(FieldPoint* point) {
+ NoteField(point, diag_field_contains_gc_root_note_);
+}
+
+void DiagnosticsReporter::NoteUserDeclaredDestructor(CXXMethodDecl* dtor) {
+ ReportDiagnostic(dtor->getLocStart(), diag_user_declared_destructor_note_);
+}
+
+void DiagnosticsReporter::NoteUserDeclaredFinalizer(CXXMethodDecl* dtor) {
+ ReportDiagnostic(dtor->getLocStart(), diag_user_declared_finalizer_note_);
+}
+
+void DiagnosticsReporter::NoteBaseRequiresFinalization(BasePoint* base) {
+ ReportDiagnostic(base->spec().getLocStart(),
+ diag_base_requires_finalization_note_)
+ << base->info()->record();
+}
+
+void DiagnosticsReporter::NoteFieldRequiresFinalization(FieldPoint* point) {
+ NoteField(point, diag_field_requires_finalization_note_);
+}
+
+void DiagnosticsReporter::NoteField(FieldPoint* point, unsigned note) {
+ NoteField(point->field(), note);
+}
+
+void DiagnosticsReporter::NoteField(FieldDecl* field, unsigned note) {
+ ReportDiagnostic(field->getLocStart(), note) << field;
+}
+
+void DiagnosticsReporter::NoteOverriddenNonVirtualTrace(
+ CXXMethodDecl* overridden) {
+ ReportDiagnostic(overridden->getLocStart(),
+ diag_overridden_non_virtual_trace_note_)
+ << overridden;
+}
diff --git a/chromium/tools/clang/blink_gc_plugin/DiagnosticsReporter.h b/chromium/tools/clang/blink_gc_plugin/DiagnosticsReporter.h
new file mode 100644
index 00000000000..2f9076ec7b9
--- /dev/null
+++ b/chromium/tools/clang/blink_gc_plugin/DiagnosticsReporter.h
@@ -0,0 +1,137 @@
+// 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_BLINK_GC_PLUGIN_DIAGNOSTICS_REPORTER_H_
+#define TOOLS_BLINK_GC_PLUGIN_DIAGNOSTICS_REPORTER_H_
+
+#include "CheckFieldsVisitor.h"
+#include "CheckFinalizerVisitor.h"
+#include "CheckGCRootsVisitor.h"
+#include "Config.h"
+#include "clang/AST/AST.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Frontend/CompilerInstance.h"
+
+class RecordInfo;
+
+// All error/warning reporting methods under one roof.
+//
+class DiagnosticsReporter {
+ public:
+ explicit DiagnosticsReporter(clang::CompilerInstance&);
+
+ bool hasErrorOccurred() const;
+ clang::DiagnosticsEngine::Level getErrorLevel() const;
+
+ void ClassMustLeftMostlyDeriveGC(RecordInfo* info);
+ void ClassRequiresTraceMethod(RecordInfo* info);
+ void BaseRequiresTracing(RecordInfo* derived,
+ clang::CXXMethodDecl* trace,
+ clang::CXXRecordDecl* base);
+ void FieldsRequireTracing(RecordInfo* info,
+ clang::CXXMethodDecl* trace);
+ void ClassContainsInvalidFields(
+ RecordInfo* info,
+ const CheckFieldsVisitor::Errors& errors);
+ void ClassContainsGCRoots(RecordInfo* info,
+ const CheckGCRootsVisitor::Errors& errors);
+ void FinalizerAccessesFinalizedFields(
+ clang::CXXMethodDecl* dtor,
+ const CheckFinalizerVisitor::Errors& errors);
+ void ClassRequiresFinalization(RecordInfo* info);
+ void ClassDoesNotRequireFinalization(RecordInfo* info);
+ void ClassMustDeclareGCMixinTraceMethod(RecordInfo* info);
+ void OverriddenNonVirtualTrace(RecordInfo* info,
+ clang::CXXMethodDecl* trace,
+ clang::CXXMethodDecl* overridden);
+ void MissingTraceDispatchMethod(RecordInfo* info);
+ void MissingFinalizeDispatchMethod(RecordInfo* info);
+ void VirtualAndManualDispatch(RecordInfo* info,
+ clang::CXXMethodDecl* dispatch);
+ void MissingTraceDispatch(const clang::FunctionDecl* dispatch,
+ RecordInfo* receiver);
+ void MissingFinalizeDispatch(const clang::FunctionDecl* dispatch,
+ RecordInfo* receiver);
+ void DerivesNonStackAllocated(RecordInfo* info, BasePoint* base);
+ void ClassOverridesNew(RecordInfo* info, clang::CXXMethodDecl* newop);
+ void ClassDeclaresPureVirtualTrace(RecordInfo* info,
+ clang::CXXMethodDecl* trace);
+ void LeftMostBaseMustBePolymorphic(RecordInfo* derived,
+ clang::CXXRecordDecl* base);
+ void BaseClassMustDeclareVirtualTrace(RecordInfo* derived,
+ clang::CXXRecordDecl* base);
+
+ void NoteManualDispatchMethod(clang::CXXMethodDecl* dispatch);
+ void NoteBaseRequiresTracing(BasePoint* base);
+ void NoteFieldRequiresTracing(RecordInfo* holder, clang::FieldDecl* field);
+ void NotePartObjectContainsGCRoot(FieldPoint* point);
+ void NoteFieldContainsGCRoot(FieldPoint* point);
+ void NoteUserDeclaredDestructor(clang::CXXMethodDecl* dtor);
+ void NoteUserDeclaredFinalizer(clang::CXXMethodDecl* dtor);
+ void NoteBaseRequiresFinalization(BasePoint* base);
+ void NoteFieldRequiresFinalization(FieldPoint* field);
+ void NoteField(FieldPoint* point, unsigned note);
+ void NoteField(clang::FieldDecl* field, unsigned note);
+ void NoteOverriddenNonVirtualTrace(clang::CXXMethodDecl* overridden);
+
+ private:
+ clang::DiagnosticBuilder ReportDiagnostic(
+ clang::SourceLocation location,
+ unsigned diag_id);
+
+ void ReportMissingDispatchMethod(RecordInfo* info, unsigned error);
+ void ReportMissingDispatch(const clang::FunctionDecl* dispatch,
+ RecordInfo* receiver,
+ unsigned error);
+
+ clang::CompilerInstance& instance_;
+ clang::DiagnosticsEngine& diagnostic_;
+
+ unsigned diag_class_must_left_mostly_derive_gc_;
+ unsigned diag_class_requires_trace_method_;
+ unsigned diag_base_requires_tracing_;
+ unsigned diag_fields_require_tracing_;
+ unsigned diag_class_contains_invalid_fields_;
+ unsigned diag_class_contains_gc_root_;
+ unsigned diag_class_requires_finalization_;
+ unsigned diag_class_does_not_require_finalization_;
+ unsigned diag_finalizer_accesses_finalized_field_;
+ unsigned diag_finalizer_eagerly_finalized_field_;
+ unsigned diag_overridden_non_virtual_trace_;
+ unsigned diag_missing_trace_dispatch_method_;
+ unsigned diag_missing_finalize_dispatch_method_;
+ unsigned diag_virtual_and_manual_dispatch_;
+ unsigned diag_missing_trace_dispatch_;
+ unsigned diag_missing_finalize_dispatch_;
+ unsigned diag_derives_non_stack_allocated_;
+ unsigned diag_class_overrides_new_;
+ unsigned diag_class_declares_pure_virtual_trace_;
+ unsigned diag_left_most_base_must_be_polymorphic_;
+ unsigned diag_base_class_must_declare_virtual_trace_;
+
+ unsigned diag_base_requires_tracing_note_;
+ unsigned diag_field_requires_tracing_note_;
+ unsigned diag_raw_ptr_to_gc_managed_class_note_;
+ unsigned diag_ref_ptr_to_gc_managed_class_note_;
+ unsigned diag_reference_ptr_to_gc_managed_class_note_;
+ unsigned diag_own_ptr_to_gc_managed_class_note_;
+ unsigned diag_member_to_gc_unmanaged_class_note_;
+ unsigned diag_stack_allocated_field_note_;
+ unsigned diag_member_in_unmanaged_class_note_;
+ unsigned diag_part_object_to_gc_derived_class_note_;
+ unsigned diag_part_object_contains_gc_root_note_;
+ unsigned diag_field_contains_gc_root_note_;
+ unsigned diag_finalized_field_note_;
+ unsigned diag_eagerly_finalized_field_note_;
+ unsigned diag_user_declared_destructor_note_;
+ unsigned diag_user_declared_finalizer_note_;
+ unsigned diag_base_requires_finalization_note_;
+ unsigned diag_field_requires_finalization_note_;
+ unsigned diag_overridden_non_virtual_trace_note_;
+ unsigned diag_manual_dispatch_method_note_;
+
+};
+
+#endif // TOOLS_BLINK_GC_PLUGIN_DIAGNOSTICS_REPORTER_H_
diff --git a/chromium/tools/clang/blink_gc_plugin/Edge.h b/chromium/tools/clang/blink_gc_plugin/Edge.h
index eca3158d75f..91e569867d8 100644
--- a/chromium/tools/clang/blink_gc_plugin/Edge.h
+++ b/chromium/tools/clang/blink_gc_plugin/Edge.h
@@ -87,7 +87,6 @@ class Edge {
virtual bool IsValue() { return false; }
virtual bool IsRawPtr() { return false; }
- virtual bool IsRawPtrClass() { return false; }
virtual bool IsRefPtr() { return false; }
virtual bool IsOwnPtr() { return false; }
virtual bool IsMember() { return false; }
@@ -126,16 +125,13 @@ class PtrEdge : public Edge {
class RawPtr : public PtrEdge {
public:
- RawPtr(Edge* ptr, bool is_ptr_class, bool is_ref_type)
+ RawPtr(Edge* ptr, bool is_ref_type)
: PtrEdge(ptr)
- , is_ptr_class_(is_ptr_class)
, is_ref_type_(is_ref_type)
{
- assert(!(is_ptr_class_ && is_ref_type_));
}
bool IsRawPtr() { return true; }
- bool IsRawPtrClass() { return is_ptr_class_; }
LivenessKind Kind() { return kWeak; }
bool NeedsFinalization() { return false; }
TracingStatus NeedsTracing(NeedsTracingOption) {
@@ -145,7 +141,6 @@ class RawPtr : public PtrEdge {
bool HasReferenceType() { return is_ref_type_; }
private:
- bool is_ptr_class_;
bool is_ref_type_;
};
diff --git a/chromium/tools/clang/blink_gc_plugin/OWNERS b/chromium/tools/clang/blink_gc_plugin/OWNERS
index 9c24a9651d6..789d7efaaaa 100644
--- a/chromium/tools/clang/blink_gc_plugin/OWNERS
+++ b/chromium/tools/clang/blink_gc_plugin/OWNERS
@@ -1,5 +1,4 @@
-ager@chromium.org
haraken@chromium.org
kouhei@chromium.org
tkent@chromium.org
-zerny@chromium.org
+sigbjornf@opera.com
diff --git a/chromium/tools/clang/blink_gc_plugin/RecordInfo.cpp b/chromium/tools/clang/blink_gc_plugin/RecordInfo.cpp
index b4937abd20f..f0e2ade715b 100644
--- a/chromium/tools/clang/blink_gc_plugin/RecordInfo.cpp
+++ b/chromium/tools/clang/blink_gc_plugin/RecordInfo.cpp
@@ -186,16 +186,6 @@ bool RecordInfo::IsEagerlyFinalized() {
return is_eagerly_finalized_;
}
-bool RecordInfo::IsGCRefCounted() {
- if (!IsGCDerived())
- return false;
- for (const auto& gc_base : gc_base_names_) {
- if (Config::IsGCRefCountedBase(gc_base))
- return true;
- }
- return false;
-}
-
bool RecordInfo::HasDefinition() {
return record_->hasDefinition();
}
@@ -584,7 +574,7 @@ Edge* RecordInfo::CreateEdge(const Type* type) {
if (type->isPointerType() || type->isReferenceType()) {
if (Edge* ptr = CreateEdge(type->getPointeeType().getTypePtrOrNull()))
- return new RawPtr(ptr, false, type->isReferenceType());
+ return new RawPtr(ptr, type->isReferenceType());
return 0;
}
@@ -597,12 +587,6 @@ Edge* RecordInfo::CreateEdge(const Type* type) {
TemplateArgs args;
- if (Config::IsRawPtr(info->name()) && info->GetTemplateArgs(1, &args)) {
- if (Edge* ptr = CreateEdge(args[0]))
- return new RawPtr(ptr, true, false);
- return 0;
- }
-
if (Config::IsRefPtr(info->name()) && info->GetTemplateArgs(1, &args)) {
if (Edge* ptr = CreateEdge(args[0]))
return new RefPtr(ptr);
diff --git a/chromium/tools/clang/blink_gc_plugin/RecordInfo.h b/chromium/tools/clang/blink_gc_plugin/RecordInfo.h
index b294ffe03b6..39c13f01c6d 100644
--- a/chromium/tools/clang/blink_gc_plugin/RecordInfo.h
+++ b/chromium/tools/clang/blink_gc_plugin/RecordInfo.h
@@ -101,7 +101,6 @@ class RecordInfo {
bool IsNonNewable();
bool IsOnlyPlacementNewable();
bool IsEagerlyFinalized();
- bool IsGCRefCounted();
bool HasDefinition();
diff --git a/chromium/tools/clang/scripts/blink_gc_plugin_flags.py b/chromium/tools/clang/scripts/blink_gc_plugin_flags.py
index 0b3e82ba86a..c2b8762bcb7 100755
--- a/chromium/tools/clang/scripts/blink_gc_plugin_flags.py
+++ b/chromium/tools/clang/scripts/blink_gc_plugin_flags.py
@@ -16,26 +16,14 @@ CLANG_LIB_PATH = os.path.normpath(os.path.join(
FLAGS = '-Xclang -add-plugin -Xclang blink-gc-plugin'
PREFIX= ' -Xclang -plugin-arg-blink-gc-plugin -Xclang '
-warn_raw_pointers = None
for arg in sys.argv[1:]:
- if arg == 'enable-oilpan=1':
- FLAGS += PREFIX + 'enable-oilpan'
- if warn_raw_pointers is None:
- warn_raw_pointers = True
- elif arg == 'dump-graph=1':
+ if arg == 'dump-graph=1':
FLAGS += PREFIX + 'dump-graph'
- elif arg == 'warn-raw-ptr=1':
- warn_raw_pointers = True
- elif arg == 'warn-raw-ptr=0':
- warn_raw_pointers = False
elif arg == 'warn-unneeded-finalizer=1':
FLAGS += PREFIX + 'warn-unneeded-finalizer'
elif arg.startswith('custom_clang_lib_path='):
CLANG_LIB_PATH = arg[len('custom_clang_lib_path='):]
-if warn_raw_pointers is True:
- FLAGS += PREFIX + 'warn-raw-ptr'
-
if not sys.platform in ['win32', 'cygwin']:
LIBSUFFIX = 'dylib' if sys.platform == 'darwin' else 'so'
FLAGS = ('-Xclang -load -Xclang "%s/libBlinkGCPlugin.%s" ' + FLAGS) % \
diff --git a/chromium/tools/clang/scripts/update.py b/chromium/tools/clang/scripts/update.py
index 0abb42af058..baac014965a 100755
--- a/chromium/tools/clang/scripts/update.py
+++ b/chromium/tools/clang/scripts/update.py
@@ -23,10 +23,11 @@ import time
import urllib2
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 = '264915'
+CLANG_REVISION = '269902'
use_head_revision = 'LLVM_FORCE_HEAD_REVISION' in os.environ
if use_head_revision:
@@ -82,6 +83,12 @@ 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',
+}
+
def DownloadUrl(url, output_file):
"""Download url into output_file."""
@@ -160,6 +167,14 @@ def WriteStampFile(s, path=STAMP_FILE):
def GetSvnRevision(svn_repo):
"""Returns current revision of the svn repo at svn_repo."""
+ if sys.platform == 'darwin':
+ # mac_files toolchain must be set for hermetic builds.
+ root = os.path.dirname(os.path.dirname(os.path.dirname(
+ os.path.dirname(__file__))))
+ sys.path.append(os.path.join(root, 'build'))
+ import mac_toolchain
+
+ mac_toolchain.SetToolchainEnvironment()
svn_info = subprocess.check_output('svn info ' + svn_repo, shell=True)
m = re.search(r'Revision: (\d+)', svn_info)
return m.group(1)
@@ -220,8 +235,8 @@ def RunCommand(command, msvc_arch=None, env=None, fail_hard=True):
def CopyFile(src, dst):
"""Copy a file from src to dst."""
- shutil.copy(src, dst)
print "Copying %s to %s" % (src, dst)
+ shutil.copy(src, dst)
def CopyDirectoryContents(src, dst, filename_filter=None):
@@ -300,13 +315,13 @@ def DownloadHostGcc(args):
def AddCMakeToPath():
"""Download CMake and add it to PATH."""
if sys.platform == 'win32':
- zip_name = 'cmake-3.2.2-win32-x86.zip'
+ zip_name = 'cmake-3.4.3-win32-x86.zip'
cmake_dir = os.path.join(LLVM_BUILD_TOOLS_DIR,
- 'cmake-3.2.2-win32-x86', 'bin')
+ 'cmake-3.4.3-win32-x86', 'bin')
else:
suffix = 'Darwin' if sys.platform == 'darwin' else 'Linux'
- zip_name = 'cmake322_%s.tgz' % suffix
- cmake_dir = os.path.join(LLVM_BUILD_TOOLS_DIR, 'cmake322', 'bin')
+ zip_name = 'cmake343_%s.tgz' % suffix
+ cmake_dir = os.path.join(LLVM_BUILD_TOOLS_DIR, 'cmake343', 'bin')
if not os.path.exists(cmake_dir):
DownloadAndUnpack(CDS_URL + '/tools/' + zip_name, LLVM_BUILD_TOOLS_DIR)
os.environ['PATH'] = cmake_dir + os.pathsep + os.environ.get('PATH', '')
@@ -318,7 +333,7 @@ def AddGnuWinToPath():
return
gnuwin_dir = os.path.join(LLVM_BUILD_TOOLS_DIR, 'gnuwin')
- GNUWIN_VERSION = '1'
+ GNUWIN_VERSION = '4'
GNUWIN_STAMP = os.path.join(gnuwin_dir, 'stamp')
if ReadStampFile(GNUWIN_STAMP) == GNUWIN_VERSION:
print 'GNU Win tools already up to date.'
@@ -351,6 +366,13 @@ def GetVSVersion():
return vs_version
+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()])
+ CopyFile(dia_dll, target_dir)
+
+
def UpdateClang(args):
print 'Updating Clang to %s...' % PACKAGE_VERSION
@@ -384,6 +406,8 @@ def UpdateClang(args):
try:
DownloadAndUnpack(cds_full_url, LLVM_BUILD_DIR)
print 'clang %s unpacked' % PACKAGE_VERSION
+ if sys.platform == 'win32':
+ CopyDiaDllTo(os.path.join(LLVM_BUILD_DIR, 'bin'))
# Download the gold plugin if requested to by an environment variable.
# This is used by the CFI ClusterFuzz bot, and it's required for official
# builds on linux.
@@ -413,7 +437,7 @@ def UpdateClang(args):
Checkout('LLVM', LLVM_REPO_URL + '/llvm/trunk', LLVM_DIR)
Checkout('Clang', LLVM_REPO_URL + '/cfe/trunk', CLANG_DIR)
- if sys.platform == 'win32':
+ if sys.platform == 'win32' or use_head_revision:
Checkout('LLD', LLVM_REPO_URL + '/lld/trunk', LLD_DIR)
Checkout('compiler-rt', LLVM_REPO_URL + '/compiler-rt/trunk', COMPILER_RT_DIR)
if sys.platform == 'darwin':
@@ -476,6 +500,8 @@ def UpdateClang(args):
RunCommand(['cmake'] + bootstrap_args + [LLVM_DIR], msvc_arch='x64')
RunCommand(['ninja'], msvc_arch='x64')
if args.run_tests:
+ if sys.platform == 'win32':
+ CopyDiaDllTo(os.path.join(LLVM_BOOTSTRAP_DIR, 'bin'))
RunCommand(['ninja', 'check-all'], msvc_arch='x64')
RunCommand(['ninja', 'install'], msvc_arch='x64')
if args.gcc_toolchain:
@@ -584,7 +610,6 @@ def UpdateClang(args):
if cxx is not None: cc_args.append('-DCMAKE_CXX_COMPILER=' + cxx)
cmake_args += base_cmake_args + [
'-DLLVM_BINUTILS_INCDIR=' + binutils_incdir,
- '-DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD=WebAssembly',
'-DCMAKE_C_FLAGS=' + ' '.join(cflags),
'-DCMAKE_CXX_FLAGS=' + ' '.join(cxxflags),
'-DCMAKE_EXE_LINKER_FLAGS=' + ' '.join(ldflags),
@@ -608,8 +633,7 @@ def UpdateClang(args):
[cxx] + cxxflags + ['-print-file-name=libstdc++.so.6']).rstrip()
CopyFile(libstdcpp, os.path.join(LLVM_BUILD_DIR, 'lib'))
- # TODO(thakis): Remove "-d explain" once http://crbug.com/569337 is fixed.
- RunCommand(['ninja', '-d', 'explain'], msvc_arch='x64')
+ RunCommand(['ninja'], msvc_arch='x64')
if args.tools:
# If any Chromium tools were built, install those now.
@@ -760,6 +784,8 @@ def UpdateClang(args):
os.chdir(LLVM_BUILD_DIR)
RunCommand(['ninja', 'cr-check-all'], msvc_arch='x64')
if args.run_tests:
+ if sys.platform == 'win32':
+ CopyDiaDllTo(os.path.join(LLVM_BUILD_DIR, 'bin'))
os.chdir(LLVM_BUILD_DIR)
RunCommand(['ninja', 'check-all'], msvc_arch='x64')
@@ -781,6 +807,9 @@ def main():
'picks /opt/foo/bin/gcc')
parser.add_argument('--lto-gold-plugin', action='store_true',
help='build LLVM Gold plugin with LTO')
+ parser.add_argument('--llvm-force-head-revision', action='store_true',
+ help=('use the revision in the repo when printing '
+ 'the revision'))
parser.add_argument('--print-revision', action='store_true',
help='print current clang revision and exit.')
parser.add_argument('--print-clang-version', action='store_true',
@@ -824,7 +853,7 @@ def main():
global CLANG_REVISION, PACKAGE_VERSION
if args.print_revision:
- if use_head_revision:
+ if use_head_revision or args.llvm_force_head_revision:
print GetSvnRevision(LLVM_DIR)
else:
print PACKAGE_VERSION
diff --git a/chromium/tools/copyright_scanner/third_party_files_whitelist.txt b/chromium/tools/copyright_scanner/third_party_files_whitelist.txt
index 43fc3311682..91def8082e7 100644
--- a/chromium/tools/copyright_scanner/third_party_files_whitelist.txt
+++ b/chromium/tools/copyright_scanner/third_party_files_whitelist.txt
@@ -174,9 +174,6 @@ net/http/md4.h
# third-party code is taken from Mozilla, the license for which we already pick
# up from third_party/npapi/.
net/proxy/proxy_resolver_script.h
-# Copyright The Chromium Authors and Netscape Communications Corporation; BSD
-# and (MPL, GPL v2 or LGPL v2) licenses. Not used on Android.
-net/socket/ssl_client_socket_nss.cc
# Contains the word 'Copyright' in comments
ppapi/generators/idl_c_proto.py
ppapi/generators/idl_outfile.py
diff --git a/chromium/tools/cygprofile/cygprofile.cc b/chromium/tools/cygprofile/cygprofile.cc
index d699c3e355b..c7f12e8b49f 100644
--- a/chromium/tools/cygprofile/cygprofile.cc
+++ b/chromium/tools/cygprofile/cygprofile.cc
@@ -51,7 +51,27 @@ const char kLogFilenameFormat[] = "%scyglog.%d.%d-%d";
ThreadLog* const kMagicBeingConstructed = reinterpret_cast<ThreadLog*>(1);
// Per-thread pointer to the current log object.
-static __thread ThreadLog* g_tls_log = NULL;
+pthread_key_t g_tls_slot;
+
+// Used to initialize the tls slot, once per the entire process.
+pthread_once_t g_tls_slot_initializer_once = PTHREAD_ONCE_INIT;
+
+// This variable is to prevent re-entrancy in the __cyg_profile_func_enter()
+// while the TLS slot itself is being initialized. Volatile here is required
+// to avoid compiler optimizations as this need to be read in a re-entrant way.
+// This variable is written by one thread only, which is the first thread that
+// happens to run the TLSSlotInitializer(). In practice this will happen very
+// early in the startup process, as soon as the first instrumented function is
+// called.
+volatile bool g_tls_slot_being_initialized = false;
+
+// Initializes the global TLS slot. This is invoked only once per process.
+static void TLSSlotInitializer()
+{
+ g_tls_slot_being_initialized = true;
+ PCHECK(0 == pthread_key_create(&g_tls_slot, NULL));
+ g_tls_slot_being_initialized = false;
+}
// Returns light-weight process ID. On Linux, this is a system-wide unique
// thread id.
@@ -151,11 +171,11 @@ class Thread {
public:
Thread(const base::Closure& thread_callback)
: thread_callback_(thread_callback) {
- CHECK_EQ(0, pthread_create(&handle_, NULL, &Thread::EntryPoint, this));
+ PCHECK(0 == pthread_create(&handle_, NULL, &Thread::EntryPoint, this));
}
~Thread() {
- CHECK_EQ(0, pthread_join(handle_, NULL));
+ PCHECK(0 == pthread_join(handle_, NULL));
}
private:
@@ -163,8 +183,11 @@ class Thread {
// Disable logging on this thread. Although this routine is not instrumented
// (cygprofile.gyp provides that), the called routines are and thus will
// call instrumentation.
- CHECK(g_tls_log == NULL); // Must be 0 as this is a new thread.
- g_tls_log = kMagicBeingConstructed;
+ pthread_once(&g_tls_slot_initializer_once, TLSSlotInitializer);
+ ThreadLog* thread_log = reinterpret_cast<ThreadLog*>(
+ pthread_getspecific(g_tls_slot));
+ CHECK(thread_log == NULL); // Must be 0 as this is a new thread.
+ PCHECK(0 == pthread_setspecific(g_tls_slot, kMagicBeingConstructed));
Thread* const instance = reinterpret_cast<Thread*>(data);
instance->thread_callback_.Run();
@@ -199,7 +222,7 @@ ThreadLog::ThreadLog(const FlushCallback& flush_callback)
}
ThreadLog::~ThreadLog() {
- g_tls_log = NULL;
+ PCHECK(0 == pthread_setspecific(g_tls_slot, NULL));
}
void ThreadLog::AddEntry(void* address) {
@@ -358,16 +381,24 @@ void __cyg_profile_func_exit(void* this_fn, void* call_site)
__attribute__((no_instrument_function));
void __cyg_profile_func_enter(void* this_fn, void* callee_unused) {
- if (g_tls_log == NULL) {
- g_tls_log = kMagicBeingConstructed;
- ThreadLog* new_log = new ThreadLog();
- CHECK(new_log);
- g_logs_manager.Pointer()->AddLog(base::WrapUnique(new_log));
- g_tls_log = new_log;
+ // Avoid re-entrancy while initializing the TLS slot (once per process).
+ if (g_tls_slot_being_initialized)
+ return;
+
+ pthread_once(&g_tls_slot_initializer_once, TLSSlotInitializer);
+ ThreadLog* thread_log = reinterpret_cast<ThreadLog*>(
+ pthread_getspecific(g_tls_slot));
+
+ if (thread_log == NULL) {
+ PCHECK(0 == pthread_setspecific(g_tls_slot, kMagicBeingConstructed));
+ thread_log = new ThreadLog();
+ CHECK(thread_log);
+ g_logs_manager.Pointer()->AddLog(base::WrapUnique(thread_log));
+ PCHECK(0 == pthread_setspecific(g_tls_slot, thread_log));
}
- if (g_tls_log != kMagicBeingConstructed)
- g_tls_log->AddEntry(this_fn);
+ if (thread_log != kMagicBeingConstructed)
+ thread_log->AddEntry(this_fn);
}
void __cyg_profile_func_exit(void* this_fn, void* call_site) {}
diff --git a/chromium/tools/export_tarball/export_tarball.py b/chromium/tools/export_tarball/export_tarball.py
deleted file mode 100755
index 876b3d89d35..00000000000
--- a/chromium/tools/export_tarball/export_tarball.py
+++ /dev/null
@@ -1,197 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2012 The Chromium 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 tool creates a tarball with all the sources, but without .svn directories.
-
-It can also remove files which are not strictly required for build, so that
-the resulting tarball can be reasonably small (last time it was ~110 MB).
-
-Example usage:
-
-export_tarball.py /foo/bar
-
-The above will create file /foo/bar.tar.bz2.
-"""
-
-import optparse
-import os
-import subprocess
-import sys
-import tarfile
-
-
-NONESSENTIAL_DIRS = (
- 'breakpad/src/processor/testdata',
- 'chrome/browser/resources/tracing/tests',
- 'chrome/common/extensions/docs',
- 'courgette/testdata',
- 'data',
- 'native_client/src/trusted/service_runtime/testdata',
- 'src/chrome/test/data',
- 'o3d/documentation',
- 'o3d/samples',
- 'o3d/tests',
- 'ppapi/examples',
- 'ppapi/native_client/tests',
- 'third_party/angle/samples/gles2_book',
- 'third_party/findbugs',
- 'third_party/hunspell_dictionaries',
- 'third_party/hunspell/tests',
- 'third_party/lighttpd',
- 'third_party/sqlite/src/test',
- 'third_party/sqlite/test',
- 'third_party/vc_80',
- 'third_party/xdg-utils/tests',
- 'third_party/yasm/source/patched-yasm/modules/arch/x86/tests',
- 'third_party/yasm/source/patched-yasm/modules/dbgfmts/dwarf2/tests',
- 'third_party/yasm/source/patched-yasm/modules/objfmts/bin/tests',
- 'third_party/yasm/source/patched-yasm/modules/objfmts/coff/tests',
- 'third_party/yasm/source/patched-yasm/modules/objfmts/elf/tests',
- 'third_party/yasm/source/patched-yasm/modules/objfmts/macho/tests',
- 'third_party/yasm/source/patched-yasm/modules/objfmts/rdf/tests',
- 'third_party/yasm/source/patched-yasm/modules/objfmts/win32/tests',
- 'third_party/yasm/source/patched-yasm/modules/objfmts/win64/tests',
- 'third_party/yasm/source/patched-yasm/modules/objfmts/xdf/tests',
- 'third_party/WebKit/LayoutTests',
- 'third_party/WebKit/Source/JavaScriptCore/tests',
- 'third_party/WebKit/Source/WebCore/ChangeLog',
- 'third_party/WebKit/Source/WebKit2',
- 'third_party/WebKit/Tools/Scripts',
- 'tools/gyp/test',
- 'v8/test',
- 'webkit/data/layout_tests',
- 'webkit/tools/test/reference_build',
-)
-
-TESTDIRS = (
- 'chrome/test/data',
- 'content/test/data',
- 'media/test/data',
- 'net/data',
-)
-
-
-def GetSourceDirectory():
- return os.path.realpath(
- os.path.join(os.path.dirname(__file__), '..', '..', '..', 'src'))
-
-
-# Workaround lack of the exclude parameter in add method in python-2.4.
-# TODO(phajdan.jr): remove the workaround when it's not needed on the bot.
-class MyTarFile(tarfile.TarFile):
- def set_remove_nonessential_files(self, remove):
- self.__remove_nonessential_files = remove
-
- def set_verbose(self, verbose):
- self.__verbose = verbose
-
- def __report_skipped(self, name):
- if self.__verbose:
- print 'D\t%s' % name
-
- def __report_added(self, name):
- if self.__verbose:
- print 'A\t%s' % name
-
- def add(self, name, arcname=None, recursive=True, exclude=None, filter=None):
- head, tail = os.path.split(name)
- if tail in ('.svn', '.git'):
- self.__report_skipped(name)
- return
-
- if self.__remove_nonessential_files:
- # WebKit change logs take quite a lot of space. This saves ~10 MB
- # in a bzip2-compressed tarball.
- if 'ChangeLog' in name:
- self.__report_skipped(name)
- return
-
- # Remove contents of non-essential directories, but preserve gyp files,
- # so that build/gyp_chromium can work.
- for nonessential_dir in (NONESSENTIAL_DIRS + TESTDIRS):
- dir_path = os.path.join(GetSourceDirectory(), nonessential_dir)
- if (name.startswith(dir_path) and
- os.path.isfile(name) and
- 'gyp' not in name):
- self.__report_skipped(name)
- return
-
- self.__report_added(name)
- tarfile.TarFile.add(self, name, arcname=arcname, recursive=recursive)
-
-
-def main(argv):
- parser = optparse.OptionParser()
- parser.add_option("--basename")
- parser.add_option("--remove-nonessential-files",
- dest="remove_nonessential_files",
- action="store_true", default=False)
- parser.add_option("--test-data", action="store_true")
- # TODO(phajdan.jr): Remove --xz option when it's not needed for compatibility.
- parser.add_option("--xz", action="store_true")
- parser.add_option("--verbose", action="store_true", default=False)
- parser.add_option("--progress", action="store_true", default=False)
-
- options, args = parser.parse_args(argv)
-
- if len(args) != 1:
- print 'You must provide only one argument: output file name'
- print '(without .tar.xz extension).'
- return 1
-
- if not os.path.exists(GetSourceDirectory()):
- print 'Cannot find the src directory ' + GetSourceDirectory()
- return 1
-
- # These two commands are from src/DEPS; please keep them in sync.
- if subprocess.call(['python', 'build/util/lastchange.py', '-o',
- 'build/util/LASTCHANGE'], cwd=GetSourceDirectory()) != 0:
- print 'Could not run build/util/lastchange.py to update LASTCHANGE.'
- return 1
- if subprocess.call(['python', 'build/util/lastchange.py', '-s',
- 'third_party/WebKit', '-o',
- 'build/util/LASTCHANGE.blink'],
- cwd=GetSourceDirectory()) != 0:
- print 'Could not run build/util/lastchange.py to update LASTCHANGE.blink.'
- return 1
-
- output_fullname = args[0] + '.tar'
- output_basename = options.basename or os.path.basename(args[0])
-
- archive = MyTarFile.open(output_fullname, 'w')
- archive.set_remove_nonessential_files(options.remove_nonessential_files)
- archive.set_verbose(options.verbose)
- try:
- if options.test_data:
- for directory in TESTDIRS:
- archive.add(os.path.join(GetSourceDirectory(), directory),
- arcname=os.path.join(output_basename, directory))
- else:
- archive.add(GetSourceDirectory(), arcname=output_basename)
- finally:
- archive.close()
-
- if options.progress:
- sys.stdout.flush()
- pv = subprocess.Popen(
- ['pv', '--force', output_fullname],
- stdout=subprocess.PIPE,
- stderr=sys.stdout)
- with open(output_fullname + '.xz', 'w') as f:
- rc = subprocess.call(['xz', '-9', '-'], stdin=pv.stdout, stdout=f)
- pv.wait()
- else:
- rc = subprocess.call(['xz', '-9', output_fullname])
-
- if rc != 0:
- print 'xz -9 failed!'
- return 1
-
- return 0
-
-
-if __name__ == "__main__":
- sys.exit(main(sys.argv[1:]))
diff --git a/chromium/tools/export_tarball/export_v8_tarball.py b/chromium/tools/export_tarball/export_v8_tarball.py
deleted file mode 100755
index b232c0aee73..00000000000
--- a/chromium/tools/export_tarball/export_v8_tarball.py
+++ /dev/null
@@ -1,135 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2011 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-"""Creates a tarball with V8 sources, but without .svn directories.
-
-This allows easy packaging of V8, synchronized with browser releases.
-
-Example usage:
-
-export_v8_tarball.py /foo/bar
-
-The above will create file /foo/bar/v8-VERSION.tar.bz2 if it doesn't exist.
-"""
-
-import optparse
-import os
-import re
-import subprocess
-import sys
-import tarfile
-
-_V8_MAJOR_VERSION_PATTERN = re.compile(r'#define\s+MAJOR_VERSION\s+(.*)')
-_V8_MINOR_VERSION_PATTERN = re.compile(r'#define\s+MINOR_VERSION\s+(.*)')
-_V8_BUILD_NUMBER_PATTERN = re.compile(r'#define\s+BUILD_NUMBER\s+(.*)')
-_V8_PATCH_LEVEL_PATTERN = re.compile(r'#define\s+PATCH_LEVEL\s+(.*)')
-
-_V8_PATTERNS = [
- _V8_MAJOR_VERSION_PATTERN,
- _V8_MINOR_VERSION_PATTERN,
- _V8_BUILD_NUMBER_PATTERN,
- _V8_PATCH_LEVEL_PATTERN]
-
-_NONESSENTIAL_DIRS = (
- 'third_party/icu',
-)
-
-
-def GetV8Version(v8_directory):
- """
- Returns version number as string based on the string
- contents of version.cc file.
- """
- with open(os.path.join(v8_directory, 'src', 'version.cc')) as version_file:
- version_contents = version_file.read()
-
- version_components = []
- for pattern in _V8_PATTERNS:
- version_components.append(pattern.search(version_contents).group(1).strip())
-
- if version_components[len(version_components) - 1] == '0':
- version_components.pop()
-
- return '.'.join(version_components)
-
-
-def GetSourceDirectory():
- return os.path.realpath(
- os.path.join(os.path.dirname(__file__), '..', '..', '..', 'src'))
-
-
-def GetV8Directory():
- return os.path.join(GetSourceDirectory(), 'v8')
-
-
-# Workaround lack of the exclude parameter in add method in python-2.4.
-# TODO(phajdan.jr): remove the workaround when it's not needed on the bot.
-class MyTarFile(tarfile.TarFile):
- def set_remove_nonessential_files(self, remove):
- self.__remove_nonessential_files = remove
-
- def add(self, name, arcname=None, recursive=True, exclude=None, filter=None):
- head, tail = os.path.split(name)
- if tail in ('.svn', '.git'):
- return
-
- if self.__remove_nonessential_files:
- # Remove contents of non-essential directories, but preserve gyp files,
- # so that build/gyp_chromium can work.
- for nonessential_dir in _NONESSENTIAL_DIRS:
- dir_path = os.path.join(GetV8Directory(), nonessential_dir)
- if (name.startswith(dir_path) and
- os.path.isfile(name) and
- 'gyp' not in name):
- return
-
- tarfile.TarFile.add(self, name, arcname=arcname, recursive=recursive)
-
-
-def main(argv):
- parser = optparse.OptionParser()
- options, args = parser.parse_args(argv)
-
- if len(args) != 1:
- print 'You must provide only one argument: output file directory'
- return 1
-
- v8_directory = GetV8Directory()
- if not os.path.exists(v8_directory):
- print 'Cannot find the v8 directory.'
- return 1
-
- v8_version = GetV8Version(v8_directory)
- print 'Packaging V8 version %s...' % v8_version
-
- subprocess.check_call(["make", "dependencies"], cwd=v8_directory)
-
- output_basename = 'v8-%s' % v8_version
-
- # Package full tarball.
- output_fullname = os.path.join(args[0], output_basename + '.tar.bz2')
- if not os.path.exists(output_fullname):
- archive = MyTarFile.open(output_fullname, 'w:bz2')
- archive.set_remove_nonessential_files(False)
- try:
- archive.add(v8_directory, arcname=output_basename)
- finally:
- archive.close()
-
- # Package lite tarball.
- output_fullname = os.path.join(args[0], output_basename + '-lite.tar.bz2')
- if not os.path.exists(output_fullname):
- archive = MyTarFile.open(output_fullname, 'w:bz2')
- archive.set_remove_nonessential_files(True)
- try:
- archive.add(v8_directory, arcname=output_basename)
- finally:
- archive.close()
-
- return 0
-
-
-if __name__ == '__main__':
- sys.exit(main(sys.argv[1:]))
diff --git a/chromium/tools/findit/OWNERS b/chromium/tools/findit/OWNERS
deleted file mode 100644
index 947f12e8524..00000000000
--- a/chromium/tools/findit/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-stgao@chromium.org
diff --git a/chromium/tools/findit/blame.py b/chromium/tools/findit/blame.py
deleted file mode 100644
index 5e5494e6cd5..00000000000
--- a/chromium/tools/findit/blame.py
+++ /dev/null
@@ -1,165 +0,0 @@
-# Copyright (c) 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.
-
-from threading import Lock
-
-from common import utils
-import crash_utils
-
-
-class Blame(object):
- """Represents a blame object.
-
- The object contains blame information for one line of stack, and this
- information is shown when there are no CLs that change the crashing files.
- Attributes:
- line_content: The content of the line to find the blame for.
- component_name: The name of the component for this line.
- stack_frame_index: The stack frame index of this file.
- file_name: The name of the file.
- line_number: The line that caused a crash.
- author: The author of this line on the latest revision.
- revision: The latest revision of this line before the crash revision.
- message: The commit message for the revision.
- time: When the revision was committed.
- url: The url of the change for the revision.
- range_start: The starting range of the regression for this component.
- range_end: The ending range of the regression.
-
- """
-
- def __init__(self, line_content, component_name, stack_frame_index,
- file_name, line_number, author, revision, message, time,
- url, range_start, range_end):
- # Set all the variables from the arguments.
- self.line_content = line_content
- self.component_name = component_name
- self.stack_frame_index = stack_frame_index
- self.file = file_name
- self.line_number = line_number
- self.author = author
- self.revision = revision
- self.message = message
- self.time = time
- self.url = url
- self.range_start = range_start
- self.range_end = range_end
-
-
-class BlameList(object):
- """Represents a list of blame objects.
-
- Thread-safe.
- """
-
- def __init__(self):
- self.blame_list = []
- self.blame_list_lock = Lock()
-
- def __getitem__(self, index):
- return self.blame_list[index]
-
- def FindBlame(self, callstack, component_to_crash_revision_dict,
- component_to_regression_dict, parsers,
- top_n_frames=10):
- """Given a stack within a stacktrace, retrieves blame information.
-
- Only either first 'top_n_frames' or the length of stack, whichever is
- shorter, results are returned. The default value of 'top_n_frames' is 10.
-
- Args:
- callstack: The list of stack frames.
- component_to_crash_revision_dict: A dictionary that maps component to its
- crash revision.
- component_to_regression_dict: A dictionary that maps component to its
- revision range.
- parsers: A list of two parsers, svn_parser and git_parser
- top_n_frames: A number of stack frames to show the blame result for.
- """
- # Only return blame information for first 'top_n_frames' frames.
- stack_frames = callstack.GetTopNFrames(top_n_frames)
- tasks = []
- # Iterate through frames in stack.
- for stack_frame in stack_frames:
- # If the component this line is from does not have a crash revision,
- # it is not possible to get blame information, so ignore this line.
- component_path = stack_frame.component_path
- if component_path not in component_to_crash_revision_dict:
- continue
-
- crash_revision = component_to_crash_revision_dict[
- component_path]['revision']
- range_start = None
- range_end = None
- repository_type = crash_utils.GetRepositoryType(crash_revision)
- repository_parser = parsers[repository_type]
-
- # If the revision is in SVN, and if regression information is available,
- # get it. For Git, we cannot know the ordering between hash numbers.
- if repository_type == 'svn':
- if component_to_regression_dict and \
- component_path in component_to_regression_dict:
- component_object = component_to_regression_dict[component_path]
- range_start = int(component_object['old_revision'])
- range_end = int(component_object['new_revision'])
-
- # Create a task to generate blame entry.
- tasks.append({
- 'function': self.__GenerateBlameEntry,
- 'args': [repository_parser, stack_frame, crash_revision,
- range_start, range_end]})
-
- # Run all the tasks.
- crash_utils.RunTasks(tasks)
-
- def __GenerateBlameEntry(self, repository_parser, stack_frame,
- crash_revision, range_start, range_end):
- """Generates blame list from the arguments."""
- stack_frame_index = stack_frame.index
- component_path = stack_frame.component_path
- component_name = stack_frame.component_name
- file_name = stack_frame.file_name
- file_path = stack_frame.file_path
- crashed_line_number = stack_frame.crashed_line_range[0]
-
- if file_path.startswith(component_path):
- file_path = file_path[len(component_path):]
-
- # Parse blame information.
- parsed_blame_info = repository_parser.ParseBlameInfo(
- component_path, file_path, crashed_line_number, crash_revision)
-
- # If it fails to retrieve information, do not do anything.
- if not parsed_blame_info:
- return
-
- # Create blame object from the parsed info and add it to the list.
- (line_content, revision, author, url, message, time) = parsed_blame_info
- blame = Blame(line_content, component_name, stack_frame_index, file_name,
- crashed_line_number, author, revision, message, time, url,
- range_start, range_end)
-
- with self.blame_list_lock:
- self.blame_list.append(blame)
-
- def FilterAndSortBlameList(self):
- """Filters and sorts the blame list."""
- # Sort the blame list by its position in stack.
- self.blame_list.sort(key=lambda blame: blame.stack_frame_index)
-
- filtered_blame_list = []
-
- for blame in self.blame_list:
- # If regression information is available, check if it needs to be
- # filtered.
- if blame.range_start and blame.range_end:
-
- # Discards results that are after the end of regression.
- if not utils.IsGitHash(blame.revision) and (
- int(blame.range_end) <= int(blame.revision)):
- continue
-
- filtered_blame_list.append(blame)
-
- self.blame_list = filtered_blame_list
diff --git a/chromium/tools/findit/chromium_deps.py b/chromium/tools/findit/chromium_deps.py
deleted file mode 100644
index 46436cbc7e0..00000000000
--- a/chromium/tools/findit/chromium_deps.py
+++ /dev/null
@@ -1,240 +0,0 @@
-# Copyright (c) 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.
-
-import base64
-import json
-import os
-import re
-import time
-import urllib2
-
-from common import utils
-
-
-_THIS_DIR = os.path.abspath(os.path.dirname(__file__))
-CONFIG = json.loads(open(os.path.join(_THIS_DIR,
- 'deps_config.json'), 'r').read())
-OLD_GIT_URL_PATTERN = re.compile(r'https?://git.chromium.org/(.*)')
-
-
-class _VarImpl(object):
-
- def __init__(self, local_scope):
- self._local_scope = local_scope
-
- def Lookup(self, var_name):
- if var_name in self._local_scope.get('vars', {}):
- return self._local_scope['vars'][var_name]
- raise Exception('Var is not defined: %s' % var_name)
-
-
-def _ParseDEPS(content):
- """Parse the DEPS file of chromium."""
- local_scope = {}
- var = _VarImpl(local_scope)
- global_scope = {
- 'Var': var.Lookup,
- 'deps': {},
- 'deps_os': {},
- 'include_rules': [],
- 'skip_child_includes': [],
- 'hooks': [],
- }
- exec(content, global_scope, local_scope)
-
- local_scope.setdefault('deps', {})
- local_scope.setdefault('deps_os', {})
-
- return (local_scope['deps'], local_scope['deps_os'])
-
-
-def _GetComponentName(path, host_dirs):
- """Return the component name of a path."""
- components_renamed = {
- 'webkit': 'blink',
- }
-
- for host_dir in host_dirs:
- if path.startswith(host_dir):
- path = path[len(host_dir):]
- name = path.split('/')[0].lower()
- if name in components_renamed:
- return components_renamed[name].lower()
- else:
- return name.lower()
-
- # Unknown path, return the whole path as component name.
- return '_'.join(path.split('/'))
-
-
-def _GetContentOfDEPS(revision):
- chromium_git_file_url_template = CONFIG['chromium_git_file_url']
-
- # Try .DEPS.git first, because before migration from SVN to GIT, the .DEPS.git
- # has the dependency in GIT repo while DEPS has dependency in SVN repo.
- url = chromium_git_file_url_template % (revision, '.DEPS.git')
- http_status_code, content = utils.GetHttpClient().Get(
- url, retries=5, retry_if_not=404)
-
- # If .DEPS.git is not found, use DEPS, assuming it is a commit after migration
- # from SVN to GIT.
- if http_status_code == 404:
- url = chromium_git_file_url_template % (revision, 'DEPS')
- http_status_code, content = utils.GetHttpClient().Get(url, retries=5)
-
- if http_status_code == 200:
- return base64.b64decode(content)
- else:
- return ''
-
-
-def GetChromiumComponents(chromium_revision,
- os_platform='unix',
- deps_file_downloader=_GetContentOfDEPS):
- """Return a list of components used by Chrome of the given revision.
-
- Args:
- chromium_revision: Revision of the Chrome build: svn revision, or git hash.
- os_platform: The target platform of the Chrome build, eg. win, mac, etc.
- deps_file_downloader: A function that takes the chromium_revision as input,
- and returns the content of the DEPS file. The returned
- content is assumed to be trusted input and will be
- evaluated as python code.
-
- Returns:
- A map from component path to parsed component name, repository URL,
- repository type and revision.
- Return None if an error occurs.
- """
- if os_platform.lower() == 'linux':
- os_platform = 'unix'
-
- chromium_git_base_url = CONFIG['chromium_git_base_url']
-
- if not utils.IsGitHash(chromium_revision):
- # Convert svn revision or commit position to Git hash.
- cr_rev_url_template = CONFIG['cr_rev_url']
- url = cr_rev_url_template % chromium_revision
- status_code, content = utils.GetHttpClient().Get(
- url, timeout=120, retries=5, retry_if_not=404)
- if status_code != 200 or not content:
- if status_code == 404:
- print 'Chromium commit position %s is not found.' % chromium_revision
- return None
-
- cr_rev_data = json.loads(content)
- if 'git_sha' not in cr_rev_data:
- return None
-
- if 'repo' not in cr_rev_data or cr_rev_data['repo'] != 'chromium/src':
- print ('%s seems like a commit position of "%s", but not "chromium/src".'
- % (chromium_revision, cr_rev_data['repo']))
- return None
-
- chromium_revision = cr_rev_data.get('git_sha')
- if not chromium_revision:
- return None
-
- # Download the content of DEPS file in chromium.
- deps_content = deps_file_downloader(chromium_revision)
- if not deps_content:
- return None
-
- all_deps = {}
-
- # Parse the content of DEPS file.
- deps, deps_os = _ParseDEPS(deps_content)
- all_deps.update(deps)
- if os_platform is not None:
- all_deps.update(deps_os.get(os_platform, {}))
-
- # Figure out components based on the dependencies.
- components = {}
- host_dirs = CONFIG['host_directories']
- for component_path, component_repo_url in all_deps.iteritems():
- if component_repo_url is None:
- # For some platform like iso, some component is ignored.
- continue
-
- name = _GetComponentName(component_path, host_dirs)
- repository, revision = component_repo_url.split('@')
- match = OLD_GIT_URL_PATTERN.match(repository)
- if match:
- repository = 'https://chromium.googlesource.com/%s' % match.group(1)
- is_git_hash = utils.IsGitHash(revision)
- if is_git_hash:
- repository_type = 'git'
- else:
- repository_type = 'svn'
- if not component_path.endswith('/'):
- component_path += '/'
- components[component_path] = {
- 'path': component_path,
- 'name': name,
- 'repository': repository,
- 'repository_type': repository_type,
- 'revision': revision
- }
-
- # Add chromium as a component.
- components['src/'] = {
- 'path': 'src/',
- 'name': 'chromium',
- 'repository': chromium_git_base_url,
- 'repository_type': 'git',
- 'revision': chromium_revision
- }
-
- return components
-
-
-def GetChromiumComponentRange(old_revision,
- new_revision,
- os_platform='unix',
- deps_file_downloader=_GetContentOfDEPS):
- """Return a list of components with their revision ranges.
-
- Args:
- old_revision: The old revision of a Chrome build.
- new_revision: The new revision of a Chrome build.
- os_platform: The target platform of the Chrome build, eg. win, mac, etc.
- deps_file_downloader: A function that takes the chromium_revision as input,
- and returns the content of the DEPS file. The returned
- content is assumed to be trusted input and will be
- evaluated as python code.
-
- Returns:
- A map from component path to its parsed regression and other information.
- Return None if an error occurs.
- """
- old_components = GetChromiumComponents(old_revision, os_platform,
- deps_file_downloader)
- if not old_components:
- return None
-
- new_components = GetChromiumComponents(new_revision, os_platform,
- deps_file_downloader)
- if not new_components:
- return None
-
- components = {}
- for path in new_components:
- new_component = new_components[path]
- old_revision = None
-
- if path in old_components:
- old_component = old_components[path]
- old_revision = old_component['revision']
-
- components[path] = {
- 'path': path,
- 'rolled': new_component['revision'] != old_revision,
- 'name': new_component['name'],
- 'old_revision': old_revision,
- 'new_revision': new_component['revision'],
- 'repository': new_component['repository'],
- 'repository_type': new_component['repository_type']
- }
-
- return components
diff --git a/chromium/tools/findit/chromium_deps_unittest.py b/chromium/tools/findit/chromium_deps_unittest.py
deleted file mode 100644
index 7f64a12b8fd..00000000000
--- a/chromium/tools/findit/chromium_deps_unittest.py
+++ /dev/null
@@ -1,189 +0,0 @@
-# Copyright (c) 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.
-
-import unittest
-
-import chromium_deps
-from common import utils
-
-
-class ChromiumDEPSTest(unittest.TestCase):
- DEPS_TEMPLATE = """
-vars = {
- "googlecode_url": "http://%%s.googlecode.com/svn",
- "webkit_trunk": "http://src.chromium.org/blink/trunk",
- "webkit_revision": "%s",
- "chromium_git": "https://chromium.googlesource.com",
-}
-
-deps = {
- "src/breakpad/src":
- (Var("googlecode_url") %% "google-breakpad") + "/trunk/src@%s",
-
- "src/third_party/WebKit":
- Var("webkit_trunk") + "@" + Var("webkit_revision"),
-}
-
-deps_os = {
- "unix": {
- "src/third_party/liblouis/src":
- Var("chromium_git") +
- "/external/liblouis.git@%s",
- }
-}
-"""
-
- def __init__(self, *args, **kwargs):
- super(ChromiumDEPSTest, self).__init__(*args, **kwargs)
-
- def testGetChromiumComponents(self):
- chromium_revision = '283296'
- chromium_revision_git_hash = 'b041fda2e8493dcb26aac08deb493943df240cbb'
- webkit_revision = '178200'
- breakpad_revision = '1345'
- liblouis_commit_hashcode = '3c2daee56250162e5a75830871601d74328d39f5'
-
- def _GetContentOfDEPS(chromium_revision_tmp):
- self.assertEqual(chromium_revision_tmp, chromium_revision_git_hash)
- return self.DEPS_TEMPLATE % (webkit_revision, breakpad_revision,
- liblouis_commit_hashcode)
-
- expected_results = {
- 'src/breakpad/src/': {
- 'path': 'src/breakpad/src/',
- 'repository_type': 'svn',
- 'name': 'breakpad',
- 'repository': 'http://google-breakpad.googlecode.com/svn/trunk/src',
- 'revision': breakpad_revision
- },
- 'src/third_party/liblouis/src/': {
- 'path': 'src/third_party/liblouis/src/',
- 'repository_type': 'git',
- 'name': 'liblouis',
- 'repository':
- 'https://chromium.googlesource.com/external/liblouis.git',
- 'revision': liblouis_commit_hashcode
- },
- 'src/': {
- 'path': 'src/',
- 'repository_type': 'git',
- 'name': 'chromium',
- 'repository': 'https://chromium.googlesource.com/chromium/src/',
- 'revision': chromium_revision_git_hash
- },
- 'src/third_party/WebKit/': {
- 'path': 'src/third_party/WebKit/',
- 'repository_type': 'svn',
- 'name': 'blink',
- 'repository': 'http://src.chromium.org/blink/trunk',
- 'revision': webkit_revision
- }
- }
-
- components = chromium_deps.GetChromiumComponents(
- chromium_revision, deps_file_downloader=_GetContentOfDEPS)
- self.assertEqual(expected_results, components)
-
- def testGetChromiumComponentRange(self):
- chromium_revision1 = '283200'
- chromium_revision_git_hash1 = 'c53c387f46a2ff0cf7c072222b826cff0817a80f'
- webkit_revision1 = '178084'
- breakpad_revision1 = '1345'
- liblouis_commit_hashcode1 = '3c2daee56250162e5a75830871601d74328d39f5'
-
- chromium_revision2 = '283296'
- chromium_revision_git_hash2 = 'b041fda2e8493dcb26aac08deb493943df240cbb'
- webkit_revision2 = '178200'
- breakpad_revision2 = '1345'
- liblouis_commit_hashcode2 = '3c2daee56250162e5a75830871601d74328d39f5'
-
- def _GetContentOfDEPS(chromium_revision):
- chromium_revision = str(chromium_revision)
- if chromium_revision == chromium_revision_git_hash1:
- return self.DEPS_TEMPLATE % (webkit_revision1, breakpad_revision1,
- liblouis_commit_hashcode1)
- else:
- self.assertEqual(chromium_revision, chromium_revision_git_hash2)
- return self.DEPS_TEMPLATE % (webkit_revision2, breakpad_revision2,
- liblouis_commit_hashcode2)
-
- expected_results = {
- 'src/breakpad/src/': {
- 'old_revision': breakpad_revision1,
- 'name': 'breakpad',
- 'repository': 'http://google-breakpad.googlecode.com/svn/trunk/src',
- 'rolled': False,
- 'new_revision': breakpad_revision2,
- 'path': 'src/breakpad/src/',
- 'repository_type': 'svn'
- },
- 'src/third_party/liblouis/src/': {
- 'old_revision': liblouis_commit_hashcode1,
- 'name': 'liblouis',
- 'repository':
- 'https://chromium.googlesource.com/external/liblouis.git',
- 'rolled': False,
- 'new_revision': liblouis_commit_hashcode2,
- 'path': 'src/third_party/liblouis/src/',
- 'repository_type': 'git'
- },
- 'src/': {
- 'old_revision': chromium_revision_git_hash1,
- 'name': 'chromium',
- 'repository': 'https://chromium.googlesource.com/chromium/src/',
- 'rolled': True,
- 'new_revision': chromium_revision_git_hash2,
- 'path': 'src/',
- 'repository_type': 'git'
- },
- 'src/third_party/WebKit/': {
- 'old_revision': webkit_revision1,
- 'name': 'blink',
- 'repository': 'http://src.chromium.org/blink/trunk',
- 'rolled': True,
- 'new_revision': webkit_revision2,
- 'path': 'src/third_party/WebKit/',
- 'repository_type': 'svn'
- }
- }
-
- components = chromium_deps.GetChromiumComponentRange(
- chromium_revision1, chromium_revision2,
- deps_file_downloader=_GetContentOfDEPS)
- self.assertEqual(expected_results, components)
-
- def _VerifyGitHashForAllComponents(self, deps):
- self.assertTrue(deps)
- self.assertTrue(isinstance(deps, dict))
- for component in deps.values():
- for key in ['revision', 'old_revision', 'new_revision']:
- if key in component:
- self.assertTrue(utils.IsGitHash(component[key]))
-
- def testComponentRangeCrossGitMigrationPoint(self):
- # The old revision is from svn.
- # The new revision is from git.
- deps = chromium_deps.GetChromiumComponentRange(
- '291440',
- '744746cc51ef81c8f8d727fafa46b14d1c03fe44')
- self._VerifyGitHashForAllComponents(deps)
-
- def testGetSvnRevision(self):
- # For this case, svn revision needs converting to git hash and there will be
- # .DEPS.git and DEPS.
- deps = chromium_deps.GetChromiumComponents(284750)
- self._VerifyGitHashForAllComponents(deps)
-
- def testGetGitRevisionWithoutDEPS_dot_GIT(self):
- # For this case, there is only DEPS, not .DEPS.git.
- deps = chromium_deps.GetChromiumComponents(
- 'f8b3fe9660d8dda318800f55d5e29799bbfd43f7')
- self._VerifyGitHashForAllComponents(deps)
-
-
- def testGetGitRevisionWithDEPS_dot_GIT(self):
- # For this case, there will be .DEPS.git.
- deps = chromium_deps.GetChromiumComponents(
- '8ae88241aa9f224e8ce97250f32469d616e437aa')
- self._VerifyGitHashForAllComponents(deps)
diff --git a/chromium/tools/findit/common/__init__.py b/chromium/tools/findit/common/__init__.py
deleted file mode 100644
index 31f0497a8a5..00000000000
--- a/chromium/tools/findit/common/__init__.py
+++ /dev/null
@@ -1,4 +0,0 @@
-# Copyright (c) 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.
-
diff --git a/chromium/tools/findit/common/cacert.pem b/chromium/tools/findit/common/cacert.pem
deleted file mode 100644
index c9ea29d7ee0..00000000000
--- a/chromium/tools/findit/common/cacert.pem
+++ /dev/null
@@ -1,2186 +0,0 @@
-# Source: http://pki.google.com/roots.pem
-# Updated at: Wed Dec 17 18:17:42 PST 2014
-
-# Issuer: CN=GTE CyberTrust Global Root O=GTE Corporation OU=GTE CyberTrust Solutions, Inc.
-# Subject: CN=GTE CyberTrust Global Root O=GTE Corporation OU=GTE CyberTrust Solutions, Inc.
-# Label: "GTE CyberTrust Global Root"
-# Serial: 421
-# MD5 Fingerprint: ca:3d:d3:68:f1:03:5c:d0:32:fa:b8:2b:59:e8:5a:db
-# SHA1 Fingerprint: 97:81:79:50:d8:1c:96:70:cc:34:d8:09:cf:79:44:31:36:7e:f4:74
-# SHA256 Fingerprint: a5:31:25:18:8d:21:10:aa:96:4b:02:c7:b7:c6:da:32:03:17:08:94:e5:fb:71:ff:fb:66:67:d5:e6:81:0a:36
------BEGIN CERTIFICATE-----
-MIICWjCCAcMCAgGlMA0GCSqGSIb3DQEBBAUAMHUxCzAJBgNVBAYTAlVTMRgwFgYD
-VQQKEw9HVEUgQ29ycG9yYXRpb24xJzAlBgNVBAsTHkdURSBDeWJlclRydXN0IFNv
-bHV0aW9ucywgSW5jLjEjMCEGA1UEAxMaR1RFIEN5YmVyVHJ1c3QgR2xvYmFsIFJv
-b3QwHhcNOTgwODEzMDAyOTAwWhcNMTgwODEzMjM1OTAwWjB1MQswCQYDVQQGEwJV
-UzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYDVQQLEx5HVEUgQ3liZXJU
-cnVzdCBTb2x1dGlvbnMsIEluYy4xIzAhBgNVBAMTGkdURSBDeWJlclRydXN0IEds
-b2JhbCBSb290MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVD6C28FCc6HrH
-iM3dFw4usJTQGz0O9pTAipTHBsiQl8i4ZBp6fmw8U+E3KHNgf7KXUwefU/ltWJTS
-r41tiGeA5u2ylc9yMcqlHHK6XALnZELn+aks1joNrI1CqiQBOeacPwGFVw1Yh0X4
-04Wqk2kmhXBIgD8SFcd5tB8FLztimQIDAQABMA0GCSqGSIb3DQEBBAUAA4GBAG3r
-GwnpXtlR22ciYaQqPEh346B8pt5zohQDhT37qw4wxYMWM4ETCJ57NE7fQMh017l9
-3PR2VX2bY1QY6fDq81yx2YtCHrnAlU66+tXifPVoYb+O7AWXX1uw16OFNMQkpw0P
-lZPvy5TYnh+dXIVtx6quTx8itc2VrbqnzPmrC3p/
------END CERTIFICATE-----
-
-# Issuer: CN=Thawte Server CA O=Thawte Consulting cc OU=Certification Services Division
-# Subject: CN=Thawte Server CA O=Thawte Consulting cc OU=Certification Services Division
-# Label: "Thawte Server CA"
-# Serial: 1
-# MD5 Fingerprint: c5:70:c4:a2:ed:53:78:0c:c8:10:53:81:64:cb:d0:1d
-# SHA1 Fingerprint: 23:e5:94:94:51:95:f2:41:48:03:b4:d5:64:d2:a3:a3:f5:d8:8b:8c
-# SHA256 Fingerprint: b4:41:0b:73:e2:e6:ea:ca:47:fb:c4:2f:8f:a4:01:8a:f4:38:1d:c5:4c:fa:a8:44:50:46:1e:ed:09:45:4d:e9
------BEGIN CERTIFICATE-----
-MIIDEzCCAnygAwIBAgIBATANBgkqhkiG9w0BAQQFADCBxDELMAkGA1UEBhMCWkEx
-FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYD
-VQQKExRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlv
-biBTZXJ2aWNlcyBEaXZpc2lvbjEZMBcGA1UEAxMQVGhhd3RlIFNlcnZlciBDQTEm
-MCQGCSqGSIb3DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0ZS5jb20wHhcNOTYwODAx
-MDAwMDAwWhcNMjAxMjMxMjM1OTU5WjCBxDELMAkGA1UEBhMCWkExFTATBgNVBAgT
-DFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3
-dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNl
-cyBEaXZpc2lvbjEZMBcGA1UEAxMQVGhhd3RlIFNlcnZlciBDQTEmMCQGCSqGSIb3
-DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0ZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQAD
-gY0AMIGJAoGBANOkUG7I/1Zr5s9dtuoMaHVHoqrC2oQl/Kj0R1HahbUgdJSGHg91
-yekIYfUGbTBuFRkC6VLAYttNmZ7iagxEOM3+vuNkCXDF/rFrKbYvScg71CcEJRCX
-L+eQbcAoQpnXTEPew/UhbVSfXcNY4cDk2VuwuNy0e982OsK1ZiIS1ocNAgMBAAGj
-EzARMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAB/pMaVz7lcxG
-7oWDTSEwjsrZqG9JGubaUeNgcGyEYRGhGshIPllDfU+VPaGLtwtimHp1it2ITk6e
-QNuozDJ0uW8NxuOzRAvZim+aKZuZGCg70eNAKJpaPNW15yAbi8qkq43pUdniTCxZ
-qdq5snUb9kLy78fyGPmJvKP/iiMucEc=
------END CERTIFICATE-----
-
-# Issuer: CN=Thawte Premium Server CA O=Thawte Consulting cc OU=Certification Services Division
-# Subject: CN=Thawte Premium Server CA O=Thawte Consulting cc OU=Certification Services Division
-# Label: "Thawte Premium Server CA"
-# Serial: 1
-# MD5 Fingerprint: 06:9f:69:79:16:66:90:02:1b:8c:8c:a2:c3:07:6f:3a
-# SHA1 Fingerprint: 62:7f:8d:78:27:65:63:99:d2:7d:7f:90:44:c9:fe:b3:f3:3e:fa:9a
-# SHA256 Fingerprint: ab:70:36:36:5c:71:54:aa:29:c2:c2:9f:5d:41:91:16:3b:16:2a:22:25:01:13:57:d5:6d:07:ff:a7:bc:1f:72
------BEGIN CERTIFICATE-----
-MIIDJzCCApCgAwIBAgIBATANBgkqhkiG9w0BAQQFADCBzjELMAkGA1UEBhMCWkEx
-FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYD
-VQQKExRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlv
-biBTZXJ2aWNlcyBEaXZpc2lvbjEhMB8GA1UEAxMYVGhhd3RlIFByZW1pdW0gU2Vy
-dmVyIENBMSgwJgYJKoZIhvcNAQkBFhlwcmVtaXVtLXNlcnZlckB0aGF3dGUuY29t
-MB4XDTk2MDgwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowgc4xCzAJBgNVBAYTAlpB
-MRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEdMBsG
-A1UEChMUVGhhd3RlIENvbnN1bHRpbmcgY2MxKDAmBgNVBAsTH0NlcnRpZmljYXRp
-b24gU2VydmljZXMgRGl2aXNpb24xITAfBgNVBAMTGFRoYXd0ZSBQcmVtaXVtIFNl
-cnZlciBDQTEoMCYGCSqGSIb3DQEJARYZcHJlbWl1bS1zZXJ2ZXJAdGhhd3RlLmNv
-bTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0jY2aovXwlue2oFBYo847kkE
-VdbQ7xwblRZH7xhINTpS9CtqBo87L+pW46+GjZ4X9560ZXUCTe/LCaIhUdib0GfQ
-ug2SBhRz1JPLlyoAnFxODLz6FVL88kRu2hFKbgifLy3j+ao6hnO2RlNYyIkFvYMR
-uHM/qgeN9EJN50CdHDcCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG
-9w0BAQQFAAOBgQAmSCwWwlj66BZ0DKqqX1Q/8tfJeGBeXm43YyJ3Nn6yF8Q0ufUI
-hfzJATj/Tb7yFkJD57taRvvBxhEf8UqwKEbJw8RCfbz6q1lu1bdRiBHjpIUZa4JM
-pAwSremkrj/xw0llmozFyD4lt5SZu5IycQfwhl7tUCemDaYj+bvLpgcUQg==
------END CERTIFICATE-----
-
-# Issuer: O=Equifax OU=Equifax Secure Certificate Authority
-# Subject: O=Equifax OU=Equifax Secure Certificate Authority
-# Label: "Equifax Secure CA"
-# Serial: 903804111
-# MD5 Fingerprint: 67:cb:9d:c0:13:24:8a:82:9b:b2:17:1e:d1:1b:ec:d4
-# SHA1 Fingerprint: d2:32:09:ad:23:d3:14:23:21:74:e4:0d:7f:9d:62:13:97:86:63:3a
-# SHA256 Fingerprint: 08:29:7a:40:47:db:a2:36:80:c7:31:db:6e:31:76:53:ca:78:48:e1:be:bd:3a:0b:01:79:a7:07:f9:2c:f1:78
------BEGIN CERTIFICATE-----
-MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV
-UzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2Vy
-dGlmaWNhdGUgQXV0aG9yaXR5MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1
-MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0VxdWlmYXgxLTArBgNVBAsTJEVx
-dWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCBnzANBgkqhkiG9w0B
-AQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPRfM6f
-BeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+A
-cJkVV5MW8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kC
-AwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQ
-MA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlm
-aWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTgw
-ODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvSspXXR9gj
-IBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQF
-MAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUA
-A4GBAFjOKer89961zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y
-7qj/WsjTVbJmcVfewCHrPSqnI0kBBIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh
-1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee9570+sB3c4
------END CERTIFICATE-----
-
-# Issuer: O=VeriSign, Inc. OU=Class 3 Public Primary Certification Authority
-# Subject: O=VeriSign, Inc. OU=Class 3 Public Primary Certification Authority
-# Label: "Verisign Class 3 Public Primary Certification Authority"
-# Serial: 149843929435818692848040365716851702463
-# MD5 Fingerprint: 10:fc:63:5d:f6:26:3e:0d:f3:25:be:5f:79:cd:67:67
-# SHA1 Fingerprint: 74:2c:31:92:e6:07:e4:24:eb:45:49:54:2b:e1:bb:c5:3e:61:74:e2
-# SHA256 Fingerprint: e7:68:56:34:ef:ac:f6:9a:ce:93:9a:6b:25:5b:7b:4f:ab:ef:42:93:5b:50:a2:65:ac:b5:cb:60:27:e4:4e:70
------BEGIN CERTIFICATE-----
-MIICPDCCAaUCEHC65B0Q2Sk0tjjKewPMur8wDQYJKoZIhvcNAQECBQAwXzELMAkG
-A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz
-cyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2
-MDEyOTAwMDAwMFoXDTI4MDgwMTIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV
-BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmlt
-YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN
-ADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhE
-BarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/is
-I19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0G
-CSqGSIb3DQEBAgUAA4GBALtMEivPLCYATxQT3ab7/AoRhIzzKBxnki98tsX63/Do
-lbwdj2wsqFHMc9ikwFPwTtYmwHYBV4GSXiHx0bH/59AhWM1pF+NEHJwZRDmJXNyc
-AA9WjQKZ7aKQRUzkuxCkPfAyAw7xzvjoyVGM5mKf5p/AfbdynMk2OmufTqj/ZA1k
------END CERTIFICATE-----
-
-# Issuer: O=VeriSign, Inc. OU=Class 3 Public Primary Certification Authority - G2/(c) 1998 VeriSign, Inc. - For authorized use only/VeriSign Trust Network
-# Subject: O=VeriSign, Inc. OU=Class 3 Public Primary Certification Authority - G2/(c) 1998 VeriSign, Inc. - For authorized use only/VeriSign Trust Network
-# Label: "Verisign Class 3 Public Primary Certification Authority - G2"
-# Serial: 167285380242319648451154478808036881606
-# MD5 Fingerprint: a2:33:9b:4c:74:78:73:d4:6c:e7:c1:f3:8d:cb:5c:e9
-# SHA1 Fingerprint: 85:37:1c:a6:e5:50:14:3d:ce:28:03:47:1b:de:3a:09:e8:f8:77:0f
-# SHA256 Fingerprint: 83:ce:3c:12:29:68:8a:59:3d:48:5f:81:97:3c:0f:91:95:43:1e:da:37:cc:5e:36:43:0e:79:c7:a8:88:63:8b
------BEGIN CERTIFICATE-----
-MIIDAjCCAmsCEH3Z/gfPqB63EHln+6eJNMYwDQYJKoZIhvcNAQEFBQAwgcExCzAJ
-BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xh
-c3MgMyBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcy
-MTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3Jp
-emVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMB4X
-DTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVTMRcw
-FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMyBQdWJsaWMg
-UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEo
-YykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5
-MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEB
-AQUAA4GNADCBiQKBgQDMXtERXVxp0KvTuWpMmR9ZmDCOFoUgRm1HP9SFIIThbbP4
-pO0M8RcPO/mn+SXXwc+EY/J8Y8+iR/LGWzOOZEAEaMGAuWQcRXfH2G71lSk8UOg0
-13gfqLptQ5GVj0VXXn7F+8qkBOvqlzdUMG+7AUcyM83cV5tkaWH4mx0ciU9cZwID
-AQABMA0GCSqGSIb3DQEBBQUAA4GBAFFNzb5cy5gZnBWyATl4Lk0PZ3BwmcYQWpSk
-U01UbSuvDV1Ai2TT1+7eVmGSX6bEHRBhNtMsJzzoKQm5EWR0zLVznxxIqbxhAe7i
-F6YM40AIOw7n60RzKprxaZLvcRTDOaxxp5EJb+RxBrO6WVcmeQD2+A2iMzAo1KpY
-oJ2daZH9
------END CERTIFICATE-----
-
-# Issuer: CN=GlobalSign Root CA O=GlobalSign nv-sa OU=Root CA
-# Subject: CN=GlobalSign Root CA O=GlobalSign nv-sa OU=Root CA
-# Label: "GlobalSign Root CA"
-# Serial: 4835703278459707669005204
-# MD5 Fingerprint: 3e:45:52:15:09:51:92:e1:b7:5d:37:9f:b1:87:29:8a
-# SHA1 Fingerprint: b1:bc:96:8b:d4:f4:9d:62:2a:a8:9a:81:f2:15:01:52:a4:1d:82:9c
-# SHA256 Fingerprint: eb:d4:10:40:e4:bb:3e:c7:42:c9:e3:81:d3:1e:f2:a4:1a:48:b6:68:5c:96:e7:ce:f3:c1:df:6c:d4:33:1c:99
------BEGIN CERTIFICATE-----
-MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG
-A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv
-b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw
-MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i
-YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT
-aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ
-jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp
-xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp
-1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG
-snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ
-U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8
-9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E
-BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B
-AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz
-yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE
-38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP
-AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad
-DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME
-HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==
------END CERTIFICATE-----
-
-# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R2
-# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R2
-# Label: "GlobalSign Root CA - R2"
-# Serial: 4835703278459682885658125
-# MD5 Fingerprint: 94:14:77:7e:3e:5e:fd:8f:30:bd:41:b0:cf:e7:d0:30
-# SHA1 Fingerprint: 75:e0:ab:b6:13:85:12:27:1c:04:f8:5f:dd:de:38:e4:b7:24:2e:fe
-# SHA256 Fingerprint: ca:42:dd:41:74:5f:d0:b8:1e:b9:02:36:2c:f9:d8:bf:71:9d:a1:bd:1b:1e:fc:94:6f:5b:4c:99:f4:2c:1b:9e
------BEGIN CERTIFICATE-----
-MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4G
-A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNp
-Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1
-MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMjETMBEG
-A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI
-hvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6ErPL
-v4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8
-eoLrvozps6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklq
-tTleiDTsvHgMCJiEbKjNS7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzd
-C9XZzPnqJworc5HGnRusyMvo4KD0L5CLTfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pa
-zq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6CygPCm48CAwEAAaOBnDCB
-mTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUm+IH
-V2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5n
-bG9iYWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG
-3lm0mi3f3BmGLjANBgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4Gs
-J0/WwbgcQ3izDJr86iw8bmEbTUsp9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO
-291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu01yiPqFbQfXf5WRDLenVOavS
-ot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG79G+dwfCMNYxd
-AfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7
-TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg==
------END CERTIFICATE-----
-
-# Issuer: CN=http://www.valicert.com/ O=ValiCert, Inc. OU=ValiCert Class 1 Policy Validation Authority
-# Subject: CN=http://www.valicert.com/ O=ValiCert, Inc. OU=ValiCert Class 1 Policy Validation Authority
-# Label: "ValiCert Class 1 VA"
-# Serial: 1
-# MD5 Fingerprint: 65:58:ab:15:ad:57:6c:1e:a8:a7:b5:69:ac:bf:ff:eb
-# SHA1 Fingerprint: e5:df:74:3c:b6:01:c4:9b:98:43:dc:ab:8c:e8:6a:81:10:9f:e4:8e
-# SHA256 Fingerprint: f4:c1:49:55:1a:30:13:a3:5b:c7:bf:fe:17:a7:f3:44:9b:c1:ab:5b:5a:0a:e7:4b:06:c2:3b:90:00:4c:01:04
------BEGIN CERTIFICATE-----
-MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0
-IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz
-BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDEgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y
-aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG
-9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNTIyMjM0OFoXDTE5MDYy
-NTIyMjM0OFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y
-azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs
-YXNzIDEgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw
-Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl
-cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDYWYJ6ibiWuqYvaG9Y
-LqdUHAZu9OqNSLwxlBfw8068srg1knaw0KWlAdcAAxIiGQj4/xEjm84H9b9pGib+
-TunRf50sQB1ZaG6m+FiwnRqP0z/x3BkGgagO4DrdyFNFCQbmD3DD+kCmDuJWBQ8Y
-TfwggtFzVXSNdnKgHZ0dwN0/cQIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFBoPUn0
-LBwGlN+VYH+Wexf+T3GtZMjdd9LvWVXoP+iOBSoh8gfStadS/pyxtuJbdxdA6nLW
-I8sogTLDAHkY7FkXicnGah5xyf23dKUlRWnFSKsZ4UWKJWsZ7uW7EvV/96aNUcPw
-nXS3qT6gpf+2SQMT2iLM7XGCK5nPOrf1LXLI
------END CERTIFICATE-----
-
-# Issuer: CN=http://www.valicert.com/ O=ValiCert, Inc. OU=ValiCert Class 2 Policy Validation Authority
-# Subject: CN=http://www.valicert.com/ O=ValiCert, Inc. OU=ValiCert Class 2 Policy Validation Authority
-# Label: "ValiCert Class 2 VA"
-# Serial: 1
-# MD5 Fingerprint: a9:23:75:9b:ba:49:36:6e:31:c2:db:f2:e7:66:ba:87
-# SHA1 Fingerprint: 31:7a:2a:d0:7f:2b:33:5e:f5:a1:c3:4e:4b:57:e8:b7:d8:f1:fc:a6
-# SHA256 Fingerprint: 58:d0:17:27:9c:d4:dc:63:ab:dd:b1:96:a6:c9:90:6c:30:c4:e0:87:83:ea:e8:c1:60:99:54:d6:93:55:59:6b
------BEGIN CERTIFICATE-----
-MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0
-IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz
-BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y
-aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG
-9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAwMTk1NFoXDTE5MDYy
-NjAwMTk1NFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y
-azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs
-YXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw
-Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl
-cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOOnHK5avIWZJV16vY
-dA757tn2VUdZZUcOBVXc65g2PFxTXdMwzzjsvUGJ7SVCCSRrCl6zfN1SLUzm1NZ9
-WlmpZdRJEy0kTRxQb7XBhVQ7/nHk01xC+YDgkRoKWzk2Z/M/VXwbP7RfZHM047QS
-v4dk+NoS/zcnwbNDu+97bi5p9wIDAQABMA0GCSqGSIb3DQEBBQUAA4GBADt/UG9v
-UJSZSWI4OB9L+KXIPqeCgfYrx+jFzug6EILLGACOTb2oWH+heQC1u+mNr0HZDzTu
-IYEZoDJJKPTEjlbVUjP9UNV+mWwD5MlM/Mtsq2azSiGM5bUMMj4QssxsodyamEwC
-W/POuZ6lcg5Ktz885hZo+L7tdEy8W9ViH0Pd
------END CERTIFICATE-----
-
-# Issuer: CN=http://www.valicert.com/ O=ValiCert, Inc. OU=ValiCert Class 3 Policy Validation Authority
-# Subject: CN=http://www.valicert.com/ O=ValiCert, Inc. OU=ValiCert Class 3 Policy Validation Authority
-# Label: "RSA Root Certificate 1"
-# Serial: 1
-# MD5 Fingerprint: a2:6f:53:b7:ee:40:db:4a:68:e7:fa:18:d9:10:4b:72
-# SHA1 Fingerprint: 69:bd:8c:f4:9c:d3:00:fb:59:2e:17:93:ca:55:6a:f3:ec:aa:35:fb
-# SHA256 Fingerprint: bc:23:f9:8a:31:3c:b9:2d:e3:bb:fc:3a:5a:9f:44:61:ac:39:49:4c:4a:e1:5a:9e:9d:f1:31:e9:9b:73:01:9a
------BEGIN CERTIFICATE-----
-MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0
-IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz
-BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDMgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y
-aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG
-9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAwMjIzM1oXDTE5MDYy
-NjAwMjIzM1owgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y
-azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs
-YXNzIDMgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw
-Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl
-cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDjmFGWHOjVsQaBalfD
-cnWTq8+epvzzFlLWLU2fNUSoLgRNB0mKOCn1dzfnt6td3zZxFJmP3MKS8edgkpfs
-2Ejcv8ECIMYkpChMMFp2bbFc893enhBxoYjHW5tBbcqwuI4V7q0zK89HBFx1cQqY
-JJgpp0lZpd34t0NiYfPT4tBVPwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFa7AliE
-Zwgs3x/be0kz9dNnnfS0ChCzycUs4pJqcXgn8nCDQtM+z6lU9PHYkhaM0QTLS6vJ
-n0WuPIqpsHEzXcjFV9+vqDWzf4mH6eglkrh/hXqu1rweN1gqZ8mRzyqBPu3GOd/A
-PhmcGcwTTYJBtYze4D1gCCAPRX5ron+jjBXu
------END CERTIFICATE-----
-
-# Issuer: CN=VeriSign Class 3 Public Primary Certification Authority - G3 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 1999 VeriSign, Inc. - For authorized use only
-# Subject: CN=VeriSign Class 3 Public Primary Certification Authority - G3 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 1999 VeriSign, Inc. - For authorized use only
-# Label: "Verisign Class 3 Public Primary Certification Authority - G3"
-# Serial: 206684696279472310254277870180966723415
-# MD5 Fingerprint: cd:68:b6:a7:c7:c4:ce:75:e0:1d:4f:57:44:61:92:09
-# SHA1 Fingerprint: 13:2d:0d:45:53:4b:69:97:cd:b2:d5:c3:39:e2:55:76:60:9b:5c:c6
-# SHA256 Fingerprint: eb:04:cf:5e:b1:f3:9a:fa:76:2f:2b:b1:20:f2:96:cb:a5:20:c1:b9:7d:b1:58:95:65:b8:1c:b9:a1:7b:72:44
------BEGIN CERTIFICATE-----
-MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQsw
-CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl
-cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu
-LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT
-aWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp
-dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD
-VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT
-aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ
-bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu
-IENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg
-LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMu6nFL8eB8aHm8b
-N3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1EUGO+i2t
-KmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGu
-kxUccLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBm
-CC+Vk7+qRy+oRpfwEuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJ
-Xwzw3sJ2zq/3avL6QaaiMxTJ5Xpj055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWu
-imi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAERSWwauSCPc/L8my/uRan2Te
-2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5fj267Cz3qWhMe
-DGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC
-/Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565p
-F4ErWjfJXir0xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGt
-TxzhT5yvDwyd93gN2PQ1VoDat20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ==
------END CERTIFICATE-----
-
-# Issuer: CN=VeriSign Class 4 Public Primary Certification Authority - G3 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 1999 VeriSign, Inc. - For authorized use only
-# Subject: CN=VeriSign Class 4 Public Primary Certification Authority - G3 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 1999 VeriSign, Inc. - For authorized use only
-# Label: "Verisign Class 4 Public Primary Certification Authority - G3"
-# Serial: 314531972711909413743075096039378935511
-# MD5 Fingerprint: db:c8:f2:27:2e:b1:ea:6a:29:23:5d:fe:56:3e:33:df
-# SHA1 Fingerprint: c8:ec:8c:87:92:69:cb:4b:ab:39:e9:8d:7e:57:67:f3:14:95:73:9d
-# SHA256 Fingerprint: e3:89:36:0d:0f:db:ae:b3:d2:50:58:4b:47:30:31:4e:22:2f:39:c1:56:a0:20:14:4e:8d:96:05:61:79:15:06
------BEGIN CERTIFICATE-----
-MIIEGjCCAwICEQDsoKeLbnVqAc/EfMwvlF7XMA0GCSqGSIb3DQEBBQUAMIHKMQsw
-CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl
-cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu
-LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT
-aWduIENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp
-dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD
-VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT
-aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ
-bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu
-IENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg
-LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK3LpRFpxlmr8Y+1
-GQ9Wzsy1HyDkniYlS+BzZYlZ3tCD5PUPtbut8XzoIfzk6AzufEUiGXaStBO3IFsJ
-+mGuqPKljYXCKtbeZjbSmwL0qJJgfJxptI8kHtCGUvYynEFYHiK9zUVilQhu0Gbd
-U6LM8BDcVHOLBKFGMzNcF0C5nk3T875Vg+ixiY5afJqWIpA7iCXy0lOIAgwLePLm
-NxdLMEYH5IBtptiWLugs+BGzOA1mppvqySNb247i8xOOGlktqgLw7KSHZtzBP/XY
-ufTsgsbSPZUd5cBPhMnZo0QoBmrXRazwa2rvTl/4EYIeOGM0ZlDUPpNz+jDDZq3/
-ky2X7wMCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAj/ola09b5KROJ1WrIhVZPMq1
-CtRK26vdoV9TxaBXOcLORyu+OshWv8LZJxA6sQU8wHcxuzrTBXttmhwwjIDLk5Mq
-g6sFUYICABFna/OIYUdfA5PVWw3g8dShMjWFsjrbsIKr0csKvE+MW8VLADsfKoKm
-fjaF3H48ZwC15DtS4KjrXRX5xm3wrR0OhbepmnMUWluPQSjA1egtTaRezarZ7c7c
-2NU8Qh0XwRJdRTjDOPP8hS6DRkiy1yBfkjaP53kPmF6Z6PDQpLv1U70qzlmwr25/
-bLvSHgCwIe34QWKCudiyxLtGUPMxxY8BqHTr9Xgn2uf3ZkPznoM+IKrDNWCRzg==
------END CERTIFICATE-----
-
-# Issuer: CN=Entrust.net Secure Server Certification Authority O=Entrust.net OU=www.entrust.net/CPS incorp. by ref. (limits liab.)/(c) 1999 Entrust.net Limited
-# Subject: CN=Entrust.net Secure Server Certification Authority O=Entrust.net OU=www.entrust.net/CPS incorp. by ref. (limits liab.)/(c) 1999 Entrust.net Limited
-# Label: "Entrust.net Secure Server CA"
-# Serial: 927650371
-# MD5 Fingerprint: df:f2:80:73:cc:f1:e6:61:73:fc:f5:42:e9:c5:7c:ee
-# SHA1 Fingerprint: 99:a6:9b:e6:1a:fe:88:6b:4d:2b:82:00:7c:b8:54:fc:31:7e:15:39
-# SHA256 Fingerprint: 62:f2:40:27:8c:56:4c:4d:d8:bf:7d:9d:4f:6f:36:6e:a8:94:d2:2f:5f:34:d9:89:a9:83:ac:ec:2f:ff:ed:50
------BEGIN CERTIFICATE-----
-MIIE2DCCBEGgAwIBAgIEN0rSQzANBgkqhkiG9w0BAQUFADCBwzELMAkGA1UEBhMC
-VVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MTswOQYDVQQLEzJ3d3cuZW50cnVzdC5u
-ZXQvQ1BTIGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMc
-KGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDE6MDgGA1UEAxMxRW50cnVzdC5u
-ZXQgU2VjdXJlIFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw05OTA1
-MjUxNjA5NDBaFw0xOTA1MjUxNjM5NDBaMIHDMQswCQYDVQQGEwJVUzEUMBIGA1UE
-ChMLRW50cnVzdC5uZXQxOzA5BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5j
-b3JwLiBieSByZWYuIChsaW1pdHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBF
-bnRydXN0Lm5ldCBMaW1pdGVkMTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUg
-U2VydmVyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGdMA0GCSqGSIb3DQEBAQUA
-A4GLADCBhwKBgQDNKIM0VBuJ8w+vN5Ex/68xYMmo6LIQaO2f55M28Qpku0f1BBc/
-I0dNxScZgSYMVHINiC3ZH5oSn7yzcdOAGT9HZnuMNSjSuQrfJNqc1lB5gXpa0zf3
-wkrYKZImZNHkmGw6AIr1NJtl+O3jEP/9uElY3KDegjlrgbEWGWG5VLbmQwIBA6OC
-AdcwggHTMBEGCWCGSAGG+EIBAQQEAwIABzCCARkGA1UdHwSCARAwggEMMIHeoIHb
-oIHYpIHVMIHSMQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRW50cnVzdC5uZXQxOzA5
-BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5jb3JwLiBieSByZWYuIChsaW1p
-dHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBFbnRydXN0Lm5ldCBMaW1pdGVk
-MTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUgU2VydmVyIENlcnRpZmljYXRp
-b24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMCmgJ6AlhiNodHRwOi8vd3d3LmVu
-dHJ1c3QubmV0L0NSTC9uZXQxLmNybDArBgNVHRAEJDAigA8xOTk5MDUyNTE2MDk0
-MFqBDzIwMTkwNTI1MTYwOTQwWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAU8Bdi
-E1U9s/8KAGv7UISX8+1i0BowHQYDVR0OBBYEFPAXYhNVPbP/CgBr+1CEl/PtYtAa
-MAwGA1UdEwQFMAMBAf8wGQYJKoZIhvZ9B0EABAwwChsEVjQuMAMCBJAwDQYJKoZI
-hvcNAQEFBQADgYEAkNwwAvpkdMKnCqV8IY00F6j7Rw7/JXyNEwr75Ji174z4xRAN
-95K+8cPV1ZVqBLssziY2ZcgxxufuP+NXdYR6Ee9GTxj005i7qIcyunL2POI9n9cd
-2cNgQ4xYDiKWL2KjLB+6rQXvqzJ4h6BUcxm1XAX5Uj5tLUUL9wqT6u0G+bI=
------END CERTIFICATE-----
-
-# Issuer: CN=Entrust.net Certification Authority (2048) O=Entrust.net OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.)/(c) 1999 Entrust.net Limited
-# Subject: CN=Entrust.net Certification Authority (2048) O=Entrust.net OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.)/(c) 1999 Entrust.net Limited
-# Label: "Entrust.net Premium 2048 Secure Server CA"
-# Serial: 946059622
-# MD5 Fingerprint: ba:21:ea:20:d6:dd:db:8f:c1:57:8b:40:ad:a1:fc:fc
-# SHA1 Fingerprint: 80:1d:62:d0:7b:44:9d:5c:5c:03:5c:98:ea:61:fa:44:3c:2a:58:fe
-# SHA256 Fingerprint: d1:c3:39:ea:27:84:eb:87:0f:93:4f:c5:63:4e:4a:a9:ad:55:05:01:64:01:f2:64:65:d3:7a:57:46:63:35:9f
------BEGIN CERTIFICATE-----
-MIIEXDCCA0SgAwIBAgIEOGO5ZjANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChML
-RW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBp
-bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5
-IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENlcnRp
-ZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQxNzUwNTFaFw0xOTEy
-MjQxODIwNTFaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3
-LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxp
-YWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEG
-A1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgp
-MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArU1LqRKGsuqjIAcVFmQq
-K0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOLGp18EzoOH1u3Hs/lJBQe
-sYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSrhRSGlVuX
-MlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVT
-XTzWnLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/
-HoZdenoVve8AjhUiVBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH
-4QIDAQABo3QwcjARBglghkgBhvhCAQEEBAMCAAcwHwYDVR0jBBgwFoAUVeSB0RGA
-vtiJuQijMfmhJAkWuXAwHQYDVR0OBBYEFFXkgdERgL7YibkIozH5oSQJFrlwMB0G
-CSqGSIb2fQdBAAQQMA4bCFY1LjA6NC4wAwIEkDANBgkqhkiG9w0BAQUFAAOCAQEA
-WUesIYSKF8mciVMeuoCFGsY8Tj6xnLZ8xpJdGGQC49MGCBFhfGPjK50xA3B20qMo
-oPS7mmNz7W3lKtvtFKkrxjYR0CvrB4ul2p5cGZ1WEvVUKcgF7bISKo30Axv/55IQ
-h7A6tcOdBTcSo8f0FbnVpDkWm1M6I5HxqIKiaohowXkCIryqptau37AUX7iH0N18
-f3v/rxzP5tsHrV7bhZ3QKw0z2wTR5klAEyt2+z7pnIkPFc4YsIV4IU9rTw76NmfN
-B/L/CNDi3tm/Kq+4h4YhPATKt5Rof8886ZjXOP/swNlQ8C5LWK5Gb9Auw2DaclVy
-vUxFnmG6v4SBkgPR0ml8xQ==
------END CERTIFICATE-----
-
-# Issuer: CN=Baltimore CyberTrust Root O=Baltimore OU=CyberTrust
-# Subject: CN=Baltimore CyberTrust Root O=Baltimore OU=CyberTrust
-# Label: "Baltimore CyberTrust Root"
-# Serial: 33554617
-# MD5 Fingerprint: ac:b6:94:a5:9c:17:e0:d7:91:52:9b:b1:97:06:a6:e4
-# SHA1 Fingerprint: d4:de:20:d0:5e:66:fc:53:fe:1a:50:88:2c:78:db:28:52:ca:e4:74
-# SHA256 Fingerprint: 16:af:57:a9:f6:76:b0:ab:12:60:95:aa:5e:ba:de:f2:2a:b3:11:19:d6:44:ac:95:cd:4b:93:db:f3:f2:6a:eb
------BEGIN CERTIFICATE-----
-MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ
-RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD
-VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX
-DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y
-ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy
-VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr
-mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr
-IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK
-mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu
-XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy
-dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye
-jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1
-BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3
-DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92
-9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx
-jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0
-Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz
-ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS
-R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp
------END CERTIFICATE-----
-
-# Issuer: CN=Equifax Secure Global eBusiness CA-1 O=Equifax Secure Inc.
-# Subject: CN=Equifax Secure Global eBusiness CA-1 O=Equifax Secure Inc.
-# Label: "Equifax Secure Global eBusiness CA"
-# Serial: 1
-# MD5 Fingerprint: 8f:5d:77:06:27:c4:98:3c:5b:93:78:e7:d7:7d:9b:cc
-# SHA1 Fingerprint: 7e:78:4a:10:1c:82:65:cc:2d:e1:f1:6d:47:b4:40:ca:d9:0a:19:45
-# SHA256 Fingerprint: 5f:0b:62:ea:b5:e3:53:ea:65:21:65:16:58:fb:b6:53:59:f4:43:28:0a:4a:fb:d1:04:d7:7d:10:f9:f0:4c:07
------BEGIN CERTIFICATE-----
-MIICkDCCAfmgAwIBAgIBATANBgkqhkiG9w0BAQQFADBaMQswCQYDVQQGEwJVUzEc
-MBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5jLjEtMCsGA1UEAxMkRXF1aWZheCBT
-ZWN1cmUgR2xvYmFsIGVCdXNpbmVzcyBDQS0xMB4XDTk5MDYyMTA0MDAwMFoXDTIw
-MDYyMTA0MDAwMFowWjELMAkGA1UEBhMCVVMxHDAaBgNVBAoTE0VxdWlmYXggU2Vj
-dXJlIEluYy4xLTArBgNVBAMTJEVxdWlmYXggU2VjdXJlIEdsb2JhbCBlQnVzaW5l
-c3MgQ0EtMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAuucXkAJlsTRVPEnC
-UdXfp9E3j9HngXNBUmCbnaEXJnitx7HoJpQytd4zjTov2/KaelpzmKNc6fuKcxtc
-58O/gGzNqfTWK8D3+ZmqY6KxRwIP1ORROhI8bIpaVIRw28HFkM9yRcuoWcDNM50/
-o5brhTMhHD4ePmBudpxnhcXIw2ECAwEAAaNmMGQwEQYJYIZIAYb4QgEBBAQDAgAH
-MA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUvqigdHJQa0S3ySPY+6j/s1dr
-aGwwHQYDVR0OBBYEFL6ooHRyUGtEt8kj2Puo/7NXa2hsMA0GCSqGSIb3DQEBBAUA
-A4GBADDiAVGqx+pf2rnQZQ8w1j7aDRRJbpGTJxQx78T3LUX47Me/okENI7SS+RkA
-Z70Br83gcfxaz2TE4JaY0KNA4gGK7ycH8WUBikQtBmV1UsCGECAhX2xrD2yuCRyv
-8qIYNMR1pHMc8Y3c7635s3a0kr/clRAevsvIO1qEYBlWlKlV
------END CERTIFICATE-----
-
-# Issuer: CN=Equifax Secure eBusiness CA-1 O=Equifax Secure Inc.
-# Subject: CN=Equifax Secure eBusiness CA-1 O=Equifax Secure Inc.
-# Label: "Equifax Secure eBusiness CA 1"
-# Serial: 4
-# MD5 Fingerprint: 64:9c:ef:2e:44:fc:c6:8f:52:07:d0:51:73:8f:cb:3d
-# SHA1 Fingerprint: da:40:18:8b:91:89:a3:ed:ee:ae:da:97:fe:2f:9d:f5:b7:d1:8a:41
-# SHA256 Fingerprint: cf:56:ff:46:a4:a1:86:10:9d:d9:65:84:b5:ee:b5:8a:51:0c:42:75:b0:e5:f9:4f:40:bb:ae:86:5e:19:f6:73
------BEGIN CERTIFICATE-----
-MIICgjCCAeugAwIBAgIBBDANBgkqhkiG9w0BAQQFADBTMQswCQYDVQQGEwJVUzEc
-MBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5jLjEmMCQGA1UEAxMdRXF1aWZheCBT
-ZWN1cmUgZUJ1c2luZXNzIENBLTEwHhcNOTkwNjIxMDQwMDAwWhcNMjAwNjIxMDQw
-MDAwWjBTMQswCQYDVQQGEwJVUzEcMBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5j
-LjEmMCQGA1UEAxMdRXF1aWZheCBTZWN1cmUgZUJ1c2luZXNzIENBLTEwgZ8wDQYJ
-KoZIhvcNAQEBBQADgY0AMIGJAoGBAM4vGbwXt3fek6lfWg0XTzQaDJj0ItlZ1MRo
-RvC0NcWFAyDGr0WlIVFFQesWWDYyb+JQYmT5/VGcqiTZ9J2DKocKIdMSODRsjQBu
-WqDZQu4aIZX5UkxVWsUPOE9G+m34LjXWHXzr4vCwdYDIqROsvojvOm6rXyo4YgKw
-Env+j6YDAgMBAAGjZjBkMBEGCWCGSAGG+EIBAQQEAwIABzAPBgNVHRMBAf8EBTAD
-AQH/MB8GA1UdIwQYMBaAFEp4MlIR21kWNl7fwRQ2QGpHfEyhMB0GA1UdDgQWBBRK
-eDJSEdtZFjZe38EUNkBqR3xMoTANBgkqhkiG9w0BAQQFAAOBgQB1W6ibAxHm6VZM
-zfmpTMANmvPMZWnmJXbMWbfWVMMdzZmsGd20hdXgPfxiIKeES1hl8eL5lSE/9dR+
-WB5Hh1Q+WKG1tfgq73HnvMP2sUlG4tega+VWeponmHxGYhTnyfxuAxJ5gDgdSIKN
-/Bf+KpYrtWKmpj29f5JZzVoqgrI3eQ==
------END CERTIFICATE-----
-
-# Issuer: O=Equifax Secure OU=Equifax Secure eBusiness CA-2
-# Subject: O=Equifax Secure OU=Equifax Secure eBusiness CA-2
-# Label: "Equifax Secure eBusiness CA 2"
-# Serial: 930140085
-# MD5 Fingerprint: aa:bf:bf:64:97:da:98:1d:6f:c6:08:3a:95:70:33:ca
-# SHA1 Fingerprint: 39:4f:f6:85:0b:06:be:52:e5:18:56:cc:10:e1:80:e8:82:b3:85:cc
-# SHA256 Fingerprint: 2f:27:4e:48:ab:a4:ac:7b:76:59:33:10:17:75:50:6d:c3:0e:e3:8e:f6:ac:d5:c0:49:32:cf:e0:41:23:42:20
------BEGIN CERTIFICATE-----
-MIIDIDCCAomgAwIBAgIEN3DPtTANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV
-UzEXMBUGA1UEChMORXF1aWZheCBTZWN1cmUxJjAkBgNVBAsTHUVxdWlmYXggU2Vj
-dXJlIGVCdXNpbmVzcyBDQS0yMB4XDTk5MDYyMzEyMTQ0NVoXDTE5MDYyMzEyMTQ0
-NVowTjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkVxdWlmYXggU2VjdXJlMSYwJAYD
-VQQLEx1FcXVpZmF4IFNlY3VyZSBlQnVzaW5lc3MgQ0EtMjCBnzANBgkqhkiG9w0B
-AQEFAAOBjQAwgYkCgYEA5Dk5kx5SBhsoNviyoynF7Y6yEb3+6+e0dMKP/wXn2Z0G
-vxLIPw7y1tEkshHe0XMJitSxLJgJDR5QRrKDpkWNYmi7hRsgcDKqQM2mll/EcTc/
-BPO3QSQ5BxoeLmFYoBIL5aXfxavqN3HMHMg3OrmXUqesxWoklE6ce8/AatbfIb0C
-AwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEX
-MBUGA1UEChMORXF1aWZheCBTZWN1cmUxJjAkBgNVBAsTHUVxdWlmYXggU2VjdXJl
-IGVCdXNpbmVzcyBDQS0yMQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTkw
-NjIzMTIxNDQ1WjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUUJ4L6q9euSBIplBq
-y/3YIHqngnYwHQYDVR0OBBYEFFCeC+qvXrkgSKZQasv92CB6p4J2MAwGA1UdEwQF
-MAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUA
-A4GBAAyGgq3oThr1jokn4jVYPSm0B482UJW/bsGe68SQsoWou7dC4A8HOd/7npCy
-0cE+U58DRLB+S/Rv5Hwf5+Kx5Lia78O9zt4LMjTZ3ijtM2vE1Nc9ElirfQkty3D1
-E4qUoSek1nDFbZS1yX2doNLGCEnZZpum0/QL3MUmV+GRMOrN
------END CERTIFICATE-----
-
-# Issuer: CN=AddTrust Class 1 CA Root O=AddTrust AB OU=AddTrust TTP Network
-# Subject: CN=AddTrust Class 1 CA Root O=AddTrust AB OU=AddTrust TTP Network
-# Label: "AddTrust Low-Value Services Root"
-# Serial: 1
-# MD5 Fingerprint: 1e:42:95:02:33:92:6b:b9:5f:c0:7f:da:d6:b2:4b:fc
-# SHA1 Fingerprint: cc:ab:0e:a0:4c:23:01:d6:69:7b:dd:37:9f:cd:12:eb:24:e3:94:9d
-# SHA256 Fingerprint: 8c:72:09:27:9a:c0:4e:27:5e:16:d0:7f:d3:b7:75:e8:01:54:b5:96:80:46:e3:1f:52:dd:25:76:63:24:e9:a7
------BEGIN CERTIFICATE-----
-MIIEGDCCAwCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQGEwJTRTEU
-MBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3
-b3JrMSEwHwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3QwHhcNMDAwNTMw
-MTAzODMxWhcNMjAwNTMwMTAzODMxWjBlMQswCQYDVQQGEwJTRTEUMBIGA1UEChML
-QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSEwHwYD
-VQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUA
-A4IBDwAwggEKAoIBAQCWltQhSWDia+hBBwzexODcEyPNwTXH+9ZOEQpnXvUGW2ul
-CDtbKRY654eyNAbFvAWlA3yCyykQruGIgb3WntP+LVbBFc7jJp0VLhD7Bo8wBN6n
-tGO0/7Gcrjyvd7ZWxbWroulpOj0OM3kyP3CCkplhbY0wCI9xP6ZIVxn4JdxLZlyl
-dI+Yrsj5wAYi56xz36Uu+1LcsRVlIPo1Zmne3yzxbrww2ywkEtvrNTVokMsAsJch
-PXQhI2U0K7t4WaPW4XY5mqRJjox0r26kmqPZm9I4XJuiGMx1I4S+6+JNM3GOGvDC
-+Mcdoq0Dlyz4zyXG9rgkMbFjXZJ/Y/AlyVMuH79NAgMBAAGjgdIwgc8wHQYDVR0O
-BBYEFJWxtPCUtr3H2tERCSG+wa9J/RB7MAsGA1UdDwQEAwIBBjAPBgNVHRMBAf8E
-BTADAQH/MIGPBgNVHSMEgYcwgYSAFJWxtPCUtr3H2tERCSG+wa9J/RB7oWmkZzBl
-MQswCQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFk
-ZFRydXN0IFRUUCBOZXR3b3JrMSEwHwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENB
-IFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBACxtZBsfzQ3duQH6lmM0MkhHma6X
-7f1yFqZzR1r0693p9db7RcwpiURdv0Y5PejuvE1Uhh4dbOMXJ0PhiVYrqW9yTkkz
-43J8KiOavD7/KCrto/8cI7pDVwlnTUtiBi34/2ydYB7YHEt9tTEv2dB8Xfjea4MY
-eDdXL+gzB2ffHsdrKpV2ro9Xo/D0UrSpUwjP4E/TelOL/bscVjby/rK25Xa71SJl
-pz/+0WatC7xrmYbvP33zGDLKe8bjq2RGlfgmadlVg3sslgf/WSxEo8bl6ancoWOA
-WiFeIc9TVPC6b4nbqKqVz4vjccweGyBECMB6tkD9xOQ14R0WHNC8K47Wcdk=
------END CERTIFICATE-----
-
-# Issuer: CN=AddTrust External CA Root O=AddTrust AB OU=AddTrust External TTP Network
-# Subject: CN=AddTrust External CA Root O=AddTrust AB OU=AddTrust External TTP Network
-# Label: "AddTrust External Root"
-# Serial: 1
-# MD5 Fingerprint: 1d:35:54:04:85:78:b0:3f:42:42:4d:bf:20:73:0a:3f
-# SHA1 Fingerprint: 02:fa:f3:e2:91:43:54:68:60:78:57:69:4d:f5:e4:5b:68:85:18:68
-# SHA256 Fingerprint: 68:7f:a4:51:38:22:78:ff:f0:c8:b1:1f:8d:43:d5:76:67:1c:6e:b2:bc:ea:b4:13:fb:83:d9:65:d0:6d:2f:f2
------BEGIN CERTIFICATE-----
-MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEU
-MBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFs
-IFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290
-MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFowbzELMAkGA1UEBhMCU0Ux
-FDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRUcnVzdCBFeHRlcm5h
-bCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0EgUm9v
-dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvt
-H7xsD821+iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9
-uMq/NzgtHj6RQa1wVsfwTz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzX
-mk6vBbOmcZSccbNQYArHE504B4YCqOmoaSYYkKtMsE8jqzpPhNjfzp/haW+710LX
-a0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy2xSoRcRdKn23tNbE7qzN
-E0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv77+ldU9U0
-WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYD
-VR0PBAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0
-Jvf6xCZU7wO94CTLVBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRU
-cnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsx
-IjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3SCAQEwDQYJKoZIhvcN
-AQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZlj7DYd7usQWxH
-YINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5
-6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvC
-Nr4TDea9Y355e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEX
-c4g/VhsxOBi0cQ+azcgOno4uG+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5a
-mnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ=
------END CERTIFICATE-----
-
-# Issuer: CN=AddTrust Public CA Root O=AddTrust AB OU=AddTrust TTP Network
-# Subject: CN=AddTrust Public CA Root O=AddTrust AB OU=AddTrust TTP Network
-# Label: "AddTrust Public Services Root"
-# Serial: 1
-# MD5 Fingerprint: c1:62:3e:23:c5:82:73:9c:03:59:4b:2b:e9:77:49:7f
-# SHA1 Fingerprint: 2a:b6:28:48:5e:78:fb:f3:ad:9e:79:10:dd:6b:df:99:72:2c:96:e5
-# SHA256 Fingerprint: 07:91:ca:07:49:b2:07:82:aa:d3:c7:d7:bd:0c:df:c9:48:58:35:84:3e:b2:d7:99:60:09:ce:43:ab:6c:69:27
------BEGIN CERTIFICATE-----
-MIIEFTCCAv2gAwIBAgIBATANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQGEwJTRTEU
-MBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3
-b3JrMSAwHgYDVQQDExdBZGRUcnVzdCBQdWJsaWMgQ0EgUm9vdDAeFw0wMDA1MzAx
-MDQxNTBaFw0yMDA1MzAxMDQxNTBaMGQxCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtB
-ZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQIE5ldHdvcmsxIDAeBgNV
-BAMTF0FkZFRydXN0IFB1YmxpYyBDQSBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOC
-AQ8AMIIBCgKCAQEA6Rowj4OIFMEg2Dybjxt+A3S72mnTRqX4jsIMEZBRpS9mVEBV
-6tsfSlbunyNu9DnLoblv8n75XYcmYZ4c+OLspoH4IcUkzBEMP9smcnrHAZcHF/nX
-GCwwfQ56HmIexkvA/X1id9NEHif2P0tEs7c42TkfYNVRknMDtABp4/MUTu7R3AnP
-dzRGULD4EfL+OHn3Bzn+UZKXC1sIXzSGAa2Il+tmzV7R/9x98oTaunet3IAIx6eH
-1lWfl2royBFkuucZKT8Rs3iQhCBSWxHveNCD9tVIkNAwHM+A+WD+eeSI8t0A65RF
-62WUaUC6wNW0uLp9BBGo6zEFlpROWCGOn9Bg/QIDAQABo4HRMIHOMB0GA1UdDgQW
-BBSBPjfYkrAfd59ctKtzquf2NGAv+jALBgNVHQ8EBAMCAQYwDwYDVR0TAQH/BAUw
-AwEB/zCBjgYDVR0jBIGGMIGDgBSBPjfYkrAfd59ctKtzquf2NGAv+qFopGYwZDEL
-MAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQLExRBZGRU
-cnVzdCBUVFAgTmV0d29yazEgMB4GA1UEAxMXQWRkVHJ1c3QgUHVibGljIENBIFJv
-b3SCAQEwDQYJKoZIhvcNAQEFBQADggEBAAP3FUr4JNojVhaTdt02KLmuG7jD8WS6
-IBh4lSknVwW8fCr0uVFV2ocC3g8WFzH4qnkuCRO7r7IgGRLlk/lL+YPoRNWyQSW/
-iHVv/xD8SlTQX/D67zZzfRs2RcYhbbQVuE7PnFylPVoAjgbjPGsye/Kf8Lb93/Ao
-GEjwxrzQvzSAlsJKsW2Ox5BF3i9nrEUEo3rcVZLJR2bYGozH7ZxOmuASu7VqTITh
-4SINhwBk/ox9Yjllpu9CtoAlEmEBqCQTcAARJl/6NVDFSMwGR+gn2HCNX2TmoUQm
-XiLsks3/QppEIW1cxeMiHV9HEufOX1362KqxMy3ZdvJOOjMMK7MtkAY=
------END CERTIFICATE-----
-
-# Issuer: CN=AddTrust Qualified CA Root O=AddTrust AB OU=AddTrust TTP Network
-# Subject: CN=AddTrust Qualified CA Root O=AddTrust AB OU=AddTrust TTP Network
-# Label: "AddTrust Qualified Certificates Root"
-# Serial: 1
-# MD5 Fingerprint: 27:ec:39:47:cd:da:5a:af:e2:9a:01:65:21:a9:4c:bb
-# SHA1 Fingerprint: 4d:23:78:ec:91:95:39:b5:00:7f:75:8f:03:3b:21:1e:c5:4d:8b:cf
-# SHA256 Fingerprint: 80:95:21:08:05:db:4b:bc:35:5e:44:28:d8:fd:6e:c2:cd:e3:ab:5f:b9:7a:99:42:98:8e:b8:f4:dc:d0:60:16
------BEGIN CERTIFICATE-----
-MIIEHjCCAwagAwIBAgIBATANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJTRTEU
-MBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3
-b3JrMSMwIQYDVQQDExpBZGRUcnVzdCBRdWFsaWZpZWQgQ0EgUm9vdDAeFw0wMDA1
-MzAxMDQ0NTBaFw0yMDA1MzAxMDQ0NTBaMGcxCzAJBgNVBAYTAlNFMRQwEgYDVQQK
-EwtBZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQIE5ldHdvcmsxIzAh
-BgNVBAMTGkFkZFRydXN0IFF1YWxpZmllZCBDQSBSb290MIIBIjANBgkqhkiG9w0B
-AQEFAAOCAQ8AMIIBCgKCAQEA5B6a/twJWoekn0e+EV+vhDTbYjx5eLfpMLXsDBwq
-xBb/4Oxx64r1EW7tTw2R0hIYLUkVAcKkIhPHEWT/IhKauY5cLwjPcWqzZwFZ8V1G
-87B4pfYOQnrjfxvM0PC3KP0q6p6zsLkEqv32x7SxuCqg+1jxGaBvcCV+PmlKfw8i
-2O+tCBGaKZnhqkRFmhJePp1tUvznoD1oL/BLcHwTOK28FSXx1s6rosAx1i+f4P8U
-WfyEk9mHfExUE+uf0S0R+Bg6Ot4l2ffTQO2kBhLEO+GRwVY18BTcZTYJbqukB8c1
-0cIDMzZbdSZtQvESa0NvS3GU+jQd7RNuyoB/mC9suWXY6QIDAQABo4HUMIHRMB0G
-A1UdDgQWBBQ5lYtii1zJ1IC6WA+XPxUIQ8yYpzALBgNVHQ8EBAMCAQYwDwYDVR0T
-AQH/BAUwAwEB/zCBkQYDVR0jBIGJMIGGgBQ5lYtii1zJ1IC6WA+XPxUIQ8yYp6Fr
-pGkwZzELMAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQL
-ExRBZGRUcnVzdCBUVFAgTmV0d29yazEjMCEGA1UEAxMaQWRkVHJ1c3QgUXVhbGlm
-aWVkIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBABmrder4i2VhlRO6aQTv
-hsoToMeqT2QbPxj2qC0sVY8FtzDqQmodwCVRLae/DLPt7wh/bDxGGuoYQ992zPlm
-hpwsaPXpF/gxsxjE1kh9I0xowX67ARRvxdlu3rsEQmr49lx95dr6h+sNNVJn0J6X
-dgWTP5XHAeZpVTh/EGGZyeNfpso+gmNIquIISD6q8rKFYqa0p9m9N5xotS1WfbC3
-P6CxB9bpT9zeRXEwMn8bLgn5v1Kh7sKAPgZcLlVAwRv1cEWw3F369nJad9Jjzc9Y
-iQBCYz95OdBEsIJuQRno3eDBiFrRHnGTHyQwdOUeqN48Jzd/g66ed8/wMLH/S5no
-xqE=
------END CERTIFICATE-----
-
-# Issuer: CN=Entrust Root Certification Authority O=Entrust, Inc. OU=www.entrust.net/CPS is incorporated by reference/(c) 2006 Entrust, Inc.
-# Subject: CN=Entrust Root Certification Authority O=Entrust, Inc. OU=www.entrust.net/CPS is incorporated by reference/(c) 2006 Entrust, Inc.
-# Label: "Entrust Root Certification Authority"
-# Serial: 1164660820
-# MD5 Fingerprint: d6:a5:c3:ed:5d:dd:3e:00:c1:3d:87:92:1f:1d:3f:e4
-# SHA1 Fingerprint: b3:1e:b1:b7:40:e3:6c:84:02:da:dc:37:d4:4d:f5:d4:67:49:52:f9
-# SHA256 Fingerprint: 73:c1:76:43:4f:1b:c6:d5:ad:f4:5b:0e:76:e7:27:28:7c:8d:e5:76:16:c1:e6:e6:14:1a:2b:2c:bc:7d:8e:4c
------BEGIN CERTIFICATE-----
-MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMC
-VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0
-Lm5ldC9DUFMgaXMgaW5jb3Jwb3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMW
-KGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsGA1UEAxMkRW50cnVzdCBSb290IENl
-cnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0MloXDTI2MTEyNzIw
-NTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMTkw
-NwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSBy
-ZWZlcmVuY2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNV
-BAMTJEVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJ
-KoZIhvcNAQEBBQADggEPADCCAQoCggEBALaVtkNC+sZtKm9I35RMOVcF7sN5EUFo
-Nu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYszA9u3g3s+IIRe7bJWKKf4
-4LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOwwCj0Yzfv9
-KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGI
-rb68j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi
-94DkZfs0Nw4pgHBNrziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOB
-sDCBrTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAi
-gA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1MzQyWjAfBgNVHSMEGDAWgBRo
-kORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DHhmak8fdLQ/uE
-vW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA
-A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9t
-O1KzKtvn1ISMY/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6Zua
-AGAT/3B+XxFNSRuzFVJ7yVTav52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP
-9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTSW3iDVuycNsMm4hH2Z0kdkquM++v/
-eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0tHuu2guQOHXvgR1m
-0vdXcDazv/wor3ElhVsT/h5/WrQ8
------END CERTIFICATE-----
-
-# Issuer: CN=GeoTrust Global CA O=GeoTrust Inc.
-# Subject: CN=GeoTrust Global CA O=GeoTrust Inc.
-# Label: "GeoTrust Global CA"
-# Serial: 144470
-# MD5 Fingerprint: f7:75:ab:29:fb:51:4e:b7:77:5e:ff:05:3c:99:8e:f5
-# SHA1 Fingerprint: de:28:f4:a4:ff:e5:b9:2f:a3:c5:03:d1:a3:49:a7:f9:96:2a:82:12
-# SHA256 Fingerprint: ff:85:6a:2d:25:1d:cd:88:d3:66:56:f4:50:12:67:98:cf:ab:aa:de:40:79:9c:72:2d:e4:d2:b5:db:36:a7:3a
------BEGIN CERTIFICATE-----
-MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT
-MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i
-YWwgQ0EwHhcNMDIwNTIxMDQwMDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQG
-EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMSR2VvVHJ1c3Qg
-R2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2swYYzD9
-9BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjoBbdq
-fnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDv
-iS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU
-1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+
-bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5aszPeE4uwc2hGKceeoW
-MPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTA
-ephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVkDBF9qn1l
-uMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKIn
-Z57QzxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfS
-tQWVYrmm3ok9Nns4d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcF
-PseKUgzbFbS9bZvlxrFUaKnjaZC2mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Un
-hw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6pXE0zX5IJL4hmXXeXxx12E6nV
-5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvmMw==
------END CERTIFICATE-----
-
-# Issuer: CN=GeoTrust Global CA 2 O=GeoTrust Inc.
-# Subject: CN=GeoTrust Global CA 2 O=GeoTrust Inc.
-# Label: "GeoTrust Global CA 2"
-# Serial: 1
-# MD5 Fingerprint: 0e:40:a7:6c:de:03:5d:8f:d1:0f:e4:d1:8d:f9:6c:a9
-# SHA1 Fingerprint: a9:e9:78:08:14:37:58:88:f2:05:19:b0:6d:2b:0d:2b:60:16:90:7d
-# SHA256 Fingerprint: ca:2d:82:a0:86:77:07:2f:8a:b6:76:4f:f0:35:67:6c:fe:3e:5e:32:5e:01:21:72:df:3f:92:09:6d:b7:9b:85
------BEGIN CERTIFICATE-----
-MIIDZjCCAk6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBEMQswCQYDVQQGEwJVUzEW
-MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3QgR2xvYmFs
-IENBIDIwHhcNMDQwMzA0MDUwMDAwWhcNMTkwMzA0MDUwMDAwWjBEMQswCQYDVQQG
-EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3Qg
-R2xvYmFsIENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDvPE1A
-PRDfO1MA4Wf+lGAVPoWI8YkNkMgoI5kF6CsgncbzYEbYwbLVjDHZ3CB5JIG/NTL8
-Y2nbsSpr7iFY8gjpeMtvy/wWUsiRxP89c96xPqfCfWbB9X5SJBri1WeR0IIQ13hL
-TytCOb1kLUCgsBDTOEhGiKEMuzozKmKY+wCdE1l/bztyqu6mD4b5BWHqZ38MN5aL
-5mkWRxHCJ1kDs6ZgwiFAVvqgx306E+PsV8ez1q6diYD3Aecs9pYrEw15LNnA5IZ7
-S4wMcoKK+xfNAGw6EzywhIdLFnopsk/bHdQL82Y3vdj2V7teJHq4PIu5+pIaGoSe
-2HSPqht/XvT+RSIhAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE
-FHE4NvICMVNHK266ZUapEBVYIAUJMB8GA1UdIwQYMBaAFHE4NvICMVNHK266ZUap
-EBVYIAUJMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQUFAAOCAQEAA/e1K6td
-EPx7srJerJsOflN4WT5CBP51o62sgU7XAotexC3IUnbHLB/8gTKY0UvGkpMzNTEv
-/NgdRN3ggX+d6YvhZJFiCzkIjKx0nVnZellSlxG5FntvRdOW2TF9AjYPnDtuzywN
-A0ZF66D0f0hExghAzN4bcLUprbqLOzRldRtxIR0sFAqwlpW41uryZfspuk/qkZN0
-abby/+Ea0AzRdoXLiiW9l14sbxWZJue2Kf8i7MkCx1YAzUm5s2x7UwQa4qjJqhIF
-I8LO57sEAszAR6LkxCkvW0VXiVHuPOtSCP8HNR6fNWpHSlaY0VqFH4z1Ir+rzoPz
-4iIprn2DQKi6bA==
------END CERTIFICATE-----
-
-# Issuer: CN=GeoTrust Universal CA O=GeoTrust Inc.
-# Subject: CN=GeoTrust Universal CA O=GeoTrust Inc.
-# Label: "GeoTrust Universal CA"
-# Serial: 1
-# MD5 Fingerprint: 92:65:58:8b:a2:1a:31:72:73:68:5c:b4:a5:7a:07:48
-# SHA1 Fingerprint: e6:21:f3:35:43:79:05:9a:4b:68:30:9d:8a:2f:74:22:15:87:ec:79
-# SHA256 Fingerprint: a0:45:9b:9f:63:b2:25:59:f5:fa:5d:4c:6d:b3:f9:f7:2f:f1:93:42:03:35:78:f0:73:bf:1d:1b:46:cb:b9:12
------BEGIN CERTIFICATE-----
-MIIFaDCCA1CgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJVUzEW
-MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEeMBwGA1UEAxMVR2VvVHJ1c3QgVW5pdmVy
-c2FsIENBMB4XDTA0MDMwNDA1MDAwMFoXDTI5MDMwNDA1MDAwMFowRTELMAkGA1UE
-BhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xHjAcBgNVBAMTFUdlb1RydXN0
-IFVuaXZlcnNhbCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKYV
-VaCjxuAfjJ0hUNfBvitbtaSeodlyWL0AG0y/YckUHUWCq8YdgNY96xCcOq9tJPi8
-cQGeBvV8Xx7BDlXKg5pZMK4ZyzBIle0iN430SppyZj6tlcDgFgDgEB8rMQ7XlFTT
-QjOgNB0eRXbdT8oYN+yFFXoZCPzVx5zw8qkuEKmS5j1YPakWaDwvdSEYfyh3peFh
-F7em6fgemdtzbvQKoiFs7tqqhZJmr/Z6a4LauiIINQ/PQvE1+mrufislzDoR5G2v
-c7J2Ha3QsnhnGqQ5HFELZ1aD/ThdDc7d8Lsrlh/eezJS/R27tQahsiFepdaVaH/w
-mZ7cRQg+59IJDTWU3YBOU5fXtQlEIGQWFwMCTFMNaN7VqnJNk22CDtucvc+081xd
-VHppCZbW2xHBjXWotM85yM48vCR85mLK4b19p71XZQvk/iXttmkQ3CgaRr0BHdCX
-teGYO8A3ZNY9lO4L4fUorgtWv3GLIylBjobFS1J72HGrH4oVpjuDWtdYAVHGTEHZ
-f9hBZ3KiKN9gg6meyHv8U3NyWfWTehd2Ds735VzZC1U0oqpbtWpU5xPKV+yXbfRe
-Bi9Fi1jUIxaS5BZuKGNZMN9QAZxjiRqf2xeUgnA3wySemkfWWspOqGmJch+RbNt+
-nhutxx9z3SxPGWX9f5NAEC7S8O08ni4oPmkmM8V7AgMBAAGjYzBhMA8GA1UdEwEB
-/wQFMAMBAf8wHQYDVR0OBBYEFNq7LqqwDLiIJlF0XG0D08DYj3rWMB8GA1UdIwQY
-MBaAFNq7LqqwDLiIJlF0XG0D08DYj3rWMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG
-9w0BAQUFAAOCAgEAMXjmx7XfuJRAyXHEqDXsRh3ChfMoWIawC/yOsjmPRFWrZIRc
-aanQmjg8+uUfNeVE44B5lGiku8SfPeE0zTBGi1QrlaXv9z+ZhP015s8xxtxqv6fX
-IwjhmF7DWgh2qaavdy+3YL1ERmrvl/9zlcGO6JP7/TG37FcREUWbMPEaiDnBTzyn
-ANXH/KttgCJwpQzgXQQpAvvLoJHRfNbDflDVnVi+QTjruXU8FdmbyUqDWcDaU/0z
-uzYYm4UPFd3uLax2k7nZAY1IEKj79TiG8dsKxr2EoyNB3tZ3b4XUhRxQ4K5RirqN
-Pnbiucon8l+f725ZDQbYKxek0nxru18UGkiPGkzns0ccjkxFKyDuSN/n3QmOGKja
-QI2SJhFTYXNd673nxE0pN2HrrDktZy4W1vUAg4WhzH92xH3kt0tm7wNFYGm2DFKW
-koRepqO1pD4r2czYG0eq8kTaT/kD6PAUyz/zg97QwVTjt+gKN02LIFkDMBmhLMi9
-ER/frslKxfMnZmaGrGiR/9nmUxwPi1xpZQomyB40w11Re9epnAahNt3ViZS82eQt
-DF4JbAiXfKM9fJP/P6EUp8+1Xevb2xzEdt+Iub1FBZUbrvxGakyvSOPOrg/Sfuvm
-bJxPgWp6ZKy7PtXny3YuxadIwVyQD8vIP/rmMuGNG2+k5o7Y+SlIis5z/iw=
------END CERTIFICATE-----
-
-# Issuer: CN=GeoTrust Universal CA 2 O=GeoTrust Inc.
-# Subject: CN=GeoTrust Universal CA 2 O=GeoTrust Inc.
-# Label: "GeoTrust Universal CA 2"
-# Serial: 1
-# MD5 Fingerprint: 34:fc:b8:d0:36:db:9e:14:b3:c2:f2:db:8f:e4:94:c7
-# SHA1 Fingerprint: 37:9a:19:7b:41:85:45:35:0c:a6:03:69:f3:3c:2e:af:47:4f:20:79
-# SHA256 Fingerprint: a0:23:4f:3b:c8:52:7c:a5:62:8e:ec:81:ad:5d:69:89:5d:a5:68:0d:c9:1d:1c:b8:47:7f:33:f8:78:b9:5b:0b
------BEGIN CERTIFICATE-----
-MIIFbDCCA1SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEW
-MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVy
-c2FsIENBIDIwHhcNMDQwMzA0MDUwMDAwWhcNMjkwMzA0MDUwMDAwWjBHMQswCQYD
-VQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1
-c3QgVW5pdmVyc2FsIENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC
-AQCzVFLByT7y2dyxUxpZKeexw0Uo5dfR7cXFS6GqdHtXr0om/Nj1XqduGdt0DE81
-WzILAePb63p3NeqqWuDW6KFXlPCQo3RWlEQwAx5cTiuFJnSCegx2oG9NzkEtoBUG
-FF+3Qs17j1hhNNwqCPkuwwGmIkQcTAeC5lvO0Ep8BNMZcyfwqph/Lq9O64ceJHdq
-XbboW0W63MOhBW9Wjo8QJqVJwy7XQYci4E+GymC16qFjwAGXEHm9ADwSbSsVsaxL
-se4YuU6W3Nx2/zu+z18DwPw76L5GG//aQMJS9/7jOvdqdzXQ2o3rXhhqMcceujwb
-KNZrVMaqW9eiLBsZzKIC9ptZvTdrhrVtgrrY6slWvKk2WP0+GfPtDCapkzj4T8Fd
-IgbQl+rhrcZV4IErKIM6+vR7IVEAvlI4zs1meaj0gVbi0IMJR1FbUGrP20gaXT73
-y/Zl92zxlfgCOzJWgjl6W70viRu/obTo/3+NjN8D8WBOWBFM66M/ECuDmgFz2ZRt
-hAAnZqzwcEAJQpKtT5MNYQlRJNiS1QuUYbKHsu3/mjX/hVTK7URDrBs8FmtISgoc
-QIgfksILAAX/8sgCSqSqqcyZlpwvWOB94b67B9xfBHJcMTTD7F8t4D1kkCLm0ey4
-Lt1ZrtmhN79UNdxzMk+MBB4zsslG8dhcyFVQyWi9qLo2CQIDAQABo2MwYTAPBgNV
-HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAfBgNV
-HSMEGDAWgBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAOBgNVHQ8BAf8EBAMCAYYwDQYJ
-KoZIhvcNAQEFBQADggIBAGbBxiPz2eAubl/oz66wsCVNK/g7WJtAJDday6sWSf+z
-dXkzoS9tcBc0kf5nfo/sm+VegqlVHy/c1FEHEv6sFj4sNcZj/NwQ6w2jqtB8zNHQ
-L1EuxBRa3ugZ4T7GzKQp5y6EqgYweHZUcyiYWTjgAA1i00J9IZ+uPTqM1fp3DRgr
-Fg5fNuH8KrUwJM/gYwx7WBr+mbpCErGR9Hxo4sjoryzqyX6uuyo9DRXcNJW2GHSo
-ag/HtPQTxORb7QrSpJdMKu0vbBKJPfEncKpqA1Ihn0CoZ1Dy81of398j9tx4TuaY
-T1U6U+Pv8vSfx3zYWK8pIpe44L2RLrB27FcRz+8pRPPphXpgY+RdM4kX2TGq2tbz
-GDVyz4crL2MjhF2EjD9XoIj8mZEoJmmZ1I+XRL6O1UixpCgp8RW04eWe3fiPpm8m
-1wk8OhwRDqZsN/etRIcsKMfYdIKz0G9KV7s1KSegi+ghp4dkNl3M2Basx7InQJJV
-OCiNUW7dFGdTbHFcJoRNdVq2fmBWqU2t+5sel/MN2dKXVHfaPRK34B7vCAas+YWH
-6aLcr34YEoP9VhdBLtUpgn2Z9DH2canPLAEnpQW5qrJITirvn5NSUZU8UnOOVkwX
-QMAJKOSLakhT2+zNVVXxxvjpoixMptEmX36vWkzaH6byHCx+rgIW0lbQL1dTR+iS
------END CERTIFICATE-----
-
-# Issuer: CN=America Online Root Certification Authority 1 O=America Online Inc.
-# Subject: CN=America Online Root Certification Authority 1 O=America Online Inc.
-# Label: "America Online Root Certification Authority 1"
-# Serial: 1
-# MD5 Fingerprint: 14:f1:08:ad:9d:fa:64:e2:89:e7:1c:cf:a8:ad:7d:5e
-# SHA1 Fingerprint: 39:21:c1:15:c1:5d:0e:ca:5c:cb:5b:c4:f0:7d:21:d8:05:0b:56:6a
-# SHA256 Fingerprint: 77:40:73:12:c6:3a:15:3d:5b:c0:0b:4e:51:75:9c:df:da:c2:37:dc:2a:33:b6:79:46:e9:8e:9b:fa:68:0a:e3
------BEGIN CERTIFICATE-----
-MIIDpDCCAoygAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEc
-MBoGA1UEChMTQW1lcmljYSBPbmxpbmUgSW5jLjE2MDQGA1UEAxMtQW1lcmljYSBP
-bmxpbmUgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAxMB4XDTAyMDUyODA2
-MDAwMFoXDTM3MTExOTIwNDMwMFowYzELMAkGA1UEBhMCVVMxHDAaBgNVBAoTE0Ft
-ZXJpY2EgT25saW5lIEluYy4xNjA0BgNVBAMTLUFtZXJpY2EgT25saW5lIFJvb3Qg
-Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMTCCASIwDQYJKoZIhvcNAQEBBQADggEP
-ADCCAQoCggEBAKgv6KRpBgNHw+kqmP8ZonCaxlCyfqXfaE0bfA+2l2h9LaaLl+lk
-hsmj76CGv2BlnEtUiMJIxUo5vxTjWVXlGbR0yLQFOVwWpeKVBeASrlmLojNoWBym
-1BW32J/X3HGrfpq/m44zDyL9Hy7nBzbvYjnF3cu6JRQj3gzGPTzOggjmZj7aUTsW
-OqMFf6Dch9Wc/HKpoH145LcxVR5lu9RhsCFg7RAycsWSJR74kEoYeEfffjA3PlAb
-2xzTa5qGUwew76wGePiEmf4hjUyAtgyC9mZweRrTT6PP8c9GsEsPPt2IYriMqQko
-O3rHl+Ee5fSfwMCuJKDIodkP1nsmgmkyPacCAwEAAaNjMGEwDwYDVR0TAQH/BAUw
-AwEB/zAdBgNVHQ4EFgQUAK3Zo/Z59m50qX8zPYEX10zPM94wHwYDVR0jBBgwFoAU
-AK3Zo/Z59m50qX8zPYEX10zPM94wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEB
-BQUAA4IBAQB8itEfGDeC4Liwo+1WlchiYZwFos3CYiZhzRAW18y0ZTTQEYqtqKkF
-Zu90821fnZmv9ov761KyBZiibyrFVL0lvV+uyIbqRizBs73B6UlwGBaXCBOMIOAb
-LjpHyx7kADCVW/RFo8AasAFOq73AI25jP4BKxQft3OJvx8Fi8eNy1gTIdGcL+oir
-oQHIb/AUr9KZzVGTfu0uOMe9zkZQPXLjeSWdm4grECDdpbgyn43gKd8hdIaC2y+C
-MMbHNYaz+ZZfRtsMRf3zUMNvxsNIrUam4SdHCh0Om7bCd39j8uB9Gr784N/Xx6ds
-sPmuujz9dLQR6FgNgLzTqIA6me11zEZ7
------END CERTIFICATE-----
-
-# Issuer: CN=America Online Root Certification Authority 2 O=America Online Inc.
-# Subject: CN=America Online Root Certification Authority 2 O=America Online Inc.
-# Label: "America Online Root Certification Authority 2"
-# Serial: 1
-# MD5 Fingerprint: d6:ed:3c:ca:e2:66:0f:af:10:43:0d:77:9b:04:09:bf
-# SHA1 Fingerprint: 85:b5:ff:67:9b:0c:79:96:1f:c8:6e:44:22:00:46:13:db:17:92:84
-# SHA256 Fingerprint: 7d:3b:46:5a:60:14:e5:26:c0:af:fc:ee:21:27:d2:31:17:27:ad:81:1c:26:84:2d:00:6a:f3:73:06:cc:80:bd
------BEGIN CERTIFICATE-----
-MIIFpDCCA4ygAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEc
-MBoGA1UEChMTQW1lcmljYSBPbmxpbmUgSW5jLjE2MDQGA1UEAxMtQW1lcmljYSBP
-bmxpbmUgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAyMB4XDTAyMDUyODA2
-MDAwMFoXDTM3MDkyOTE0MDgwMFowYzELMAkGA1UEBhMCVVMxHDAaBgNVBAoTE0Ft
-ZXJpY2EgT25saW5lIEluYy4xNjA0BgNVBAMTLUFtZXJpY2EgT25saW5lIFJvb3Qg
-Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIP
-ADCCAgoCggIBAMxBRR3pPU0Q9oyxQcngXssNt79Hc9PwVU3dxgz6sWYFas14tNwC
-206B89enfHG8dWOgXeMHDEjsJcQDIPT/DjsS/5uN4cbVG7RtIuOx238hZK+GvFci
-KtZHgVdEglZTvYYUAQv8f3SkWq7xuhG1m1hagLQ3eAkzfDJHA1zEpYNI9FdWboE2
-JxhP7JsowtS013wMPgwr38oE18aO6lhOqKSlGBxsRZijQdEt0sdtjRnxrXm3gT+9
-BoInLRBYBbV4Bbkv2wxrkJB+FFk4u5QkE+XRnRTf04JNRvCAOVIyD+OEsnpD8l7e
-Xz8d3eOyG6ChKiMDbi4BFYdcpnV1x5dhvt6G3NRI270qv0pV2uh9UPu0gBe4lL8B
-PeraunzgWGcXuVjgiIZGZ2ydEEdYMtA1fHkqkKJaEBEjNa0vzORKW6fIJ/KD3l67
-Xnfn6KVuY8INXWHQjNJsWiEOyiijzirplcdIz5ZvHZIlyMbGwcEMBawmxNJ10uEq
-Z8A9W6Wa6897GqidFEXlD6CaZd4vKL3Ob5Rmg0gp2OpljK+T2WSfVVcmv2/LNzGZ
-o2C7HK2JNDJiuEMhBnIMoVxtRsX6Kc8w3onccVvdtjc+31D1uAclJuW8tf48ArO3
-+L5DwYcRlJ4jbBeKuIonDFRH8KmzwICMoCfrHRnjB453cMor9H124HhnAgMBAAGj
-YzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFE1FwWg4u3OpaaEg5+31IqEj
-FNeeMB8GA1UdIwQYMBaAFE1FwWg4u3OpaaEg5+31IqEjFNeeMA4GA1UdDwEB/wQE
-AwIBhjANBgkqhkiG9w0BAQUFAAOCAgEAZ2sGuV9FOypLM7PmG2tZTiLMubekJcmn
-xPBUlgtk87FYT15R/LKXeydlwuXK5w0MJXti4/qftIe3RUavg6WXSIylvfEWK5t2
-LHo1YGwRgJfMqZJS5ivmae2p+DYtLHe/YUjRYwu5W1LtGLBDQiKmsXeu3mnFzccc
-obGlHBD7GL4acN3Bkku+KVqdPzW+5X1R+FXgJXUjhx5c3LqdsKyzadsXg8n33gy8
-CNyRnqjQ1xU3c6U1uPx+xURABsPr+CKAXEfOAuMRn0T//ZoyzH1kUQ7rVyZ2OuMe
-IjzCpjbdGe+n/BLzJsBZMYVMnNjP36TMzCmT/5RtdlwTCJfy7aULTd3oyWgOZtMA
-DjMSW7yV5TKQqLPGbIOtd+6Lfn6xqavT4fG2wLHqiMDn05DpKJKUe2h7lyoKZy2F
-AjgQ5ANh1NolNscIWC2hp1GvMApJ9aZphwctREZ2jirlmjvXGKL8nDgQzMY70rUX
-Om/9riW99XJZZLF0KjhfGEzfz3EEWjbUvy+ZnOjZurGV5gJLIaFb1cFPj65pbVPb
-AZO1XB4Y3WRayhgoPmMEEf0cjQAPuDffZ4qdZqkCapH/E8ovXYO8h5Ns3CRRFgQl
-Zvqz2cK6Kb6aSDiCmfS/O0oxGfm/jiEzFMpPVF/7zvuPcX/9XhmgD0uRuMRUvAaw
-RY8mkaKO/qk=
------END CERTIFICATE-----
-
-# Issuer: CN=AAA Certificate Services O=Comodo CA Limited
-# Subject: CN=AAA Certificate Services O=Comodo CA Limited
-# Label: "Comodo AAA Services root"
-# Serial: 1
-# MD5 Fingerprint: 49:79:04:b0:eb:87:19:ac:47:b0:bc:11:51:9b:74:d0
-# SHA1 Fingerprint: d1:eb:23:a4:6d:17:d6:8f:d9:25:64:c2:f1:f1:60:17:64:d8:e3:49
-# SHA256 Fingerprint: d7:a7:a0:fb:5d:7e:27:31:d7:71:e9:48:4e:bc:de:f7:1d:5f:0c:3e:0a:29:48:78:2b:c8:3e:e0:ea:69:9e:f4
------BEGIN CERTIFICATE-----
-MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEb
-MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow
-GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmlj
-YXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVowezEL
-MAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE
-BwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNVBAMM
-GEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP
-ADCCAQoCggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQua
-BtDFcCLNSS1UY8y2bmhGC1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe
-3M/vg4aijJRPn2jymJBGhCfHdr/jzDUsi14HZGWCwEiwqJH5YZ92IFCokcdmtet4
-YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszWY19zjNoFmag4qMsXeDZR
-rOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjHYpy+g8cm
-ez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQU
-oBEKIz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF
-MAMBAf8wewYDVR0fBHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20v
-QUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29t
-b2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2VzLmNybDANBgkqhkiG9w0BAQUF
-AAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm7l3sAg9g1o1Q
-GE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz
-Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2
-G9w84FoVxp7Z8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsi
-l2D4kF501KKaU73yqWjgom7C12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3
-smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg==
------END CERTIFICATE-----
-
-# Issuer: CN=Secure Certificate Services O=Comodo CA Limited
-# Subject: CN=Secure Certificate Services O=Comodo CA Limited
-# Label: "Comodo Secure Services root"
-# Serial: 1
-# MD5 Fingerprint: d3:d9:bd:ae:9f:ac:67:24:b3:c8:1b:52:e1:b9:a9:bd
-# SHA1 Fingerprint: 4a:65:d5:f4:1d:ef:39:b8:b8:90:4a:4a:d3:64:81:33:cf:c7:a1:d1
-# SHA256 Fingerprint: bd:81:ce:3b:4f:65:91:d1:1a:67:b5:fc:7a:47:fd:ef:25:52:1b:f9:aa:4e:18:b9:e3:df:2e:34:a7:80:3b:e8
------BEGIN CERTIFICATE-----
-MIIEPzCCAyegAwIBAgIBATANBgkqhkiG9w0BAQUFADB+MQswCQYDVQQGEwJHQjEb
-MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow
-GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEkMCIGA1UEAwwbU2VjdXJlIENlcnRp
-ZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVow
-fjELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
-A1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxJDAiBgNV
-BAMMG1NlY3VyZSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEB
-BQADggEPADCCAQoCggEBAMBxM4KK0HDrc4eCQNUd5MvJDkKQ+d40uaG6EfQlhfPM
-cm3ye5drswfxdySRXyWP9nQ95IDC+DwN879A6vfIUtFyb+/Iq0G4bi4XKpVpDM3S
-HpR7LZQdqnXXs5jLrLxkU0C8j6ysNstcrbvd4JQX7NFc0L/vpZXJkMWwrPsbQ996
-CF23uPJAGysnnlDOXmWCiIxe004MeuoIkbY2qitC++rCoznl2yY4rYsK7hljxxwk
-3wN42ubqwUcaCwtGCd0C/N7Lh1/XMGNooa7cMqG6vv5Eq2i2pRcV/b3Vp6ea5EQz
-6YiO/O1R65NxTq0B50SOqy3LqP4BSUjwwN3HaNiS/j0CAwEAAaOBxzCBxDAdBgNV
-HQ4EFgQUPNiTiMLAggnMAZkGkyDpnnAJY08wDgYDVR0PAQH/BAQDAgEGMA8GA1Ud
-EwEB/wQFMAMBAf8wgYEGA1UdHwR6MHgwO6A5oDeGNWh0dHA6Ly9jcmwuY29tb2Rv
-Y2EuY29tL1NlY3VyZUNlcnRpZmljYXRlU2VydmljZXMuY3JsMDmgN6A1hjNodHRw
-Oi8vY3JsLmNvbW9kby5uZXQvU2VjdXJlQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmww
-DQYJKoZIhvcNAQEFBQADggEBAIcBbSMdflsXfcFhMs+P5/OKlFlm4J4oqF7Tt/Q0
-5qo5spcWxYJvMqTpjOev/e/C6LlLqqP05tqNZSH7uoDrJiiFGv45jN5bBAS0VPmj
-Z55B+glSzAVIqMk/IQQezkhr/IXownuvf7fM+F86/TXGDe+X3EyrEeFryzHRbPtI
-gKvcnDe4IRRLDXE97IMzbtFuMhbsmMcWi1mmNKsFVy2T96oTy9IT4rcuO81rUBcJ
-aD61JlfutuC23bkpgHl9j6PwpCikFcSF9CfUa7/lXORlAnZUtOM3ZiTTGWHIUhDl
-izeauan5Hb/qmZJhlv8BzaFfDbxxvA6sCx1HRR3B7Hzs/Sk=
------END CERTIFICATE-----
-
-# Issuer: CN=Trusted Certificate Services O=Comodo CA Limited
-# Subject: CN=Trusted Certificate Services O=Comodo CA Limited
-# Label: "Comodo Trusted Services root"
-# Serial: 1
-# MD5 Fingerprint: 91:1b:3f:6e:cd:9e:ab:ee:07:fe:1f:71:d2:b3:61:27
-# SHA1 Fingerprint: e1:9f:e3:0e:8b:84:60:9e:80:9b:17:0d:72:a8:c5:ba:6e:14:09:bd
-# SHA256 Fingerprint: 3f:06:e5:56:81:d4:96:f5:be:16:9e:b5:38:9f:9f:2b:8f:f6:1e:17:08:df:68:81:72:48:49:cd:5d:27:cb:69
------BEGIN CERTIFICATE-----
-MIIEQzCCAyugAwIBAgIBATANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJHQjEb
-MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow
-GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDElMCMGA1UEAwwcVHJ1c3RlZCBDZXJ0
-aWZpY2F0ZSBTZXJ2aWNlczAeFw0wNDAxMDEwMDAwMDBaFw0yODEyMzEyMzU5NTla
-MH8xCzAJBgNVBAYTAkdCMRswGQYDVQQIDBJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO
-BgNVBAcMB1NhbGZvcmQxGjAYBgNVBAoMEUNvbW9kbyBDQSBMaW1pdGVkMSUwIwYD
-VQQDDBxUcnVzdGVkIENlcnRpZmljYXRlIFNlcnZpY2VzMIIBIjANBgkqhkiG9w0B
-AQEFAAOCAQ8AMIIBCgKCAQEA33FvNlhTWvI2VFeAxHQIIO0Yfyod5jWaHiWsnOWW
-fnJSoBVC21ndZHoa0Lh73TkVvFVIxO06AOoxEbrycXQaZ7jPM8yoMa+j49d/vzMt
-TGo87IvDktJTdyR0nAducPy9C1t2ul/y/9c3S0pgePfw+spwtOpZqqPOSC+pw7IL
-fhdyFgymBwwbOM/JYrc/oJOlh0Hyt3BAd9i+FHzjqMB6juljatEPmsbS9Is6FARW
-1O24zG71++IsWL1/T2sr92AkWCTOJu80kTrV44HQsvAEAtdbtz6SrGsSivnkBbA7
-kUlcsutT6vifR4buv5XAwAaf0lteERv0xwQ1KdJVXOTt6wIDAQABo4HJMIHGMB0G
-A1UdDgQWBBTFe1i97doladL3WRaoszLAeydb9DAOBgNVHQ8BAf8EBAMCAQYwDwYD
-VR0TAQH/BAUwAwEB/zCBgwYDVR0fBHwwejA8oDqgOIY2aHR0cDovL2NybC5jb21v
-ZG9jYS5jb20vVHJ1c3RlZENlcnRpZmljYXRlU2VydmljZXMuY3JsMDqgOKA2hjRo
-dHRwOi8vY3JsLmNvbW9kby5uZXQvVHJ1c3RlZENlcnRpZmljYXRlU2VydmljZXMu
-Y3JsMA0GCSqGSIb3DQEBBQUAA4IBAQDIk4E7ibSvuIQSTI3S8NtwuleGFTQQuS9/
-HrCoiWChisJ3DFBKmwCL2Iv0QeLQg4pKHBQGsKNoBXAxMKdTmw7pSqBYaWcOrp32
-pSxBvzwGa+RZzG0Q8ZZvH9/0BAKkn0U+yNj6NkZEUD+Cl5EfKNsYEYwq5GWDVxIS
-jBc/lDb+XbDABHcTuPQV1T84zJQ6VdCsmPW6AF/ghhmBeC8owH7TzEIK9a5QoNE+
-xqFx7D+gIIxmOom0jtTYsU0lR+4viMi14QVFwL4Ucd56/Y57fU0IlqUSc/Atyjcn
-dBInTMu2l+nZrghtWjlA3QVHdWpaIbOjGM9O9y5Xt5hwXsjEeLBi
------END CERTIFICATE-----
-
-# Issuer: CN=UTN - DATACorp SGC O=The USERTRUST Network OU=http://www.usertrust.com
-# Subject: CN=UTN - DATACorp SGC O=The USERTRUST Network OU=http://www.usertrust.com
-# Label: "UTN DATACorp SGC Root CA"
-# Serial: 91374294542884689855167577680241077609
-# MD5 Fingerprint: b3:a5:3e:77:21:6d:ac:4a:c0:c9:fb:d5:41:3d:ca:06
-# SHA1 Fingerprint: 58:11:9f:0e:12:82:87:ea:50:fd:d9:87:45:6f:4f:78:dc:fa:d6:d4
-# SHA256 Fingerprint: 85:fb:2f:91:dd:12:27:5a:01:45:b6:36:53:4f:84:02:4a:d6:8b:69:b8:ee:88:68:4f:f7:11:37:58:05:b3:48
------BEGIN CERTIFICATE-----
-MIIEXjCCA0agAwIBAgIQRL4Mi1AAIbQR0ypoBqmtaTANBgkqhkiG9w0BAQUFADCB
-kzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug
-Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho
-dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xGzAZBgNVBAMTElVUTiAtIERBVEFDb3Jw
-IFNHQzAeFw05OTA2MjQxODU3MjFaFw0xOTA2MjQxOTA2MzBaMIGTMQswCQYDVQQG
-EwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4wHAYD
-VQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cu
-dXNlcnRydXN0LmNvbTEbMBkGA1UEAxMSVVROIC0gREFUQUNvcnAgU0dDMIIBIjAN
-BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3+5YEKIrblXEjr8uRgnn4AgPLit6
-E5Qbvfa2gI5lBZMAHryv4g+OGQ0SR+ysraP6LnD43m77VkIVni5c7yPeIbkFdicZ
-D0/Ww5y0vpQZY/KmEQrrU0icvvIpOxboGqBMpsn0GFlowHDyUwDAXlCCpVZvNvlK
-4ESGoE1O1kduSUrLZ9emxAW5jh70/P/N5zbgnAVssjMiFdC04MwXwLLA9P4yPykq
-lXvY8qdOD1R8oQ2AswkDwf9c3V6aPryuvEeKaq5xyh+xKrhfQgUL7EYw0XILyulW
-bfXv33i+Ybqypa4ETLyorGkVl73v67SMvzX41MPRKA5cOp9wGDMgd8SirwIDAQAB
-o4GrMIGoMAsGA1UdDwQEAwIBxjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRT
-MtGzz3/64PGgXYVOktKeRR20TzA9BgNVHR8ENjA0MDKgMKAuhixodHRwOi8vY3Js
-LnVzZXJ0cnVzdC5jb20vVVROLURBVEFDb3JwU0dDLmNybDAqBgNVHSUEIzAhBggr
-BgEFBQcDAQYKKwYBBAGCNwoDAwYJYIZIAYb4QgQBMA0GCSqGSIb3DQEBBQUAA4IB
-AQAnNZcAiosovcYzMB4p/OL31ZjUQLtgyr+rFywJNn9Q+kHcrpY6CiM+iVnJowft
-Gzet/Hy+UUla3joKVAgWRcKZsYfNjGjgaQPpxE6YsjuMFrMOoAyYUJuTqXAJyCyj
-j98C5OBxOvG0I3KgqgHf35g+FFCgMSa9KOlaMCZ1+XtgHI3zzVAmbQQnmt/VDUVH
-KWss5nbZqSl9Mt3JNjy9rjXxEZ4du5A/EkdOjtd+D2JzHVImOBwYSf0wdJrE5SIv
-2MCN7ZF6TACPcn9d2t0bi0Vr591pl6jFVkwPDPafepE39peC4N1xaf92P2BNPM/3
-mfnGV/TJVTl4uix5yaaIK/QI
------END CERTIFICATE-----
-
-# Issuer: CN=UTN-USERFirst-Hardware O=The USERTRUST Network OU=http://www.usertrust.com
-# Subject: CN=UTN-USERFirst-Hardware O=The USERTRUST Network OU=http://www.usertrust.com
-# Label: "UTN USERFirst Hardware Root CA"
-# Serial: 91374294542884704022267039221184531197
-# MD5 Fingerprint: 4c:56:41:e5:0d:bb:2b:e8:ca:a3:ed:18:08:ad:43:39
-# SHA1 Fingerprint: 04:83:ed:33:99:ac:36:08:05:87:22:ed:bc:5e:46:00:e3:be:f9:d7
-# SHA256 Fingerprint: 6e:a5:47:41:d0:04:66:7e:ed:1b:48:16:63:4a:a3:a7:9e:6e:4b:96:95:0f:82:79:da:fc:8d:9b:d8:81:21:37
------BEGIN CERTIFICATE-----
-MIIEdDCCA1ygAwIBAgIQRL4Mi1AAJLQR0zYq/mUK/TANBgkqhkiG9w0BAQUFADCB
-lzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug
-Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho
-dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3Qt
-SGFyZHdhcmUwHhcNOTkwNzA5MTgxMDQyWhcNMTkwNzA5MTgxOTIyWjCBlzELMAkG
-A1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEe
-MBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8v
-d3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdh
-cmUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCx98M4P7Sof885glFn
-0G2f0v9Y8+efK+wNiVSZuTiZFvfgIXlIwrthdBKWHTxqctU8EGc6Oe0rE81m65UJ
-M6Rsl7HoxuzBdXmcRl6Nq9Bq/bkqVRcQVLMZ8Jr28bFdtqdt++BxF2uiiPsA3/4a
-MXcMmgF6sTLjKwEHOG7DpV4jvEWbe1DByTCP2+UretNb+zNAHqDVmBe8i4fDidNd
-oI6yqqr2jmmIBsX6iSHzCJ1pLgkzmykNRg+MzEk0sGlRvfkGzWitZky8PqxhvQqI
-DsjfPe58BEydCl5rkdbux+0ojatNh4lz0G6k0B4WixThdkQDf2Os5M1JnMWS9Ksy
-oUhbAgMBAAGjgbkwgbYwCwYDVR0PBAQDAgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYD
-VR0OBBYEFKFyXyYbKJhDlV0HN9WFlp1L0sNFMEQGA1UdHwQ9MDswOaA3oDWGM2h0
-dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9VVE4tVVNFUkZpcnN0LUhhcmR3YXJlLmNy
-bDAxBgNVHSUEKjAoBggrBgEFBQcDAQYIKwYBBQUHAwUGCCsGAQUFBwMGBggrBgEF
-BQcDBzANBgkqhkiG9w0BAQUFAAOCAQEARxkP3nTGmZev/K0oXnWO6y1n7k57K9cM
-//bey1WiCuFMVGWTYGufEpytXoMs61quwOQt9ABjHbjAbPLPSbtNk28Gpgoiskli
-CE7/yMgUsogWXecB5BKV5UU0s4tpvc+0hY91UZ59Ojg6FEgSxvunOxqNDYJAB+gE
-CJChicsZUN/KHAG8HQQZexB2lzvukJDKxA4fFm517zP4029bHpbj4HR3dHuKom4t
-3XbWOTCC8KucUvIqx69JXn7HaOWCgchqJ/kniCrVWFCVH/A7HFe7fRQ5YiuayZSS
-KqMiDP+JJn1fIytH1xUdqWqeUQ0qUZ6B+dQ7XnASfxAynB67nfhmqA==
------END CERTIFICATE-----
-
-# Issuer: CN=XRamp Global Certification Authority O=XRamp Security Services Inc OU=www.xrampsecurity.com
-# Subject: CN=XRamp Global Certification Authority O=XRamp Security Services Inc OU=www.xrampsecurity.com
-# Label: "XRamp Global CA Root"
-# Serial: 107108908803651509692980124233745014957
-# MD5 Fingerprint: a1:0b:44:b3:ca:10:d8:00:6e:9d:0f:d8:0f:92:0a:d1
-# SHA1 Fingerprint: b8:01:86:d1:eb:9c:86:a5:41:04:cf:30:54:f3:4c:52:b7:e5:58:c6
-# SHA256 Fingerprint: ce:cd:dc:90:50:99:d8:da:df:c5:b1:d2:09:b7:37:cb:e2:c1:8c:fb:2c:10:c0:ff:0b:cf:0d:32:86:fc:1a:a2
------BEGIN CERTIFICATE-----
-MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCB
-gjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEk
-MCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRY
-UmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQxMTAxMTcx
-NDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3
-dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2Vy
-dmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB
-dXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS6
-38eMpSe2OAtp87ZOqCwuIR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCP
-KZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMxfoArtYzAQDsRhtDLooY2YKTVMIJt2W7Q
-DxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FEzG+gSqmUsE3a56k0enI4
-qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqsAxcZZPRa
-JSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNVi
-PvryxS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0P
-BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASs
-jVy16bYbMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0
-eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQEwDQYJKoZIhvcNAQEFBQAD
-ggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc/Kh4ZzXxHfAR
-vbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt
-qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLa
-IR9NmXmd4c8nnxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSy
-i6mx5O+aGtA9aZnuqCij4Tyz8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQ
-O+7ETPTsJ3xCwnR8gooJybQDJbw=
------END CERTIFICATE-----
-
-# Issuer: O=The Go Daddy Group, Inc. OU=Go Daddy Class 2 Certification Authority
-# Subject: O=The Go Daddy Group, Inc. OU=Go Daddy Class 2 Certification Authority
-# Label: "Go Daddy Class 2 CA"
-# Serial: 0
-# MD5 Fingerprint: 91:de:06:25:ab:da:fd:32:17:0c:bb:25:17:2a:84:67
-# SHA1 Fingerprint: 27:96:ba:e6:3f:18:01:e2:77:26:1b:a0:d7:77:70:02:8f:20:ee:e4
-# SHA256 Fingerprint: c3:84:6b:f2:4b:9e:93:ca:64:27:4c:0e:c6:7c:1e:cc:5e:02:4f:fc:ac:d2:d7:40:19:35:0e:81:fe:54:6a:e4
------BEGIN CERTIFICATE-----
-MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEh
-MB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBE
-YWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3
-MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRo
-ZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3Mg
-MiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggEN
-ADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCA
-PVYYYwhv2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6w
-wdhFJ2+qN1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXi
-EqITLdiOr18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMY
-avx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+
-YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0OBBYEFNLE
-sNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h
-/t2oatTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5
-IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmlj
-YXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD
-ggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wimPQoZ+YeAEW5p5JYXMP80kWNy
-OO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKtI3lpjbi2Tc7P
-TMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ
-HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mER
-dEr/VxqHD3VILs9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5Cuf
-ReYNnyicsbkqWletNw+vHX/bvZ8=
------END CERTIFICATE-----
-
-# Issuer: O=Starfield Technologies, Inc. OU=Starfield Class 2 Certification Authority
-# Subject: O=Starfield Technologies, Inc. OU=Starfield Class 2 Certification Authority
-# Label: "Starfield Class 2 CA"
-# Serial: 0
-# MD5 Fingerprint: 32:4a:4b:bb:c8:63:69:9b:be:74:9a:c6:dd:1d:46:24
-# SHA1 Fingerprint: ad:7e:1c:28:b0:64:ef:8f:60:03:40:20:14:c3:d0:e3:37:0e:b5:8a
-# SHA256 Fingerprint: 14:65:fa:20:53:97:b8:76:fa:a6:f0:a9:95:8e:55:90:e4:0f:cc:7f:aa:4f:b7:c2:c8:67:75:21:fb:5f:b6:58
------BEGIN CERTIFICATE-----
-MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzEl
-MCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMp
-U3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQw
-NjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBoMQswCQYDVQQGEwJVUzElMCMGA1UE
-ChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZp
-ZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqGSIb3
-DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf
-8MOh2tTYbitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN
-+lq2cwQlZut3f+dZxkqZJRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0
-X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVmepsZGD3/cVE8MC5fvj13c7JdBmzDI1aa
-K4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSNF4Azbl5KXZnJHoe0nRrA
-1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HFMIHCMB0G
-A1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fR
-zt0fhvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0
-YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBD
-bGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8w
-DQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGsafPzWdqbAYcaT1epoXkJKtv3
-L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLMPUxA2IGvd56D
-eruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl
-xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynp
-VSJYACPq4xJDKVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEY
-WQPJIrSPnNVeKtelttQKbfi3QBFGmh95DmK/D5fs4C8fF5Q=
------END CERTIFICATE-----
-
-# Issuer: CN=StartCom Certification Authority O=StartCom Ltd. OU=Secure Digital Certificate Signing
-# Subject: CN=StartCom Certification Authority O=StartCom Ltd. OU=Secure Digital Certificate Signing
-# Label: "StartCom Certification Authority"
-# Serial: 1
-# MD5 Fingerprint: 22:4d:8f:8a:fc:f7:35:c2:bb:57:34:90:7b:8b:22:16
-# SHA1 Fingerprint: 3e:2b:f7:f2:03:1b:96:f3:8c:e6:c4:d8:a8:5d:3e:2d:58:47:6a:0f
-# SHA256 Fingerprint: c7:66:a9:be:f2:d4:07:1c:86:3a:31:aa:49:20:e8:13:b2:d1:98:60:8c:b7:b7:cf:e2:11:43:b8:36:df:09:ea
------BEGIN CERTIFICATE-----
-MIIHyTCCBbGgAwIBAgIBATANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEW
-MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg
-Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh
-dGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0NjM2WhcNMzYwOTE3MTk0NjM2WjB9
-MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMi
-U2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3Rh
-cnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUA
-A4ICDwAwggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZk
-pMyONvg45iPwbm2xPN1yo4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rf
-OQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/C
-Ji/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/deMotHweXMAEtcnn6RtYT
-Kqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt2PZE4XNi
-HzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMM
-Av+Z6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w
-+2OqqGwaVLRcJXrJosmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+
-Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3
-Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVcUjyJthkqcwEKDwOzEmDyei+B
-26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT37uMdBNSSwID
-AQABo4ICUjCCAk4wDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAa4wHQYDVR0OBBYE
-FE4L7xqkQFulF2mHMMo0aEPQQa7yMGQGA1UdHwRdMFswLKAqoCiGJmh0dHA6Ly9j
-ZXJ0LnN0YXJ0Y29tLm9yZy9zZnNjYS1jcmwuY3JsMCugKaAnhiVodHRwOi8vY3Js
-LnN0YXJ0Y29tLm9yZy9zZnNjYS1jcmwuY3JsMIIBXQYDVR0gBIIBVDCCAVAwggFM
-BgsrBgEEAYG1NwEBATCCATswLwYIKwYBBQUHAgEWI2h0dHA6Ly9jZXJ0LnN0YXJ0
-Y29tLm9yZy9wb2xpY3kucGRmMDUGCCsGAQUFBwIBFilodHRwOi8vY2VydC5zdGFy
-dGNvbS5vcmcvaW50ZXJtZWRpYXRlLnBkZjCB0AYIKwYBBQUHAgIwgcMwJxYgU3Rh
-cnQgQ29tbWVyY2lhbCAoU3RhcnRDb20pIEx0ZC4wAwIBARqBl0xpbWl0ZWQgTGlh
-YmlsaXR5LCByZWFkIHRoZSBzZWN0aW9uICpMZWdhbCBMaW1pdGF0aW9ucyogb2Yg
-dGhlIFN0YXJ0Q29tIENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFBvbGljeSBhdmFp
-bGFibGUgYXQgaHR0cDovL2NlcnQuc3RhcnRjb20ub3JnL3BvbGljeS5wZGYwEQYJ
-YIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilTdGFydENvbSBGcmVlIFNT
-TCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQUFAAOCAgEAFmyZ
-9GYMNPXQhV59CuzaEE44HF7fpiUFS5Eyweg78T3dRAlbB0mKKctmArexmvclmAk8
-jhvh3TaHK0u7aNM5Zj2gJsfyOZEdUauCe37Vzlrk4gNXcGmXCPleWKYK34wGmkUW
-FjgKXlf2Ysd6AgXmvB618p70qSmD+LIU424oh0TDkBreOKk8rENNZEXO3SipXPJz
-ewT4F+irsfMuXGRuczE6Eri8sxHkfY+BUZo7jYn0TZNmezwD7dOaHZrzZVD1oNB1
-ny+v8OqCQ5j4aZyJecRDjkZy42Q2Eq/3JR44iZB3fsNrarnDy0RLrHiQi+fHLB5L
-EUTINFInzQpdn4XBidUaePKVEFMy3YCEZnXZtWgo+2EuvoSoOMCZEoalHmdkrQYu
-L6lwhceWD3yJZfWOQ1QOq92lgDmUYMA0yZZwLKMS9R9Ie70cfmu3nZD0Ijuu+Pwq
-yvqCUqDvr0tVk+vBtfAii6w0TiYiBKGHLHVKt+V9E9e4DGTANtLJL4YSjCMJwRuC
-O3NJo2pXh5Tl1njFmUNj403gdy3hZZlyaQQaRwnmDwFWJPsfvw55qVguucQJAX6V
-um0ABj6y6koQOdjQK/W/7HW/lwLFCRsI3FU34oH7N4RDYiDK51ZLZer+bMEkkySh
-NOsF/5oirpt9P/FlUQqmMGqz9IgcgA38corog14=
------END CERTIFICATE-----
-
-# Issuer: CN=DigiCert Assured ID Root CA O=DigiCert Inc OU=www.digicert.com
-# Subject: CN=DigiCert Assured ID Root CA O=DigiCert Inc OU=www.digicert.com
-# Label: "DigiCert Assured ID Root CA"
-# Serial: 17154717934120587862167794914071425081
-# MD5 Fingerprint: 87:ce:0b:7b:2a:0e:49:00:e1:58:71:9b:37:a8:93:72
-# SHA1 Fingerprint: 05:63:b8:63:0d:62:d7:5a:bb:c8:ab:1e:4b:df:b5:a8:99:b2:4d:43
-# SHA256 Fingerprint: 3e:90:99:b5:01:5e:8f:48:6c:00:bc:ea:9d:11:1e:e7:21:fa:ba:35:5a:89:bc:f1:df:69:56:1e:3d:c6:32:5c
------BEGIN CERTIFICATE-----
-MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBl
-MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
-d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv
-b3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzExMTEwMDAwMDAwWjBlMQswCQYDVQQG
-EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl
-cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwggEi
-MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7c
-JpSIqvTO9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYP
-mDI2dsze3Tyoou9q+yHyUmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+
-wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW/lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4
-VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpyoeb6pNnVFzF1roV9Iq4/
-AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whfGHdPAgMB
-AAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW
-BBRF66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYun
-pyGd823IDzANBgkqhkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRC
-dWKuh+vy1dneVrOfzM4UKLkNl2BcEkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTf
-fwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38FnSbNd67IJKusm7Xi+fT8r87cm
-NW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i8b5QZ7dsvfPx
-H2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe
-+o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g==
------END CERTIFICATE-----
-
-# Issuer: CN=DigiCert Global Root CA O=DigiCert Inc OU=www.digicert.com
-# Subject: CN=DigiCert Global Root CA O=DigiCert Inc OU=www.digicert.com
-# Label: "DigiCert Global Root CA"
-# Serial: 10944719598952040374951832963794454346
-# MD5 Fingerprint: 79:e4:a9:84:0d:7d:3a:96:d7:c0:4f:e2:43:4c:89:2e
-# SHA1 Fingerprint: a8:98:5d:3a:65:e5:e5:c4:b2:d7:d6:6d:40:c6:dd:2f:b1:9c:54:36
-# SHA256 Fingerprint: 43:48:a0:e9:44:4c:78:cb:26:5e:05:8d:5e:89:44:b4:d8:4f:96:62:bd:26:db:25:7f:89:34:a4:43:c7:01:61
------BEGIN CERTIFICATE-----
-MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh
-MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
-d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
-QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT
-MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
-b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG
-9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB
-CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97
-nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt
-43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P
-T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4
-gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO
-BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR
-TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw
-DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr
-hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg
-06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF
-PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls
-YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
-CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
------END CERTIFICATE-----
-
-# Issuer: CN=DigiCert High Assurance EV Root CA O=DigiCert Inc OU=www.digicert.com
-# Subject: CN=DigiCert High Assurance EV Root CA O=DigiCert Inc OU=www.digicert.com
-# Label: "DigiCert High Assurance EV Root CA"
-# Serial: 3553400076410547919724730734378100087
-# MD5 Fingerprint: d4:74:de:57:5c:39:b2:d3:9c:85:83:c5:c0:65:49:8a
-# SHA1 Fingerprint: 5f:b7:ee:06:33:e2:59:db:ad:0c:4c:9a:e6:d3:8f:1a:61:c7:dc:25
-# SHA256 Fingerprint: 74:31:e5:f4:c3:c1:ce:46:90:77:4f:0b:61:e0:54:40:88:3b:a9:a0:1e:d0:0b:a6:ab:d7:80:6e:d3:b1:18:cf
------BEGIN CERTIFICATE-----
-MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs
-MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
-d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
-ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL
-MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
-LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug
-RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm
-+9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW
-PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM
-xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB
-Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3
-hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg
-EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF
-MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA
-FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec
-nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z
-eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF
-hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2
-Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe
-vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep
-+OkuE6N36B9K
------END CERTIFICATE-----
-
-# Issuer: CN=GeoTrust Primary Certification Authority O=GeoTrust Inc.
-# Subject: CN=GeoTrust Primary Certification Authority O=GeoTrust Inc.
-# Label: "GeoTrust Primary Certification Authority"
-# Serial: 32798226551256963324313806436981982369
-# MD5 Fingerprint: 02:26:c3:01:5e:08:30:37:43:a9:d0:7d:cf:37:e6:bf
-# SHA1 Fingerprint: 32:3c:11:8e:1b:f7:b8:b6:52:54:e2:e2:10:0d:d6:02:90:37:f0:96
-# SHA256 Fingerprint: 37:d5:10:06:c5:12:ea:ab:62:64:21:f1:ec:8c:92:01:3f:c5:f8:2a:e9:8e:e5:33:eb:46:19:b8:de:b4:d0:6c
------BEGIN CERTIFICATE-----
-MIIDfDCCAmSgAwIBAgIQGKy1av1pthU6Y2yv2vrEoTANBgkqhkiG9w0BAQUFADBY
-MQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjExMC8GA1UEAxMo
-R2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEx
-MjcwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMFgxCzAJBgNVBAYTAlVTMRYwFAYDVQQK
-Ew1HZW9UcnVzdCBJbmMuMTEwLwYDVQQDEyhHZW9UcnVzdCBQcmltYXJ5IENlcnRp
-ZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
-AQEAvrgVe//UfH1nrYNke8hCUy3f9oQIIGHWAVlqnEQRr+92/ZV+zmEwu3qDXwK9
-AWbK7hWNb6EwnL2hhZ6UOvNWiAAxz9juapYC2e0DjPt1befquFUWBRaa9OBesYjA
-ZIVcFU2Ix7e64HXprQU9nceJSOC7KMgD4TCTZF5SwFlwIjVXiIrxlQqD17wxcwE0
-7e9GceBrAqg1cmuXm2bgyxx5X9gaBGgeRwLmnWDiNpcB3841kt++Z8dtd1k7j53W
-kBWUvEI0EME5+bEnPn7WinXFsq+W06Lem+SYvn3h6YGttm/81w7a4DSwDRp35+MI
-mO9Y+pyEtzavwt+s0vQQBnBxNQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4G
-A1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQULNVQQZcVi/CPNmFbSvtr2ZnJM5IwDQYJ
-KoZIhvcNAQEFBQADggEBAFpwfyzdtzRP9YZRqSa+S7iq8XEN3GHHoOo0Hnp3DwQ1
-6CePbJC/kRYkRj5KTs4rFtULUh38H2eiAkUxT87z+gOneZ1TatnaYzr4gNfTmeGl
-4b7UVXGYNTq+k+qurUKykG/g/CFNNWMziUnWm07Kx+dOCQD32sfvmWKZd7aVIl6K
-oKv0uHiYyjgZmclynnjNS6yvGaBzEi38wkG6gZHaFloxt/m0cYASSJlyc1pZU8Fj
-UjPtp8nSOQJw+uCxQmYpqptR7TBUIhRf2asdweSU8Pj1K/fqynhG1riR/aYNKxoU
-AT6A8EKglQdebc3MS6RFjasS6LPeWuWgfOgPIh1a6Vk=
------END CERTIFICATE-----
-
-# Issuer: CN=thawte Primary Root CA O=thawte, Inc. OU=Certification Services Division/(c) 2006 thawte, Inc. - For authorized use only
-# Subject: CN=thawte Primary Root CA O=thawte, Inc. OU=Certification Services Division/(c) 2006 thawte, Inc. - For authorized use only
-# Label: "thawte Primary Root CA"
-# Serial: 69529181992039203566298953787712940909
-# MD5 Fingerprint: 8c:ca:dc:0b:22:ce:f5:be:72:ac:41:1a:11:a8:d8:12
-# SHA1 Fingerprint: 91:c6:d6:ee:3e:8a:c8:63:84:e5:48:c2:99:29:5c:75:6c:81:7b:81
-# SHA256 Fingerprint: 8d:72:2f:81:a9:c1:13:c0:79:1d:f1:36:a2:96:6d:b2:6c:95:0a:97:1d:b4:6b:41:99:f4:ea:54:b7:8b:fb:9f
------BEGIN CERTIFICATE-----
-MIIEIDCCAwigAwIBAgIQNE7VVyDV7exJ9C/ON9srbTANBgkqhkiG9w0BAQUFADCB
-qTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMf
-Q2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIw
-MDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxHzAdBgNV
-BAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwHhcNMDYxMTE3MDAwMDAwWhcNMzYw
-NzE2MjM1OTU5WjCBqTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5j
-LjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYG
-A1UECxMvKGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl
-IG9ubHkxHzAdBgNVBAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwggEiMA0GCSqG
-SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCsoPD7gFnUnMekz52hWXMJEEUMDSxuaPFs
-W0hoSVk3/AszGcJ3f8wQLZU0HObrTQmnHNK4yZc2AreJ1CRfBsDMRJSUjQJib+ta
-3RGNKJpchJAQeg29dGYvajig4tVUROsdB58Hum/u6f1OCyn1PoSgAfGcq/gcfomk
-6KHYcWUNo1F77rzSImANuVud37r8UVsLr5iy6S7pBOhih94ryNdOwUxkHt3Ph1i6
-Sk/KaAcdHJ1KxtUvkcx8cXIcxcBn6zL9yZJclNqFwJu/U30rCfSMnZEfl2pSy94J
-NqR32HuHUETVPm4pafs5SSYeCaWAe0At6+gnhcn+Yf1+5nyXHdWdAgMBAAGjQjBA
-MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBR7W0XP
-r87Lev0xkhpqtvNG61dIUDANBgkqhkiG9w0BAQUFAAOCAQEAeRHAS7ORtvzw6WfU
-DW5FvlXok9LOAz/t2iWwHVfLHjp2oEzsUHboZHIMpKnxuIvW1oeEuzLlQRHAd9mz
-YJ3rG9XRbkREqaYB7FViHXe4XI5ISXycO1cRrK1zN44veFyQaEfZYGDm/Ac9IiAX
-xPcW6cTYcvnIc3zfFi8VqT79aie2oetaupgf1eNNZAqdE8hhuvU5HIe6uL17In/2
-/qxAeeWsEG89jxt5dovEN7MhGITlNgDrYyCZuen+MwS7QcjBAvlEYyCegc5C09Y/
-LHbTY5xZ3Y+m4Q6gLkH3LpVHz7z9M/P2C2F+fpErgUfCJzDupxBdN49cOSvkBPB7
-jVaMaA==
------END CERTIFICATE-----
-
-# Issuer: CN=VeriSign Class 3 Public Primary Certification Authority - G5 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2006 VeriSign, Inc. - For authorized use only
-# Subject: CN=VeriSign Class 3 Public Primary Certification Authority - G5 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2006 VeriSign, Inc. - For authorized use only
-# Label: "VeriSign Class 3 Public Primary Certification Authority - G5"
-# Serial: 33037644167568058970164719475676101450
-# MD5 Fingerprint: cb:17:e4:31:67:3e:e2:09:fe:45:57:93:f3:0a:fa:1c
-# SHA1 Fingerprint: 4e:b6:d5:78:49:9b:1c:cf:5f:58:1e:ad:56:be:3d:9b:67:44:a5:e5
-# SHA256 Fingerprint: 9a:cf:ab:7e:43:c8:d8:80:d0:6b:26:2a:94:de:ee:e4:b4:65:99:89:c3:d0:ca:f1:9b:af:64:05:e4:1a:b7:df
------BEGIN CERTIFICATE-----
-MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCB
-yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL
-ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp
-U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW
-ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0
-aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCByjEL
-MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW
-ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2ln
-biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp
-U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y
-aXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvJAgIKXo1
-nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKzj/i5Vbex
-t0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIz
-SdhDY2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQG
-BO+QueQA5N06tRn/Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+
-rCpSx4/VBEnkjWNHiDxpg8v+R70rfk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/
-NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E
-BAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEwHzAH
-BgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy
-aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKv
-MzEzMA0GCSqGSIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzE
-p6B4Eq1iDkVwZMXnl2YtmAl+X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y
-5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKEKQsTb47bDN0lAtukixlE0kF6BWlK
-WE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiCKm0oHw0LxOXnGiYZ
-4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vEZV8N
-hnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq
------END CERTIFICATE-----
-
-# Issuer: CN=COMODO Certification Authority O=COMODO CA Limited
-# Subject: CN=COMODO Certification Authority O=COMODO CA Limited
-# Label: "COMODO Certification Authority"
-# Serial: 104350513648249232941998508985834464573
-# MD5 Fingerprint: 5c:48:dc:f7:42:72:ec:56:94:6d:1c:cc:71:35:80:75
-# SHA1 Fingerprint: 66:31:bf:9e:f7:4f:9e:b6:c9:d5:a6:0c:ba:6a:be:d1:f7:bd:ef:7b
-# SHA256 Fingerprint: 0c:2c:d6:3d:f7:80:6f:a3:99:ed:e8:09:11:6b:57:5b:f8:79:89:f0:65:18:f9:80:8c:86:05:03:17:8b:af:66
------BEGIN CERTIFICATE-----
-MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCB
-gTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
-A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNV
-BAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEyMDEwMDAw
-MDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3Jl
-YXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01P
-RE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0
-aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3
-UcEbVASY06m/weaKXTuH+7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI
-2GqGd0S7WWaXUF601CxwRM/aN5VCaTwwxHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8
-Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV4EajcNxo2f8ESIl33rXp
-+2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA1KGzqSX+
-DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5O
-nKVIrLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW
-/zAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6g
-PKA6hjhodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9u
-QXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOCAQEAPpiem/Yb6dc5t3iuHXIY
-SdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CPOGEIqB6BCsAv
-IC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/
-RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4
-zJVSk/BwJVmcIGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5dd
-BA6+C4OmF4O5MBKgxTMVBbkN+8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IB
-ZQ==
------END CERTIFICATE-----
-
-# Issuer: CN=Network Solutions Certificate Authority O=Network Solutions L.L.C.
-# Subject: CN=Network Solutions Certificate Authority O=Network Solutions L.L.C.
-# Label: "Network Solutions Certificate Authority"
-# Serial: 116697915152937497490437556386812487904
-# MD5 Fingerprint: d3:f3:a6:16:c0:fa:6b:1d:59:b1:2d:96:4d:0e:11:2e
-# SHA1 Fingerprint: 74:f8:a3:c3:ef:e7:b3:90:06:4b:83:90:3c:21:64:60:20:e5:df:ce
-# SHA256 Fingerprint: 15:f0:ba:00:a3:ac:7a:f3:ac:88:4c:07:2b:10:11:a0:77:bd:77:c0:97:f4:01:64:b2:f8:59:8a:bd:83:86:0c
------BEGIN CERTIFICATE-----
-MIID5jCCAs6gAwIBAgIQV8szb8JcFuZHFhfjkDFo4DANBgkqhkiG9w0BAQUFADBi
-MQswCQYDVQQGEwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMu
-MTAwLgYDVQQDEydOZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3Jp
-dHkwHhcNMDYxMjAxMDAwMDAwWhcNMjkxMjMxMjM1OTU5WjBiMQswCQYDVQQGEwJV
-UzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMuMTAwLgYDVQQDEydO
-ZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0GCSqG
-SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkvH6SMG3G2I4rC7xGzuAnlt7e+foS0zwz
-c7MEL7xxjOWftiJgPl9dzgn/ggwbmlFQGiaJ3dVhXRncEg8tCqJDXRfQNJIg6nPP
-OCwGJgl6cvf6UDL4wpPTaaIjzkGxzOTVHzbRijr4jGPiFFlp7Q3Tf2vouAPlT2rl
-mGNpSAW+Lv8ztumXWWn4Zxmuk2GWRBXTcrA/vGp97Eh/jcOrqnErU2lBUzS1sLnF
-BgrEsEX1QV1uiUV7PTsmjHTC5dLRfbIR1PtYMiKagMnc/Qzpf14Dl847ABSHJ3A4
-qY5usyd2mFHgBeMhqxrVhSI8KbWaFsWAqPS7azCPL0YCorEMIuDTAgMBAAGjgZcw
-gZQwHQYDVR0OBBYEFCEwyfsA106Y2oeqKtCnLrFAMadMMA4GA1UdDwEB/wQEAwIB
-BjAPBgNVHRMBAf8EBTADAQH/MFIGA1UdHwRLMEkwR6BFoEOGQWh0dHA6Ly9jcmwu
-bmV0c29sc3NsLmNvbS9OZXR3b3JrU29sdXRpb25zQ2VydGlmaWNhdGVBdXRob3Jp
-dHkuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQC7rkvnt1frf6ott3NHhWrB5KUd5Oc8
-6fRZZXe1eltajSU24HqXLjjAV2CDmAaDn7l2em5Q4LqILPxFzBiwmZVRDuwduIj/
-h1AcgsLj4DKAv6ALR8jDMe+ZZzKATxcheQxpXN5eNK4CtSbqUN9/GGUsyfJj4akH
-/nxxH2szJGoeBfcFaMBqEssuXmHLrijTfsK0ZpEmXzwuJF/LWA/rKOyvEZbz3Htv
-wKeI8lN3s2Berq4o2jUsbzRF0ybh3uxbTydrFny9RAQYgrOJeRcQcT16ohZO9QHN
-pGxlaKFJdlxDydi8NmdspZS11My5vWo1ViHe2MPr+8ukYEywVaCge1ey
------END CERTIFICATE-----
-
-# Issuer: CN=COMODO ECC Certification Authority O=COMODO CA Limited
-# Subject: CN=COMODO ECC Certification Authority O=COMODO CA Limited
-# Label: "COMODO ECC Certification Authority"
-# Serial: 41578283867086692638256921589707938090
-# MD5 Fingerprint: 7c:62:ff:74:9d:31:53:5e:68:4a:d5:78:aa:1e:bf:23
-# SHA1 Fingerprint: 9f:74:4e:9f:2b:4d:ba:ec:0f:31:2c:50:b6:56:3b:8e:2d:93:c3:11
-# SHA256 Fingerprint: 17:93:92:7a:06:14:54:97:89:ad:ce:2f:8f:34:f7:f0:b6:6d:0f:3a:e3:a3:b8:4d:21:ec:15:db:ba:4f:ad:c7
------BEGIN CERTIFICATE-----
-MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTEL
-MAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE
-BxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMT
-IkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwMzA2MDAw
-MDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdy
-ZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09N
-T0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlv
-biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSR
-FtSrYpn1PlILBs5BAH+X4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0J
-cfRK9ChQtP6IHG4/bC8vCVlbpVsLM5niwz2J+Wos77LTBumjQjBAMB0GA1UdDgQW
-BBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/
-BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VGFAkK+qDm
-fQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdv
-GDeAU/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY=
------END CERTIFICATE-----
-
-# Issuer: CN=TC TrustCenter Class 2 CA II O=TC TrustCenter GmbH OU=TC TrustCenter Class 2 CA
-# Subject: CN=TC TrustCenter Class 2 CA II O=TC TrustCenter GmbH OU=TC TrustCenter Class 2 CA
-# Label: "TC TrustCenter Class 2 CA II"
-# Serial: 941389028203453866782103406992443
-# MD5 Fingerprint: ce:78:33:5c:59:78:01:6e:18:ea:b9:36:a0:b9:2e:23
-# SHA1 Fingerprint: ae:50:83:ed:7c:f4:5c:bc:8f:61:c6:21:fe:68:5d:79:42:21:15:6e
-# SHA256 Fingerprint: e6:b8:f8:76:64:85:f8:07:ae:7f:8d:ac:16:70:46:1f:07:c0:a1:3e:ef:3a:1f:f7:17:53:8d:7a:ba:d3:91:b4
------BEGIN CERTIFICATE-----
-MIIEqjCCA5KgAwIBAgIOLmoAAQACH9dSISwRXDswDQYJKoZIhvcNAQEFBQAwdjEL
-MAkGA1UEBhMCREUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxIjAgBgNV
-BAsTGVRDIFRydXN0Q2VudGVyIENsYXNzIDIgQ0ExJTAjBgNVBAMTHFRDIFRydXN0
-Q2VudGVyIENsYXNzIDIgQ0EgSUkwHhcNMDYwMTEyMTQzODQzWhcNMjUxMjMxMjI1
-OTU5WjB2MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1c3RDZW50ZXIgR21i
-SDEiMCAGA1UECxMZVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMiBDQTElMCMGA1UEAxMc
-VEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMiBDQSBJSTCCASIwDQYJKoZIhvcNAQEBBQAD
-ggEPADCCAQoCggEBAKuAh5uO8MN8h9foJIIRszzdQ2Lu+MNF2ujhoF/RKrLqk2jf
-tMjWQ+nEdVl//OEd+DFwIxuInie5e/060smp6RQvkL4DUsFJzfb95AhmC1eKokKg
-uNV/aVyQMrKXDcpK3EY+AlWJU+MaWss2xgdW94zPEfRMuzBwBJWl9jmM/XOBCH2J
-XjIeIqkiRUuwZi4wzJ9l/fzLganx4Duvo4bRierERXlQXa7pIXSSTYtZgo+U4+lK
-8edJsBTj9WLL1XK9H7nSn6DNqPoByNkN39r8R52zyFTfSUrxIan+GE7uSNQZu+99
-5OKdy1u2bv/jzVrndIIFuoAlOMvkaZ6vQaoahPUCAwEAAaOCATQwggEwMA8GA1Ud
-EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTjq1RMgKHbVkO3
-kUrL84J6E1wIqzCB7QYDVR0fBIHlMIHiMIHfoIHcoIHZhjVodHRwOi8vd3d3LnRy
-dXN0Y2VudGVyLmRlL2NybC92Mi90Y19jbGFzc18yX2NhX0lJLmNybIaBn2xkYXA6
-Ly93d3cudHJ1c3RjZW50ZXIuZGUvQ049VEMlMjBUcnVzdENlbnRlciUyMENsYXNz
-JTIwMiUyMENBJTIwSUksTz1UQyUyMFRydXN0Q2VudGVyJTIwR21iSCxPVT1yb290
-Y2VydHMsREM9dHJ1c3RjZW50ZXIsREM9ZGU/Y2VydGlmaWNhdGVSZXZvY2F0aW9u
-TGlzdD9iYXNlPzANBgkqhkiG9w0BAQUFAAOCAQEAjNfffu4bgBCzg/XbEeprS6iS
-GNn3Bzn1LL4GdXpoUxUc6krtXvwjshOg0wn/9vYua0Fxec3ibf2uWWuFHbhOIprt
-ZjluS5TmVfwLG4t3wVMTZonZKNaL80VKY7f9ewthXbhtvsPcW3nS7Yblok2+XnR8
-au0WOB9/WIFaGusyiC2y8zl3gK9etmF1KdsjTYjKUCjLhdLTEKJZbtOTVAB6okaV
-hgWcqRmY5TFyDADiZ9lA4CQze28suVyrZZ0srHbqNZn1l7kPJOzHdiEoZa5X6AeI
-dUpWoNIFOqTmjZKILPPy4cHGYdtBxceb9w4aUUXCYWvcZCcXjFq32nQozZfkvQ==
------END CERTIFICATE-----
-
-# Issuer: CN=TC TrustCenter Class 3 CA II O=TC TrustCenter GmbH OU=TC TrustCenter Class 3 CA
-# Subject: CN=TC TrustCenter Class 3 CA II O=TC TrustCenter GmbH OU=TC TrustCenter Class 3 CA
-# Label: "TC TrustCenter Class 3 CA II"
-# Serial: 1506523511417715638772220530020799
-# MD5 Fingerprint: 56:5f:aa:80:61:12:17:f6:67:21:e6:2b:6d:61:56:8e
-# SHA1 Fingerprint: 80:25:ef:f4:6e:70:c8:d4:72:24:65:84:fe:40:3b:8a:8d:6a:db:f5
-# SHA256 Fingerprint: 8d:a0:84:fc:f9:9c:e0:77:22:f8:9b:32:05:93:98:06:fa:5c:b8:11:e1:c8:13:f6:a1:08:c7:d3:36:b3:40:8e
------BEGIN CERTIFICATE-----
-MIIEqjCCA5KgAwIBAgIOSkcAAQAC5aBd1j8AUb8wDQYJKoZIhvcNAQEFBQAwdjEL
-MAkGA1UEBhMCREUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxIjAgBgNV
-BAsTGVRDIFRydXN0Q2VudGVyIENsYXNzIDMgQ0ExJTAjBgNVBAMTHFRDIFRydXN0
-Q2VudGVyIENsYXNzIDMgQ0EgSUkwHhcNMDYwMTEyMTQ0MTU3WhcNMjUxMjMxMjI1
-OTU5WjB2MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1c3RDZW50ZXIgR21i
-SDEiMCAGA1UECxMZVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMyBDQTElMCMGA1UEAxMc
-VEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMyBDQSBJSTCCASIwDQYJKoZIhvcNAQEBBQAD
-ggEPADCCAQoCggEBALTgu1G7OVyLBMVMeRwjhjEQY0NVJz/GRcekPewJDRoeIMJW
-Ht4bNwcwIi9v8Qbxq63WyKthoy9DxLCyLfzDlml7forkzMA5EpBCYMnMNWju2l+Q
-Vl/NHE1bWEnrDgFPZPosPIlY2C8u4rBo6SI7dYnWRBpl8huXJh0obazovVkdKyT2
-1oQDZogkAHhg8fir/gKya/si+zXmFtGt9i4S5Po1auUZuV3bOx4a+9P/FRQI2Alq
-ukWdFHlgfa9Aigdzs5OW03Q0jTo3Kd5c7PXuLjHCINy+8U9/I1LZW+Jk2ZyqBwi1
-Rb3R0DHBq1SfqdLDYmAD8bs5SpJKPQq5ncWg/jcCAwEAAaOCATQwggEwMA8GA1Ud
-EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTUovyfs8PYA9NX
-XAek0CSnwPIA1DCB7QYDVR0fBIHlMIHiMIHfoIHcoIHZhjVodHRwOi8vd3d3LnRy
-dXN0Y2VudGVyLmRlL2NybC92Mi90Y19jbGFzc18zX2NhX0lJLmNybIaBn2xkYXA6
-Ly93d3cudHJ1c3RjZW50ZXIuZGUvQ049VEMlMjBUcnVzdENlbnRlciUyMENsYXNz
-JTIwMyUyMENBJTIwSUksTz1UQyUyMFRydXN0Q2VudGVyJTIwR21iSCxPVT1yb290
-Y2VydHMsREM9dHJ1c3RjZW50ZXIsREM9ZGU/Y2VydGlmaWNhdGVSZXZvY2F0aW9u
-TGlzdD9iYXNlPzANBgkqhkiG9w0BAQUFAAOCAQEANmDkcPcGIEPZIxpC8vijsrlN
-irTzwppVMXzEO2eatN9NDoqTSheLG43KieHPOh6sHfGcMrSOWXaiQYUlN6AT0PV8
-TtXqluJucsG7Kv5sbviRmEb8yRtXW+rIGjs/sFGYPAfaLFkB2otE6OF0/ado3VS6
-g0bsyEa1+K+XwDsJHI/OcpY9M1ZwvJbL2NV9IJqDnxrcOfHFcqMRA/07QlIp2+gB
-95tejNaNhk4Z+rwcvsUhpYeeeC422wlxo3I0+GzjBgnyXlal092Y+tTmBvTwtiBj
-S+opvaqCZh77gaqnN60TGOaSw4HBM7uIHqHn4rS9MWwOUT1v+5ZWgOI2F9Hc5A==
------END CERTIFICATE-----
-
-# Issuer: CN=TC TrustCenter Universal CA I O=TC TrustCenter GmbH OU=TC TrustCenter Universal CA
-# Subject: CN=TC TrustCenter Universal CA I O=TC TrustCenter GmbH OU=TC TrustCenter Universal CA
-# Label: "TC TrustCenter Universal CA I"
-# Serial: 601024842042189035295619584734726
-# MD5 Fingerprint: 45:e1:a5:72:c5:a9:36:64:40:9e:f5:e4:58:84:67:8c
-# SHA1 Fingerprint: 6b:2f:34:ad:89:58:be:62:fd:b0:6b:5c:ce:bb:9d:d9:4f:4e:39:f3
-# SHA256 Fingerprint: eb:f3:c0:2a:87:89:b1:fb:7d:51:19:95:d6:63:b7:29:06:d9:13:ce:0d:5e:10:56:8a:8a:77:e2:58:61:67:e7
------BEGIN CERTIFICATE-----
-MIID3TCCAsWgAwIBAgIOHaIAAQAC7LdggHiNtgYwDQYJKoZIhvcNAQEFBQAweTEL
-MAkGA1UEBhMCREUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxJDAiBgNV
-BAsTG1RDIFRydXN0Q2VudGVyIFVuaXZlcnNhbCBDQTEmMCQGA1UEAxMdVEMgVHJ1
-c3RDZW50ZXIgVW5pdmVyc2FsIENBIEkwHhcNMDYwMzIyMTU1NDI4WhcNMjUxMjMx
-MjI1OTU5WjB5MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1c3RDZW50ZXIg
-R21iSDEkMCIGA1UECxMbVEMgVHJ1c3RDZW50ZXIgVW5pdmVyc2FsIENBMSYwJAYD
-VQQDEx1UQyBUcnVzdENlbnRlciBVbml2ZXJzYWwgQ0EgSTCCASIwDQYJKoZIhvcN
-AQEBBQADggEPADCCAQoCggEBAKR3I5ZEr5D0MacQ9CaHnPM42Q9e3s9B6DGtxnSR
-JJZ4Hgmgm5qVSkr1YnwCqMqs+1oEdjneX/H5s7/zA1hV0qq34wQi0fiU2iIIAI3T
-fCZdzHd55yx4Oagmcw6iXSVphU9VDprvxrlE4Vc93x9UIuVvZaozhDrzznq+VZeu
-jRIPFDPiUHDDSYcTvFHe15gSWu86gzOSBnWLknwSaHtwag+1m7Z3W0hZneTvWq3z
-wZ7U10VOylY0Ibw+F1tvdwxIAUMpsN0/lm7mlaoMwCC2/T42J5zjXM9OgdwZu5GQ
-fezmlwQek8wiSdeXhrYTCjxDI3d+8NzmzSQfO4ObNDqDNOMCAwEAAaNjMGEwHwYD
-VR0jBBgwFoAUkqR1LKSevoFE63n8isWVpesQdXMwDwYDVR0TAQH/BAUwAwEB/zAO
-BgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFJKkdSyknr6BROt5/IrFlaXrEHVzMA0G
-CSqGSIb3DQEBBQUAA4IBAQAo0uCG1eb4e/CX3CJrO5UUVg8RMKWaTzqwOuAGy2X1
-7caXJ/4l8lfmXpWMPmRgFVp/Lw0BxbFg/UU1z/CyvwbZ71q+s2IhtNerNXxTPqYn
-8aEt2hojnczd7Dwtnic0XQ/CNnm8yUpiLe1r2X1BQ3y2qsrtYbE3ghUJGooWMNjs
-ydZHcnhLEEYUjl8Or+zHL6sQ17bxbuyGssLoDZJz3KL0Dzq/YSMQiZxIQG5wALPT
-ujdEWBF6AmqI8Dc08BnprNRlc/ZpjGSUOnmFKbAWKwyCPwacx/0QK54PLLae4xW/
-2TYcuiUaUj0a7CIMHOCkoj3w6DnPgcB77V0fb8XQC9eY
------END CERTIFICATE-----
-
-# Issuer: CN=Cybertrust Global Root O=Cybertrust, Inc
-# Subject: CN=Cybertrust Global Root O=Cybertrust, Inc
-# Label: "Cybertrust Global Root"
-# Serial: 4835703278459682877484360
-# MD5 Fingerprint: 72:e4:4a:87:e3:69:40:80:77:ea:bc:e3:f4:ff:f0:e1
-# SHA1 Fingerprint: 5f:43:e5:b1:bf:f8:78:8c:ac:1c:c7:ca:4a:9a:c6:22:2b:cc:34:c6
-# SHA256 Fingerprint: 96:0a:df:00:63:e9:63:56:75:0c:29:65:dd:0a:08:67:da:0b:9c:bd:6e:77:71:4a:ea:fb:23:49:ab:39:3d:a3
------BEGIN CERTIFICATE-----
-MIIDoTCCAomgAwIBAgILBAAAAAABD4WqLUgwDQYJKoZIhvcNAQEFBQAwOzEYMBYG
-A1UEChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2Jh
-bCBSb290MB4XDTA2MTIxNTA4MDAwMFoXDTIxMTIxNTA4MDAwMFowOzEYMBYGA1UE
-ChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2JhbCBS
-b290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA+Mi8vRRQZhP/8NN5
-7CPytxrHjoXxEnOmGaoQ25yiZXRadz5RfVb23CO21O1fWLE3TdVJDm71aofW0ozS
-J8bi/zafmGWgE07GKmSb1ZASzxQG9Dvj1Ci+6A74q05IlG2OlTEQXO2iLb3VOm2y
-HLtgwEZLAfVJrn5GitB0jaEMAs7u/OePuGtm839EAL9mJRQr3RAwHQeWP032a7iP
-t3sMpTjr3kfb1V05/Iin89cqdPHoWqI7n1C6poxFNcJQZZXcY4Lv3b93TZxiyWNz
-FtApD0mpSPCzqrdsxacwOUBdrsTiXSZT8M4cIwhhqJQZugRiQOwfOHB3EgZxpzAY
-XSUnpQIDAQABo4GlMIGiMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/
-MB0GA1UdDgQWBBS2CHsNesysIEyGVjJez6tuhS1wVzA/BgNVHR8EODA2MDSgMqAw
-hi5odHRwOi8vd3d3Mi5wdWJsaWMtdHJ1c3QuY29tL2NybC9jdC9jdHJvb3QuY3Js
-MB8GA1UdIwQYMBaAFLYIew16zKwgTIZWMl7Pq26FLXBXMA0GCSqGSIb3DQEBBQUA
-A4IBAQBW7wojoFROlZfJ+InaRcHUowAl9B8Tq7ejhVhpwjCt2BWKLePJzYFa+HMj
-Wqd8BfP9IjsO0QbE2zZMcwSO5bAi5MXzLqXZI+O4Tkogp24CJJ8iYGd7ix1yCcUx
-XOl5n4BHPa2hCwcUPUf/A2kaDAtE52Mlp3+yybh2hO0j9n0Hq0V+09+zv+mKts2o
-omcrUtW3ZfA5TGOgkXmTUg9U3YO7n9GPp1Nzw8v/MOx8BLjYRB+TX3EJIrduPuoc
-A06dGiBh+4E37F78CkWr1+cXVdCg6mCbpvbjjFspwgZgFJ0tl0ypkxWdYcQBX0jW
-WL1WMRJOEcgh4LMRkWXbtKaIOM5V
------END CERTIFICATE-----
-
-# Issuer: CN=GeoTrust Primary Certification Authority - G3 O=GeoTrust Inc. OU=(c) 2008 GeoTrust Inc. - For authorized use only
-# Subject: CN=GeoTrust Primary Certification Authority - G3 O=GeoTrust Inc. OU=(c) 2008 GeoTrust Inc. - For authorized use only
-# Label: "GeoTrust Primary Certification Authority - G3"
-# Serial: 28809105769928564313984085209975885599
-# MD5 Fingerprint: b5:e8:34:36:c9:10:44:58:48:70:6d:2e:83:d4:b8:05
-# SHA1 Fingerprint: 03:9e:ed:b8:0b:e7:a0:3c:69:53:89:3b:20:d2:d9:32:3a:4c:2a:fd
-# SHA256 Fingerprint: b4:78:b8:12:25:0d:f8:78:63:5c:2a:a7:ec:7d:15:5e:aa:62:5e:e8:29:16:e2:cd:29:43:61:88:6c:d1:fb:d4
------BEGIN CERTIFICATE-----
-MIID/jCCAuagAwIBAgIQFaxulBmyeUtB9iepwxgPHzANBgkqhkiG9w0BAQsFADCB
-mDELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsT
-MChjKSAyMDA4IEdlb1RydXN0IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25s
-eTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhv
-cml0eSAtIEczMB4XDTA4MDQwMjAwMDAwMFoXDTM3MTIwMTIzNTk1OVowgZgxCzAJ
-BgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykg
-MjAwOCBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0
-BgNVBAMTLUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg
-LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANziXmJYHTNXOTIz
-+uvLh4yn1ErdBojqZI4xmKU4kB6Yzy5jK/BGvESyiaHAKAxJcCGVn2TAppMSAmUm
-hsalifD614SgcK9PGpc/BkTVyetyEH3kMSj7HGHmKAdEc5IiaacDiGydY8hS2pgn
-5whMcD60yRLBxWeDXTPzAxHsatBT4tG6NmCUgLthY2xbF37fQJQeqw3CIShwiP/W
-JmxsYAQlTlV+fe+/lEjetx3dcI0FX4ilm/LC7urRQEFtYjgdVgbFA0dRIBn8exAL
-DmKudlW/X3e+PkkBUz2YJQN2JFodtNuJ6nnltrM7P7pMKEF/BqxqjsHQ9gUdfeZC
-huOl1UcCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw
-HQYDVR0OBBYEFMR5yo6hTgMdHNxr2zFblD4/MH8tMA0GCSqGSIb3DQEBCwUAA4IB
-AQAtxRPPVoB7eni9n64smefv2t+UXglpp+duaIy9cr5HqQ6XErhK8WTTOd8lNNTB
-zU6B8A8ExCSzNJbGpqow32hhc9f5joWJ7w5elShKKiePEI4ufIbEAp7aDHdlDkQN
-kv39sxY2+hENHYwOB4lqKVb3cvTdFZx3NWZXqxNT2I7BQMXXExZacse3aQHEerGD
-AWh9jUGhlBjBJVz88P6DAod8DQ3PLghcSkANPuyBYeYk28rgDi0Hsj5W3I31QYUH
-SJsMC8tJP33st/3LjWeJGqvtux6jAAgIFyqCXDFdRootD4abdNlF+9RAsXqqaC2G
-spki4cErx5z481+oghLrGREt
------END CERTIFICATE-----
-
-# Issuer: CN=thawte Primary Root CA - G2 O=thawte, Inc. OU=(c) 2007 thawte, Inc. - For authorized use only
-# Subject: CN=thawte Primary Root CA - G2 O=thawte, Inc. OU=(c) 2007 thawte, Inc. - For authorized use only
-# Label: "thawte Primary Root CA - G2"
-# Serial: 71758320672825410020661621085256472406
-# MD5 Fingerprint: 74:9d:ea:60:24:c4:fd:22:53:3e:cc:3a:72:d9:29:4f
-# SHA1 Fingerprint: aa:db:bc:22:23:8f:c4:01:a1:27:bb:38:dd:f4:1d:db:08:9e:f0:12
-# SHA256 Fingerprint: a4:31:0d:50:af:18:a6:44:71:90:37:2a:86:af:af:8b:95:1f:fb:43:1d:83:7f:1e:56:88:b4:59:71:ed:15:57
------BEGIN CERTIFICATE-----
-MIICiDCCAg2gAwIBAgIQNfwmXNmET8k9Jj1Xm67XVjAKBggqhkjOPQQDAzCBhDEL
-MAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjE4MDYGA1UECxMvKGMp
-IDIwMDcgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAi
-BgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMjAeFw0wNzExMDUwMDAw
-MDBaFw0zODAxMTgyMzU5NTlaMIGEMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhh
-d3RlLCBJbmMuMTgwNgYDVQQLEy8oYykgMjAwNyB0aGF3dGUsIEluYy4gLSBGb3Ig
-YXV0aG9yaXplZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9v
-dCBDQSAtIEcyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEotWcgnuVnfFSeIf+iha/
-BebfowJPDQfGAFG6DAJSLSKkQjnE/o/qycG+1E3/n3qe4rF8mq2nhglzh9HnmuN6
-papu+7qzcMBniKI11KOasf2twu8x+qi58/sIxpHR+ymVo0IwQDAPBgNVHRMBAf8E
-BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUmtgAMADna3+FGO6Lts6K
-DPgR4bswCgYIKoZIzj0EAwMDaQAwZgIxAN344FdHW6fmCsO99YCKlzUNG4k8VIZ3
-KMqh9HneteY4sPBlcIx/AlTCv//YoT7ZzwIxAMSNlPzcU9LcnXgWHxUzI1NS41ox
-XZ3Krr0TKUQNJ1uo52icEvdYPy5yAlejj6EULg==
------END CERTIFICATE-----
-
-# Issuer: CN=thawte Primary Root CA - G3 O=thawte, Inc. OU=Certification Services Division/(c) 2008 thawte, Inc. - For authorized use only
-# Subject: CN=thawte Primary Root CA - G3 O=thawte, Inc. OU=Certification Services Division/(c) 2008 thawte, Inc. - For authorized use only
-# Label: "thawte Primary Root CA - G3"
-# Serial: 127614157056681299805556476275995414779
-# MD5 Fingerprint: fb:1b:5d:43:8a:94:cd:44:c6:76:f2:43:4b:47:e7:31
-# SHA1 Fingerprint: f1:8b:53:8d:1b:e9:03:b6:a6:f0:56:43:5b:17:15:89:ca:f3:6b:f2
-# SHA256 Fingerprint: 4b:03:f4:58:07:ad:70:f2:1b:fc:2c:ae:71:c9:fd:e4:60:4c:06:4c:f5:ff:b6:86:ba:e5:db:aa:d7:fd:d3:4c
------BEGIN CERTIFICATE-----
-MIIEKjCCAxKgAwIBAgIQYAGXt0an6rS0mtZLL/eQ+zANBgkqhkiG9w0BAQsFADCB
-rjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMf
-Q2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIw
-MDggdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAiBgNV
-BAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMzAeFw0wODA0MDIwMDAwMDBa
-Fw0zNzEyMDEyMzU5NTlaMIGuMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhhd3Rl
-LCBJbmMuMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9u
-MTgwNgYDVQQLEy8oYykgMjAwOCB0aGF3dGUsIEluYy4gLSBGb3IgYXV0aG9yaXpl
-ZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAtIEcz
-MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsr8nLPvb2FvdeHsbnndm
-gcs+vHyu86YnmjSjaDFxODNi5PNxZnmxqWWjpYvVj2AtP0LMqmsywCPLLEHd5N/8
-YZzic7IilRFDGF/Eth9XbAoFWCLINkw6fKXRz4aviKdEAhN0cXMKQlkC+BsUa0Lf
-b1+6a4KinVvnSr0eAXLbS3ToO39/fR8EtCab4LRarEc9VbjXsCZSKAExQGbY2SS9
-9irY7CFJXJv2eul/VTV+lmuNk5Mny5K76qxAwJ/C+IDPXfRa3M50hqY+bAtTyr2S
-zhkGcuYMXDhpxwTWvGzOW/b3aJzcJRVIiKHpqfiYnODz1TEoYRFsZ5aNOZnLwkUk
-OQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNV
-HQ4EFgQUrWyqlGCc7eT/+j4KdCtjA/e2Wb8wDQYJKoZIhvcNAQELBQADggEBABpA
-2JVlrAmSicY59BDlqQ5mU1143vokkbvnRFHfxhY0Cu9qRFHqKweKA3rD6z8KLFIW
-oCtDuSWQP3CpMyVtRRooOyfPqsMpQhvfO0zAMzRbQYi/aytlryjvsvXDqmbOe1bu
-t8jLZ8HJnBoYuMTDSQPxYA5QzUbF83d597YV4Djbxy8ooAw/dyZ02SUS2jHaGh7c
-KUGRIjxpp7sC8rZcJwOJ9Abqm+RyguOhCcHpABnTPtRwa7pxpqpYrvS76Wy274fM
-m7v/OeZWYdMKp8RcTGB7BXcmer/YB1IsYvdwY9k5vG8cwnncdimvzsUsZAReiDZu
-MdRAGmI0Nj81Aa6sY6A=
------END CERTIFICATE-----
-
-# Issuer: CN=GeoTrust Primary Certification Authority - G2 O=GeoTrust Inc. OU=(c) 2007 GeoTrust Inc. - For authorized use only
-# Subject: CN=GeoTrust Primary Certification Authority - G2 O=GeoTrust Inc. OU=(c) 2007 GeoTrust Inc. - For authorized use only
-# Label: "GeoTrust Primary Certification Authority - G2"
-# Serial: 80682863203381065782177908751794619243
-# MD5 Fingerprint: 01:5e:d8:6b:bd:6f:3d:8e:a1:31:f8:12:e0:98:73:6a
-# SHA1 Fingerprint: 8d:17:84:d5:37:f3:03:7d:ec:70:fe:57:8b:51:9a:99:e6:10:d7:b0
-# SHA256 Fingerprint: 5e:db:7a:c4:3b:82:a0:6a:87:61:e8:d7:be:49:79:eb:f2:61:1f:7d:d7:9b:f9:1c:1c:6b:56:6a:21:9e:d7:66
------BEGIN CERTIFICATE-----
-MIICrjCCAjWgAwIBAgIQPLL0SAoA4v7rJDteYD7DazAKBggqhkjOPQQDAzCBmDEL
-MAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChj
-KSAyMDA3IEdlb1RydXN0IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2
-MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0
-eSAtIEcyMB4XDTA3MTEwNTAwMDAwMFoXDTM4MDExODIzNTk1OVowgZgxCzAJBgNV
-BAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykgMjAw
-NyBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNV
-BAMTLUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBH
-MjB2MBAGByqGSM49AgEGBSuBBAAiA2IABBWx6P0DFUPlrOuHNxFi79KDNlJ9RVcL
-So17VDs6bl8VAsBQps8lL33KSLjHUGMcKiEIfJo22Av+0SbFWDEwKCXzXV2juLal
-tJLtbCyf691DiaI8S0iRHVDsJt/WYC69IaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO
-BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBVfNVdRVfslsq0DafwBo/q+EVXVMAoG
-CCqGSM49BAMDA2cAMGQCMGSWWaboCd6LuvpaiIjwH5HTRqjySkwCY/tsXzjbLkGT
-qQ7mndwxHLKgpxgceeHHNgIwOlavmnRs9vuD4DPTCF+hnMJbn0bWtsuRBmOiBucz
-rD6ogRLQy7rQkgu2npaqBA+K
------END CERTIFICATE-----
-
-# Issuer: CN=VeriSign Universal Root Certification Authority O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2008 VeriSign, Inc. - For authorized use only
-# Subject: CN=VeriSign Universal Root Certification Authority O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2008 VeriSign, Inc. - For authorized use only
-# Label: "VeriSign Universal Root Certification Authority"
-# Serial: 85209574734084581917763752644031726877
-# MD5 Fingerprint: 8e:ad:b5:01:aa:4d:81:e4:8c:1d:d1:e1:14:00:95:19
-# SHA1 Fingerprint: 36:79:ca:35:66:87:72:30:4d:30:a5:fb:87:3b:0f:a7:7b:b7:0d:54
-# SHA256 Fingerprint: 23:99:56:11:27:a5:71:25:de:8c:ef:ea:61:0d:df:2f:a0:78:b5:c8:06:7f:4e:82:82:90:bf:b8:60:e8:4b:3c
------BEGIN CERTIFICATE-----
-MIIEuTCCA6GgAwIBAgIQQBrEZCGzEyEDDrvkEhrFHTANBgkqhkiG9w0BAQsFADCB
-vTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL
-ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwOCBWZXJp
-U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MTgwNgYDVQQDEy9W
-ZXJpU2lnbiBVbml2ZXJzYWwgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe
-Fw0wODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIG9MQswCQYDVQQGEwJVUzEX
-MBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0
-IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9y
-IGF1dGhvcml6ZWQgdXNlIG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNh
-bCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEF
-AAOCAQ8AMIIBCgKCAQEAx2E3XrEBNNti1xWb/1hajCMj1mCOkdeQmIN65lgZOIzF
-9uVkhbSicfvtvbnazU0AtMgtc6XHaXGVHzk8skQHnOgO+k1KxCHfKWGPMiJhgsWH
-H26MfF8WIFFE0XBPV+rjHOPMee5Y2A7Cs0WTwCznmhcrewA3ekEzeOEz4vMQGn+H
-LL729fdC4uW/h2KJXwBL38Xd5HVEMkE6HnFuacsLdUYI0crSK5XQz/u5QGtkjFdN
-/BMReYTtXlT2NJ8IAfMQJQYXStrxHXpma5hgZqTZ79IugvHw7wnqRMkVauIDbjPT
-rJ9VAMf2CGqUuV/c4DPxhGD5WycRtPwW8rtWaoAljQIDAQABo4GyMIGvMA8GA1Ud
-EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMG0GCCsGAQUFBwEMBGEwX6FdoFsw
-WTBXMFUWCWltYWdlL2dpZjAhMB8wBwYFKw4DAhoEFI/l0xqGrI2Oa8PPgGrUSBgs
-exkuMCUWI2h0dHA6Ly9sb2dvLnZlcmlzaWduLmNvbS92c2xvZ28uZ2lmMB0GA1Ud
-DgQWBBS2d/ppSEefUxLVwuoHMnYH0ZcHGTANBgkqhkiG9w0BAQsFAAOCAQEASvj4
-sAPmLGd75JR3Y8xuTPl9Dg3cyLk1uXBPY/ok+myDjEedO2Pzmvl2MpWRsXe8rJq+
-seQxIcaBlVZaDrHC1LGmWazxY8u4TB1ZkErvkBYoH1quEPuBUDgMbMzxPcP1Y+Oz
-4yHJJDnp/RVmRvQbEdBNc6N9Rvk97ahfYtTxP/jgdFcrGJ2BtMQo2pSXpXDrrB2+
-BxHw1dvd5Yzw1TKwg+ZX4o+/vqGqvz0dtdQ46tewXDpPaj+PwGZsY6rp2aQW9IHR
-lRQOfc2VNNnSj3BzgXucfr2YYdhFh5iQxeuGMMY1v/D/w1WIg0vvBZIGcfK4mJO3
-7M2CYfE45k+XmCpajQ==
------END CERTIFICATE-----
-
-# Issuer: CN=VeriSign Class 3 Public Primary Certification Authority - G4 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2007 VeriSign, Inc. - For authorized use only
-# Subject: CN=VeriSign Class 3 Public Primary Certification Authority - G4 O=VeriSign, Inc. OU=VeriSign Trust Network/(c) 2007 VeriSign, Inc. - For authorized use only
-# Label: "VeriSign Class 3 Public Primary Certification Authority - G4"
-# Serial: 63143484348153506665311985501458640051
-# MD5 Fingerprint: 3a:52:e1:e7:fd:6f:3a:e3:6f:f3:6f:99:1b:f9:22:41
-# SHA1 Fingerprint: 22:d5:d8:df:8f:02:31:d1:8d:f7:9d:b7:cf:8a:2d:64:c9:3f:6c:3a
-# SHA256 Fingerprint: 69:dd:d7:ea:90:bb:57:c9:3e:13:5d:c8:5e:a6:fc:d5:48:0b:60:32:39:bd:c4:54:fc:75:8b:2a:26:cf:7f:79
------BEGIN CERTIFICATE-----
-MIIDhDCCAwqgAwIBAgIQL4D+I4wOIg9IZxIokYesszAKBggqhkjOPQQDAzCByjEL
-MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW
-ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2ln
-biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp
-U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y
-aXR5IC0gRzQwHhcNMDcxMTA1MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCByjELMAkG
-A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJp
-U2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwg
-SW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2ln
-biBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5
-IC0gRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASnVnp8Utpkmw4tXNherJI9/gHm
-GUo9FANL+mAnINmDiWn6VMaaGF5VKmTeBvaNSjutEDxlPZCIBIngMGGzrl0Bp3ve
-fLK+ymVhAIau2o970ImtTR1ZmkGxvEeA3J5iw/mjgbIwga8wDwYDVR0TAQH/BAUw
-AwEB/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJ
-aW1hZ2UvZ2lmMCEwHzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYj
-aHR0cDovL2xvZ28udmVyaXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFLMW
-kf3upm7ktS5Jj4d4gYDs5bG1MAoGCCqGSM49BAMDA2gAMGUCMGYhDBgmYFo4e1ZC
-4Kf8NoRRkSAsdk1DPcQdhCPQrNZ8NQbOzWm9kA3bbEhCHQ6qQgIxAJw9SDkjOVga
-FRJZap7v1VmyHVIsmXHNxynfGyphe3HR3vPA5Q06Sqotp9iGKt0uEA==
------END CERTIFICATE-----
-
-# Issuer: O=VeriSign, Inc. OU=Class 3 Public Primary Certification Authority
-# Subject: O=VeriSign, Inc. OU=Class 3 Public Primary Certification Authority
-# Label: "Verisign Class 3 Public Primary Certification Authority"
-# Serial: 80507572722862485515306429940691309246
-# MD5 Fingerprint: ef:5a:f1:33:ef:f1:cd:bb:51:02:ee:12:14:4b:96:c4
-# SHA1 Fingerprint: a1:db:63:93:91:6f:17:e4:18:55:09:40:04:15:c7:02:40:b0:ae:6b
-# SHA256 Fingerprint: a4:b6:b3:99:6f:c2:f3:06:b3:fd:86:81:bd:63:41:3d:8c:50:09:cc:4f:a3:29:c2:cc:f0:e2:fa:1b:14:03:05
------BEGIN CERTIFICATE-----
-MIICPDCCAaUCEDyRMcsf9tAbDpq40ES/Er4wDQYJKoZIhvcNAQEFBQAwXzELMAkG
-A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz
-cyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2
-MDEyOTAwMDAwMFoXDTI4MDgwMjIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV
-BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmlt
-YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN
-ADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhE
-BarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/is
-I19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0G
-CSqGSIb3DQEBBQUAA4GBABByUqkFFBkyCEHwxWsKzH4PIRnN5GfcX6kb5sroc50i
-2JhucwNhkcV8sEVAbkSdjbCxlnRhLQ2pRdKkkirWmnWXbj9T/UWZYB2oK0z5XqcJ
-2HUw19JlYD1n1khVdWk/kfVIC0dpImmClr7JyDiGSnoscxlIaU5rfGW/D/xwzoiQ
------END CERTIFICATE-----
-
-# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R3
-# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R3
-# Label: "GlobalSign Root CA - R3"
-# Serial: 4835703278459759426209954
-# MD5 Fingerprint: c5:df:b8:49:ca:05:13:55:ee:2d:ba:1a:c3:3e:b0:28
-# SHA1 Fingerprint: d6:9b:56:11:48:f0:1c:77:c5:45:78:c1:09:26:df:5b:85:69:76:ad
-# SHA256 Fingerprint: cb:b5:22:d7:b7:f1:27:ad:6a:01:13:86:5b:df:1c:d4:10:2e:7d:07:59:af:63:5a:7c:f4:72:0d:c9:63:c5:3b
------BEGIN CERTIFICATE-----
-MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G
-A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp
-Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4
-MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG
-A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI
-hvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8
-RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT
-gHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm
-KPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd
-QQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ
-XriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw
-DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o
-LkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU
-RUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp
-jjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK
-6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX
-mcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs
-Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH
-WD9f
------END CERTIFICATE-----
-
-# Issuer: CN=TC TrustCenter Universal CA III O=TC TrustCenter GmbH OU=TC TrustCenter Universal CA
-# Subject: CN=TC TrustCenter Universal CA III O=TC TrustCenter GmbH OU=TC TrustCenter Universal CA
-# Label: "TC TrustCenter Universal CA III"
-# Serial: 2010889993983507346460533407902964
-# MD5 Fingerprint: 9f:dd:db:ab:ff:8e:ff:45:21:5f:f0:6c:9d:8f:fe:2b
-# SHA1 Fingerprint: 96:56:cd:7b:57:96:98:95:d0:e1:41:46:68:06:fb:b8:c6:11:06:87
-# SHA256 Fingerprint: 30:9b:4a:87:f6:ca:56:c9:31:69:aa:a9:9c:6d:98:88:54:d7:89:2b:d5:43:7e:2d:07:b2:9c:be:da:55:d3:5d
------BEGIN CERTIFICATE-----
-MIID4TCCAsmgAwIBAgIOYyUAAQACFI0zFQLkbPQwDQYJKoZIhvcNAQEFBQAwezEL
-MAkGA1UEBhMCREUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxJDAiBgNV
-BAsTG1RDIFRydXN0Q2VudGVyIFVuaXZlcnNhbCBDQTEoMCYGA1UEAxMfVEMgVHJ1
-c3RDZW50ZXIgVW5pdmVyc2FsIENBIElJSTAeFw0wOTA5MDkwODE1MjdaFw0yOTEy
-MzEyMzU5NTlaMHsxCzAJBgNVBAYTAkRFMRwwGgYDVQQKExNUQyBUcnVzdENlbnRl
-ciBHbWJIMSQwIgYDVQQLExtUQyBUcnVzdENlbnRlciBVbml2ZXJzYWwgQ0ExKDAm
-BgNVBAMTH1RDIFRydXN0Q2VudGVyIFVuaXZlcnNhbCBDQSBJSUkwggEiMA0GCSqG
-SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDC2pxisLlxErALyBpXsq6DFJmzNEubkKLF
-5+cvAqBNLaT6hdqbJYUtQCggbergvbFIgyIpRJ9Og+41URNzdNW88jBmlFPAQDYv
-DIRlzg9uwliT6CwLOunBjvvya8o84pxOjuT5fdMnnxvVZ3iHLX8LR7PH6MlIfK8v
-zArZQe+f/prhsq75U7Xl6UafYOPfjdN/+5Z+s7Vy+EutCHnNaYlAJ/Uqwa1D7KRT
-yGG299J5KmcYdkhtWyUB0SbFt1dpIxVbYYqt8Bst2a9c8SaQaanVDED1M4BDj5yj
-dipFtK+/fz6HP3bFzSreIMUWWMv5G/UPyw0RUmS40nZid4PxWJ//AgMBAAGjYzBh
-MB8GA1UdIwQYMBaAFFbn4VslQ4Dg9ozhcbyO5YAvxEjiMA8GA1UdEwEB/wQFMAMB
-Af8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRW5+FbJUOA4PaM4XG8juWAL8RI
-4jANBgkqhkiG9w0BAQUFAAOCAQEAg8ev6n9NCjw5sWi+e22JLumzCecYV42Fmhfz
-dkJQEw/HkG8zrcVJYCtsSVgZ1OK+t7+rSbyUyKu+KGwWaODIl0YgoGhnYIg5IFHY
-aAERzqf2EQf27OysGh+yZm5WZ2B6dF7AbZc2rrUNXWZzwCUyRdhKBgePxLcHsU0G
-DeGl6/R1yrqc0L2z0zIkTO5+4nYES0lT2PLpVDP85XEfPRRclkvxOvIAu2y0+pZV
-CIgJwcyRGSmwIC3/yzikQOEXvnlhgP8HA4ZMTnsGnxGGjYnuJ8Tb4rwZjgvDwxPH
-LQNjO9Po5KIqwoIIlBZU8O8fJ5AluA0OKBtHd0e9HKgl8ZS0Zg==
------END CERTIFICATE-----
-
-# Issuer: CN=Go Daddy Root Certificate Authority - G2 O=GoDaddy.com, Inc.
-# Subject: CN=Go Daddy Root Certificate Authority - G2 O=GoDaddy.com, Inc.
-# Label: "Go Daddy Root Certificate Authority - G2"
-# Serial: 0
-# MD5 Fingerprint: 80:3a:bc:22:c1:e6:fb:8d:9b:3b:27:4a:32:1b:9a:01
-# SHA1 Fingerprint: 47:be:ab:c9:22:ea:e8:0e:78:78:34:62:a7:9f:45:c2:54:fd:e6:8b
-# SHA256 Fingerprint: 45:14:0b:32:47:eb:9c:c8:c5:b4:f0:d7:b5:30:91:f7:32:92:08:9e:6e:5a:63:e2:74:9d:d3:ac:a9:19:8e:da
------BEGIN CERTIFICATE-----
-MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMx
-EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoT
-EUdvRGFkZHkuY29tLCBJbmMuMTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRp
-ZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIz
-NTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQH
-EwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8GA1UE
-AxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIw
-DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKD
-E6bFIEMBO4Tx5oVJnyfq9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH
-/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD+qK+ihVqf94Lw7YZFAXK6sOoBJQ7Rnwy
-DfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutdfMh8+7ArU6SSYmlRJQVh
-GkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMlNAJWJwGR
-tDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEA
-AaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE
-FDqahQcQZyi27/a9BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmX
-WWcDYfF+OwYxdS2hII5PZYe096acvNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu
-9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r5N9ss4UXnT3ZJE95kTXWXwTr
-gIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYVN8Gb5DKj7Tjo
-2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO
-LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI
-4uJEvlz36hz1
------END CERTIFICATE-----
-
-# Issuer: CN=Starfield Root Certificate Authority - G2 O=Starfield Technologies, Inc.
-# Subject: CN=Starfield Root Certificate Authority - G2 O=Starfield Technologies, Inc.
-# Label: "Starfield Root Certificate Authority - G2"
-# Serial: 0
-# MD5 Fingerprint: d6:39:81:c6:52:7e:96:69:fc:fc:ca:66:ed:05:f2:96
-# SHA1 Fingerprint: b5:1c:06:7c:ee:2b:0c:3d:f8:55:ab:2d:92:f4:fe:39:d4:e7:0f:0e
-# SHA256 Fingerprint: 2c:e1:cb:0b:f9:d2:f9:e1:02:99:3f:be:21:51:52:c3:b2:dd:0c:ab:de:1c:68:e5:31:9b:83:91:54:db:b7:f5
------BEGIN CERTIFICATE-----
-MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMx
-EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT
-HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVs
-ZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAw
-MFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6
-b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQgVGVj
-aG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZp
-Y2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
-ggEBAL3twQP89o/8ArFvW59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMg
-nLRJdzIpVv257IzdIvpy3Cdhl+72WoTsbhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1
-HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNkN3mSwOxGXn/hbVNMYq/N
-Hwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7NfZTD4p7dN
-dloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0
-HZbUJtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO
-BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0G
-CSqGSIb3DQEBCwUAA4IBAQARWfolTwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjU
-sHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx4mcujJUDJi5DnUox9g61DLu3
-4jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUwF5okxBDgBPfg
-8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K
-pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1
-mMpYjn0q7pBZc2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0
------END CERTIFICATE-----
-
-# Issuer: CN=Starfield Services Root Certificate Authority - G2 O=Starfield Technologies, Inc.
-# Subject: CN=Starfield Services Root Certificate Authority - G2 O=Starfield Technologies, Inc.
-# Label: "Starfield Services Root Certificate Authority - G2"
-# Serial: 0
-# MD5 Fingerprint: 17:35:74:af:7b:61:1c:eb:f4:f9:3c:e2:ee:40:f9:a2
-# SHA1 Fingerprint: 92:5a:8f:8d:2c:6d:04:e0:66:5f:59:6a:ff:22:d8:63:e8:25:6f:3f
-# SHA256 Fingerprint: 56:8d:69:05:a2:c8:87:08:a4:b3:02:51:90:ed:cf:ed:b1:97:4a:60:6a:13:c6:e5:29:0f:cb:2a:e6:3e:da:b5
------BEGIN CERTIFICATE-----
-MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMx
-EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT
-HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVs
-ZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5
-MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNVBAYTAlVTMRAwDgYD
-VQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFy
-ZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2Vy
-dmljZXMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI
-hvcNAQEBBQADggEPADCCAQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20p
-OsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm2
-8xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4PahHQUw2eeBGg6345AWh1K
-Ts9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLPLJGmpufe
-hRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk
-6mFBrMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAw
-DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+q
-AdcwKziIorhtSpzyEZGDMA0GCSqGSIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMI
-bw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPPE95Dz+I0swSdHynVv/heyNXB
-ve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTyxQGjhdByPq1z
-qwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd
-iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn
-0q23KXB56jzaYyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCN
-sSi6
------END CERTIFICATE-----
-
-# Issuer: CN=AffirmTrust Commercial O=AffirmTrust
-# Subject: CN=AffirmTrust Commercial O=AffirmTrust
-# Label: "AffirmTrust Commercial"
-# Serial: 8608355977964138876
-# MD5 Fingerprint: 82:92:ba:5b:ef:cd:8a:6f:a6:3d:55:f9:84:f6:d6:b7
-# SHA1 Fingerprint: f9:b5:b6:32:45:5f:9c:be:ec:57:5f:80:dc:e9:6e:2c:c7:b2:78:b7
-# SHA256 Fingerprint: 03:76:ab:1d:54:c5:f9:80:3c:e4:b2:e2:01:a0:ee:7e:ef:7b:57:b6:36:e8:a9:3c:9b:8d:48:60:c9:6f:5f:a7
------BEGIN CERTIFICATE-----
-MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UE
-BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz
-dCBDb21tZXJjaWFsMB4XDTEwMDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDEL
-MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp
-cm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
-AQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6EqdbDuKP
-Hx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yr
-ba0F8PrVC8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPAL
-MeIrJmqbTFeurCA+ukV6BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1
-yHp52UKqK39c/s4mT6NmgTWvRLpUHhwwMmWd5jyTXlBOeuM61G7MGvv50jeuJCqr
-VwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNVHQ4EFgQUnZPGU4teyq8/
-nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ
-KoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYG
-XUPGhi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNj
-vbz4YYCanrHOQnDiqX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivt
-Z8SOyUOyXGsViQK8YvxO8rUzqrJv0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9g
-N53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0khsUlHRUe072o0EclNmsxZt9YC
-nlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8=
------END CERTIFICATE-----
-
-# Issuer: CN=AffirmTrust Networking O=AffirmTrust
-# Subject: CN=AffirmTrust Networking O=AffirmTrust
-# Label: "AffirmTrust Networking"
-# Serial: 8957382827206547757
-# MD5 Fingerprint: 42:65:ca:be:01:9a:9a:4c:a9:8c:41:49:cd:c0:d5:7f
-# SHA1 Fingerprint: 29:36:21:02:8b:20:ed:02:f5:66:c5:32:d1:d6:ed:90:9f:45:00:2f
-# SHA256 Fingerprint: 0a:81:ec:5a:92:97:77:f1:45:90:4a:f3:8d:5d:50:9f:66:b5:e2:c5:8f:cd:b5:31:05:8b:0e:17:f3:f0:b4:1b
------BEGIN CERTIFICATE-----
-MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UE
-BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz
-dCBOZXR3b3JraW5nMB4XDTEwMDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDEL
-MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp
-cm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
-AQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SEHi3y
-YJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbua
-kCNrmreIdIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRL
-QESxG9fhwoXA3hA/Pe24/PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp
-6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gbh+0t+nvujArjqWaJGctB+d1ENmHP4ndG
-yH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNVHQ4EFgQUBx/S55zawm6i
-QLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ
-KoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfO
-tDIuUFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzu
-QY0x2+c06lkh1QF612S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZ
-Lgo/bNjR9eUJtGxUAArgFU2HdW23WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4u
-olu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9/ZFvgrG+CJPbFEfxojfHRZ48
-x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s=
------END CERTIFICATE-----
-
-# Issuer: CN=AffirmTrust Premium O=AffirmTrust
-# Subject: CN=AffirmTrust Premium O=AffirmTrust
-# Label: "AffirmTrust Premium"
-# Serial: 7893706540734352110
-# MD5 Fingerprint: c4:5d:0e:48:b6:ac:28:30:4e:0a:bc:f9:38:16:87:57
-# SHA1 Fingerprint: d8:a6:33:2c:e0:03:6f:b1:85:f6:63:4f:7d:6a:06:65:26:32:28:27
-# SHA256 Fingerprint: 70:a7:3f:7f:37:6b:60:07:42:48:90:45:34:b1:14:82:d5:bf:0e:69:8e:cc:49:8d:f5:25:77:eb:f2:e9:3b:9a
------BEGIN CERTIFICATE-----
-MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UE
-BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVz
-dCBQcmVtaXVtMB4XDTEwMDEyOTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkG
-A1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1U
-cnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxBLf
-qV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtnBKAQ
-JG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ
-+jjeRFcV5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrS
-s8PhaJyJ+HoAVt70VZVs+7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5
-HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmdGPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d7
-70O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5Rp9EixAqnOEhss/n/fauG
-V+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NIS+LI+H+S
-qHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S
-5u046uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4Ia
-C1nEWTJ3s7xgaVY5/bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TX
-OwF0lkLgAOIua+rF7nKsu7/+6qqo+Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYE
-FJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/
-BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByvMiPIs0laUZx2
-KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg
-Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B
-8OWycvpEgjNC6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQ
-MKSOyARiqcTtNd56l+0OOF6SL5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc
-0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK+4w1IX2COPKpVJEZNZOUbWo6xbLQ
-u4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmVBtWVyuEklut89pMF
-u+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFgIxpH
-YoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8
-GKa1qF60g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaO
-RtGdFNrHF+QFlozEJLUbzxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6e
-KeC2uAloGRwYQw==
------END CERTIFICATE-----
-
-# Issuer: CN=AffirmTrust Premium ECC O=AffirmTrust
-# Subject: CN=AffirmTrust Premium ECC O=AffirmTrust
-# Label: "AffirmTrust Premium ECC"
-# Serial: 8401224907861490260
-# MD5 Fingerprint: 64:b0:09:55:cf:b1:d5:99:e2:be:13:ab:a6:5d:ea:4d
-# SHA1 Fingerprint: b8:23:6b:00:2f:1d:16:86:53:01:55:6c:11:a4:37:ca:eb:ff:c3:bb
-# SHA256 Fingerprint: bd:71:fd:f6:da:97:e4:cf:62:d1:64:7a:dd:25:81:b0:7d:79:ad:f8:39:7e:b4:ec:ba:9c:5e:84:88:82:14:23
------BEGIN CERTIFICATE-----
-MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMC
-VVMxFDASBgNVBAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQ
-cmVtaXVtIEVDQzAeFw0xMDAxMjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJ
-BgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1UcnVzdDEgMB4GA1UEAwwXQWZmaXJt
-VHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQNMF4bFZ0D
-0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQN8O9
-ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0G
-A1UdDgQWBBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4G
-A1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/Vs
-aobgxCd05DhT1wV/GzTjxi+zygk8N53X57hG8f2h4nECMEJZh0PUUd+60wkyWs6I
-flc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKMeQ==
------END CERTIFICATE-----
-
-# Issuer: CN=StartCom Certification Authority O=StartCom Ltd. OU=Secure Digital Certificate Signing
-# Subject: CN=StartCom Certification Authority O=StartCom Ltd. OU=Secure Digital Certificate Signing
-# Label: "StartCom Certification Authority"
-# Serial: 45
-# MD5 Fingerprint: c9:3b:0d:84:41:fc:a4:76:79:23:08:57:de:10:19:16
-# SHA1 Fingerprint: a3:f1:33:3f:e2:42:bf:cf:c5:d1:4e:8f:39:42:98:40:68:10:d1:a0
-# SHA256 Fingerprint: e1:78:90:ee:09:a3:fb:f4:f4:8b:9c:41:4a:17:d6:37:b7:a5:06:47:e9:bc:75:23:22:72:7f:cc:17:42:a9:11
------BEGIN CERTIFICATE-----
-MIIHhzCCBW+gAwIBAgIBLTANBgkqhkiG9w0BAQsFADB9MQswCQYDVQQGEwJJTDEW
-MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg
-Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh
-dGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0NjM3WhcNMzYwOTE3MTk0NjM2WjB9
-MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMi
-U2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3Rh
-cnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUA
-A4ICDwAwggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZk
-pMyONvg45iPwbm2xPN1yo4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rf
-OQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/C
-Ji/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/deMotHweXMAEtcnn6RtYT
-Kqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt2PZE4XNi
-HzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMM
-Av+Z6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w
-+2OqqGwaVLRcJXrJosmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+
-Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3
-Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVcUjyJthkqcwEKDwOzEmDyei+B
-26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT37uMdBNSSwID
-AQABo4ICEDCCAgwwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD
-VR0OBBYEFE4L7xqkQFulF2mHMMo0aEPQQa7yMB8GA1UdIwQYMBaAFE4L7xqkQFul
-F2mHMMo0aEPQQa7yMIIBWgYDVR0gBIIBUTCCAU0wggFJBgsrBgEEAYG1NwEBATCC
-ATgwLgYIKwYBBQUHAgEWImh0dHA6Ly93d3cuc3RhcnRzc2wuY29tL3BvbGljeS5w
-ZGYwNAYIKwYBBQUHAgEWKGh0dHA6Ly93d3cuc3RhcnRzc2wuY29tL2ludGVybWVk
-aWF0ZS5wZGYwgc8GCCsGAQUFBwICMIHCMCcWIFN0YXJ0IENvbW1lcmNpYWwgKFN0
-YXJ0Q29tKSBMdGQuMAMCAQEagZZMaW1pdGVkIExpYWJpbGl0eSwgcmVhZCB0aGUg
-c2VjdGlvbiAqTGVnYWwgTGltaXRhdGlvbnMqIG9mIHRoZSBTdGFydENvbSBDZXJ0
-aWZpY2F0aW9uIEF1dGhvcml0eSBQb2xpY3kgYXZhaWxhYmxlIGF0IGh0dHA6Ly93
-d3cuc3RhcnRzc2wuY29tL3BvbGljeS5wZGYwEQYJYIZIAYb4QgEBBAQDAgAHMDgG
-CWCGSAGG+EIBDQQrFilTdGFydENvbSBGcmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1
-dGhvcml0eTANBgkqhkiG9w0BAQsFAAOCAgEAjo/n3JR5fPGFf59Jb2vKXfuM/gTF
-wWLRfUKKvFO3lANmMD+x5wqnUCBVJX92ehQN6wQOQOY+2IirByeDqXWmN3PH/UvS
-Ta0XQMhGvjt/UfzDtgUx3M2FIk5xt/JxXrAaxrqTi3iSSoX4eA+D/i+tLPfkpLst
-0OcNOrg+zvZ49q5HJMqjNTbOx8aHmNrs++myziebiMMEofYLWWivydsQD032ZGNc
-pRJvkrKTlMeIFw6Ttn5ii5B/q06f/ON1FE8qMt9bDeD1e5MNq6HPh+GlBEXoPBKl
-CcWw0bdT82AUuoVpaiF8H3VhFyAXe2w7QSlc4axa0c2Mm+tgHRns9+Ww2vl5GKVF
-P0lDV9LdJNUso/2RjSe15esUBppMeyG7Oq0wBhjA2MFrLH9ZXF2RsXAiV+uKa0hK
-1Q8p7MZAwC+ITGgBF3f0JBlPvfrhsiAhS90a2Cl9qrjeVOwhVYBsHvUwyKMQ5bLm
-KhQxw4UtjJixhlpPiVktucf3HMiKf8CdBUrmQk9io20ppB+Fq9vlgcitKj1MXVuE
-JnHEhV5xJMqlG2zYYdMa4FTbzrqpMrUi9nNBCV24F10OD5mQ1kfabwo6YigUZ4LZ
-8dCAWZvLMdibD4x3TrVoivJs9iQOLWxwxXPR3hTQcY+203sC9uO41Alua551hDnm
-fyWl8kgAwKQB2j8=
------END CERTIFICATE-----
-
-# Issuer: CN=StartCom Certification Authority G2 O=StartCom Ltd.
-# Subject: CN=StartCom Certification Authority G2 O=StartCom Ltd.
-# Label: "StartCom Certification Authority G2"
-# Serial: 59
-# MD5 Fingerprint: 78:4b:fb:9e:64:82:0a:d3:b8:4c:62:f3:64:f2:90:64
-# SHA1 Fingerprint: 31:f1:fd:68:22:63:20:ee:c6:3b:3f:9d:ea:4a:3e:53:7c:7c:39:17
-# SHA256 Fingerprint: c7:ba:65:67:de:93:a7:98:ae:1f:aa:79:1e:71:2d:37:8f:ae:1f:93:c4:39:7f:ea:44:1b:b7:cb:e6:fd:59:95
------BEGIN CERTIFICATE-----
-MIIFYzCCA0ugAwIBAgIBOzANBgkqhkiG9w0BAQsFADBTMQswCQYDVQQGEwJJTDEW
-MBQGA1UEChMNU3RhcnRDb20gTHRkLjEsMCoGA1UEAxMjU3RhcnRDb20gQ2VydGlm
-aWNhdGlvbiBBdXRob3JpdHkgRzIwHhcNMTAwMTAxMDEwMDAxWhcNMzkxMjMxMjM1
-OTAxWjBTMQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjEsMCoG
-A1UEAxMjU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgRzIwggIiMA0G
-CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2iTZbB7cgNr2Cu+EWIAOVeq8Oo1XJ
-JZlKxdBWQYeQTSFgpBSHO839sj60ZwNq7eEPS8CRhXBF4EKe3ikj1AENoBB5uNsD
-vfOpL9HG4A/LnooUCri99lZi8cVytjIl2bLzvWXFDSxu1ZJvGIsAQRSCb0AgJnoo
-D/Uefyf3lLE3PbfHkffiAez9lInhzG7TNtYKGXmu1zSCZf98Qru23QumNK9LYP5/
-Q0kGi4xDuFby2X8hQxfqp0iVAXV16iulQ5XqFYSdCI0mblWbq9zSOdIxHWDirMxW
-RST1HFSr7obdljKF+ExP6JV2tgXdNiNnvP8V4so75qbsO+wmETRIjfaAKxojAuuK
-HDp2KntWFhxyKrOq42ClAJ8Em+JvHhRYW6Vsi1g8w7pOOlz34ZYrPu8HvKTlXcxN
-nw3h3Kq74W4a7I/htkxNeXJdFzULHdfBR9qWJODQcqhaX2YtENwvKhOuJv4KHBnM
-0D4LnMgJLvlblnpHnOl68wVQdJVznjAJ85eCXuaPOQgeWeU1FEIT/wCc976qUM/i
-UUjXuG+v+E5+M5iSFGI6dWPPe/regjupuznixL0sAA7IF6wT700ljtizkC+p2il9
-Ha90OrInwMEePnWjFqmveiJdnxMaz6eg6+OGCtP95paV1yPIN93EfKo2rJgaErHg
-TuixO/XWb/Ew1wIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQE
-AwIBBjAdBgNVHQ4EFgQUS8W0QGutHLOlHGVuRjaJhwUMDrYwDQYJKoZIhvcNAQEL
-BQADggIBAHNXPyzVlTJ+N9uWkusZXn5T50HsEbZH77Xe7XRcxfGOSeD8bpkTzZ+K
-2s06Ctg6Wgk/XzTQLwPSZh0avZyQN8gMjgdalEVGKua+etqhqaRpEpKwfTbURIfX
-UfEpY9Z1zRbkJ4kd+MIySP3bmdCPX1R0zKxnNBFi2QwKN4fRoxdIjtIXHfbX/dtl
-6/2o1PXWT6RbdejF0mCy2wl+JYt7ulKSnj7oxXehPOBKc2thz4bcQ///If4jXSRK
-9dNtD2IEBVeC2m6kMyV5Sy5UGYvMLD0w6dEG/+gyRr61M3Z3qAFdlsHB1b6uJcDJ
-HgoJIIihDsnzb02CVAAgp9KP5DlUFy6NHrgbuxu9mk47EDTcnIhT76IxW1hPkWLI
-wpqazRVdOKnWvvgTtZ8SafJQYqz7Fzf07rh1Z2AQ+4NQ+US1dZxAF7L+/XldblhY
-XzD8AK6vM8EOTmy6p6ahfzLbOOCxchcKK5HsamMm7YnUeMx0HgX4a/6ManY5Ka5l
-IxKVCCIcl85bBu4M4ru8H0ST9tg4RQUh7eStqxK2A6RCLi3ECToDZ2mEmuFZkIoo
-hdVddLHRDiBYmxOlsGOm7XtH/UVVMKTumtTm4ofvmMkyghEpIrwACjFeLQ/Ajulr
-so8uBtjRkcfGEvRM/TAXw8HaOFvjqermobp573PYtlNXLfbQ4ddI
------END CERTIFICATE-----
diff --git a/chromium/tools/findit/common/http_client.py b/chromium/tools/findit/common/http_client.py
deleted file mode 100644
index ae3349dac46..00000000000
--- a/chromium/tools/findit/common/http_client.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright (c) 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.
-
-class HttpClient(object):
- """Represent a http client for sending request to a http[s] server.
-
- If cookies need to be sent, they should be in a file pointed to by
- COOKIE_FILE in the environment.
- """
-
- @staticmethod
- def Get(url, params={}, timeout=120, retries=5, retry_interval=0.5,
- retry_if_not=None):
- """Send a GET request to the given url with the given parameters.
-
- Args:
- url: the url to send request to.
- params: parameters to send as part of the http request.
- timeout: timeout for the http request, default is 120 seconds.
- retries: indicate how many retries before failing, default is 5.
- retry_interval: interval in second to wait before retry, default is 0.5.
- retry_if_not: a http status code. If set, retry only when the failed http
- status code is a different value.
-
- Returns:
- (status_code, data)
- state_code: the http status code in the response.
- data: the body of the response.
- """
- raise NotImplemented()
diff --git a/chromium/tools/findit/common/http_client_local.py b/chromium/tools/findit/common/http_client_local.py
deleted file mode 100644
index b8a168dce24..00000000000
--- a/chromium/tools/findit/common/http_client_local.py
+++ /dev/null
@@ -1,253 +0,0 @@
-# Copyright (c) 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 http client with support for https connections with certificate verification.
-
-The verification is based on http://tools.ietf.org/html/rfc6125#section-6.4.3
-and the code is from Lib/ssl.py in python3:
- http://hg.python.org/cpython/file/4dac45f88d45/Lib/ssl.py
-
-One use case is to download Chromium DEPS file in a secure way:
- https://src.chromium.org/chrome/trunk/src/DEPS
-
-Notice: python 2.7 or newer is required.
-"""
-
-import cookielib
-import httplib
-import os
-import re
-import socket
-import ssl
-import time
-import urllib
-import urllib2
-
-import http_client
-
-
-_SCRIPT_DIR = os.path.dirname(__file__)
-_TRUSTED_ROOT_CERTS = os.path.join(_SCRIPT_DIR, 'cacert.pem')
-
-
-class CertificateError(ValueError):
- pass
-
-
-def _DNSNameMatch(dn, hostname, max_wildcards=1):
- """Matching according to RFC 6125, section 6.4.3
-
- http://tools.ietf.org/html/rfc6125#section-6.4.3
- """
- pats = []
- if not dn:
- return False
-
- parts = dn.split(r'.')
- leftmost = parts[0]
- remainder = parts[1:]
-
- wildcards = leftmost.count('*')
- if wildcards > max_wildcards:
- # Issue #17980: avoid denials of service by refusing more
- # than one wildcard per fragment. A survery of established
- # policy among SSL implementations showed it to be a
- # reasonable choice.
- raise CertificateError(
- 'too many wildcards in certificate DNS name: ' + repr(dn))
-
- # speed up common case w/o wildcards
- if not wildcards:
- return dn.lower() == hostname.lower()
-
- # RFC 6125, section 6.4.3, subitem 1.
- # The client SHOULD NOT attempt to match a presented identifier in which
- # the wildcard character comprises a label other than the left-most label.
- if leftmost == '*':
- # When '*' is a fragment by itself, it matches a non-empty dotless
- # fragment.
- pats.append('[^.]+')
- elif leftmost.startswith('xn--') or hostname.startswith('xn--'):
- # RFC 6125, section 6.4.3, subitem 3.
- # The client SHOULD NOT attempt to match a presented identifier
- # where the wildcard character is embedded within an A-label or
- # U-label of an internationalized domain name.
- pats.append(re.escape(leftmost))
- else:
- # Otherwise, '*' matches any dotless string, e.g. www*
- pats.append(re.escape(leftmost).replace(r'\*', '[^.]*'))
-
- # add the remaining fragments, ignore any wildcards
- for frag in remainder:
- pats.append(re.escape(frag))
-
- pat = re.compile(r'\A' + r'\.'.join(pats) + r'\Z', re.IGNORECASE)
- return pat.match(hostname)
-
-
-def _MatchHostname(cert, hostname):
- """Verify that *cert* (in decoded format as returned by
- SSLSocket.getpeercert()) matches the *hostname*. RFC 2818 and RFC 6125
- rules are followed, but IP addresses are not accepted for *hostname*.
-
- CertificateError is raised on failure. On success, the function
- returns nothing.
- """
- if not cert:
- raise ValueError('empty or no certificate, match_hostname needs a '
- 'SSL socket or SSL context with either '
- 'CERT_OPTIONAL or CERT_REQUIRED')
- dnsnames = []
- san = cert.get('subjectAltName', ())
- for key, value in san:
- if key == 'DNS':
- if _DNSNameMatch(value, hostname):
- return
- dnsnames.append(value)
- if not dnsnames:
- # The subject is only checked when there is no dNSName entry
- # in subjectAltName
- for sub in cert.get('subject', ()):
- for key, value in sub:
- # XXX according to RFC 2818, the most specific Common Name
- # must be used.
- if key == 'commonName':
- if _DNSNameMatch(value, hostname):
- return
- dnsnames.append(value)
- if len(dnsnames) > 1:
- raise CertificateError('hostname %r doesn\'t match either of %s'
- % (hostname, ', '.join(map(repr, dnsnames))))
- elif len(dnsnames) == 1:
- raise CertificateError('hostname %r doesn\'t match %r'
- % (hostname, dnsnames[0]))
- else:
- raise CertificateError('no appropriate commonName or '
- 'subjectAltName fields were found')
-
-
-class HTTPSConnection(httplib.HTTPSConnection):
-
- def __init__(self, host, root_certs=_TRUSTED_ROOT_CERTS, **kwargs):
- self.root_certs = root_certs
- httplib.HTTPSConnection.__init__(self, host, **kwargs)
-
- def connect(self):
- # Overrides for certificate verification.
- args = [(self.host, self.port), self.timeout,]
- if self.source_address:
- args.append(self.source_address)
- sock = socket.create_connection(*args)
-
- if self._tunnel_host:
- self.sock = sock
- self._tunnel()
-
- # Wrap the socket for verification with the root certs.
- kwargs = {}
- if self.root_certs is not None:
- kwargs.update(cert_reqs=ssl.CERT_REQUIRED, ca_certs=self.root_certs)
- self.sock = ssl.wrap_socket(sock, **kwargs)
-
- # Check hostname.
- try:
- _MatchHostname(self.sock.getpeercert(), self.host)
- except CertificateError:
- self.sock.shutdown(socket.SHUT_RDWR)
- self.sock.close()
- raise
-
-
-class HTTPSHandler(urllib2.HTTPSHandler):
-
- def __init__(self, root_certs=_TRUSTED_ROOT_CERTS):
- urllib2.HTTPSHandler.__init__(self)
- self.root_certs = root_certs
-
- def https_open(self, req):
- # Pass a reference to the function below so that verification against
- # trusted root certs could be injected.
- return self.do_open(self.GetConnection, req)
-
- def GetConnection(self, host, **kwargs):
- params = dict(root_certs=self.root_certs)
- params.update(kwargs)
- return HTTPSConnection(host, **params)
-
-
-def _SendRequest(url, timeout=None):
- """Send request to the given https url, and return the server response.
-
- Args:
- url: The https url to send request to.
-
- Returns:
- An integer: http code of the response.
- A string: content of the response.
-
- Raises:
- CertificateError: Certificate verification fails.
- """
- if not url:
- return None, None
-
- handlers = []
- if url.startswith('https://'):
- # HTTPSHandler has to go first, because we don't want to send secure cookies
- # to a man in the middle.
- handlers.append(HTTPSHandler())
-
-
- cookie_file = os.environ.get('COOKIE_FILE')
- if cookie_file and os.path.exists(cookie_file):
- handlers.append(
- urllib2.HTTPCookieProcessor(cookielib.MozillaCookieJar(cookie_file)))
-
- url_opener = urllib2.build_opener(*handlers)
-
- status_code = None
- content = None
-
- try:
- response = url_opener.open(url, timeout=timeout)
-
- status_code = response.code
- content = response.read()
- except urllib2.HTTPError as e:
- status_code = e.code
- content = None
- except (ssl.SSLError, httplib.BadStatusLine, IOError):
- status_code = -1
- content = None
-
- return status_code, content
-
-
-class HttpClientLocal(http_client.HttpClient):
- """This http client is used locally in a workstation, GCE VMs, etc."""
-
- @staticmethod
- def Get(url, params={}, timeout=120, retries=5, retry_interval=0.5,
- retry_if_not=None):
- if params:
- url = '%s?%s' % (url, urllib.urlencode(params))
-
- count = 0
- while True:
- count += 1
-
- status_code, content = _SendRequest(url, timeout=timeout)
- if status_code == 200:
- return status_code, content
- if retry_if_not and status_code == retry_if_not:
- return status_code, content
-
- if count < retries:
- time.sleep(retry_interval)
- else:
- return status_code, content
-
- # Should never be reached.
- return status_code, content
diff --git a/chromium/tools/findit/common/http_client_local_unittest.py b/chromium/tools/findit/common/http_client_local_unittest.py
deleted file mode 100644
index 40d41fa5058..00000000000
--- a/chromium/tools/findit/common/http_client_local_unittest.py
+++ /dev/null
@@ -1,15 +0,0 @@
-# Copyright (c) 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.
-
-import unittest
-
-from http_client_local import HttpClientLocal
-
-class HttpClientLocalTest(unittest.TestCase):
-
- def testGetWithoutParameters(self):
- code, deps = HttpClientLocal.Get(
- 'https://src.chromium.org/chrome/trunk/src/DEPS')
- self.assertEqual(200, code)
- self.assertTrue(isinstance(deps, str))
diff --git a/chromium/tools/findit/common/utils.py b/chromium/tools/findit/common/utils.py
deleted file mode 100644
index 5011e76e2b1..00000000000
--- a/chromium/tools/findit/common/utils.py
+++ /dev/null
@@ -1,68 +0,0 @@
-# Copyright (c) 2011 The Chromium 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 re
-import sys
-
-from http_client_local import HttpClientLocal
-
-
-GIT_HASH_PATTERN = re.compile(r'^[0-9a-fA-F]{40}$')
-
-
-def GetOSName(platform_name=sys.platform):
- if platform_name == 'cygwin' or platform_name.startswith('win'):
- return 'win'
- elif platform_name.startswith('linux'):
- return 'unix'
- elif platform_name.startswith('darwin'):
- return 'mac'
- else:
- return platform_name
-
-
-def IsGitHash(revision):
- return GIT_HASH_PATTERN.match(str(revision))
-
-
-def GetHttpClient():
- # TODO(stgao): return implementation for appengine when running on appengine.
- return HttpClientLocal
-
-
-def JoinLineNumbers(line_numbers, accepted_gap=1):
- """Join line numbers into line blocks.
-
- Args:
- line_numbers: a list of line number.
- accepted_gap: if two line numbers are within the give gap,
- they would be combined together into a block.
- Eg: for (1, 2, 3, 6, 7, 8, 12), if |accepted_gap| = 1, result
- would be 1-3, 6-8, 12; if |accepted_gap| = 3, result would be
- 1-8, 12; if |accepted_gap| =4, result would be 1-12.
- """
- if not line_numbers:
- return ''
-
- line_numbers = map(int, line_numbers)
- line_numbers.sort()
-
- block = []
- start_line_number = line_numbers[0]
- last_line_number = start_line_number
- for current_line_number in line_numbers[1:]:
- if last_line_number + accepted_gap < current_line_number:
- if start_line_number == last_line_number:
- block.append('%d' % start_line_number)
- else:
- block.append('%d-%d' % (start_line_number, last_line_number))
- start_line_number = current_line_number
- last_line_number = current_line_number
- else:
- if start_line_number == last_line_number:
- block.append('%d' % start_line_number)
- else:
- block.append('%d-%d' % (start_line_number, last_line_number))
-
- return ', '.join(block)
diff --git a/chromium/tools/findit/component_dictionary.py b/chromium/tools/findit/component_dictionary.py
deleted file mode 100644
index d1a8967338e..00000000000
--- a/chromium/tools/findit/component_dictionary.py
+++ /dev/null
@@ -1,122 +0,0 @@
-# Copyright (c) 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.
-
-
-class FileDictionary(object):
- """Maps file in a stacktrace to its crash information.
-
- It maps file to another dictionary, which maps the file's path to crashed
- lines, stack frame indices and crashed functions.
- """
-
- def __init__(self):
- """Initializes the file dictionary."""
- self.file_dict = {}
-
- def AddFile(self, file_path, crashed_line_range, stack_frame_index,
- function):
- """Adds file and its crash information to the map.
-
- Args:
- file_path: The path of the crashed file.
- crashed_line_range: The crashed line of the file.
- stack_frame_index: The file's position in the callstack.
- function: The name of the crashed function.
- """
- # Populate the dictionary if this file path has not been added before.
- if file_path not in self.file_dict:
- self.file_dict[file_path] = {}
- self.file_dict[file_path]['line_numbers'] = []
- self.file_dict[file_path]['stack_frame_indices'] = []
- self.file_dict[file_path]['function'] = []
-
- # Add the crashed line, frame index and function name.
- self.file_dict[file_path]['line_numbers'].append(
- crashed_line_range)
- self.file_dict[file_path]['stack_frame_indices'].append(
- stack_frame_index)
- self.file_dict[file_path]['function'].append(function)
-
- def GetCrashedLineNumbers(self, file_path):
- """Returns crashed line numbers given a file path."""
- return self.file_dict[file_path]['line_numbers']
-
- def GetCrashStackFrameIndices(self, file_path):
- """Returns stack frame indices given a file path."""
- return self.file_dict[file_path]['stack_frame_indices']
-
- def GetCrashFunctions(self, file_path):
- """Returns list of crashed functions given a file path."""
- return self.file_dict[file_path]['function']
-
- def __iter__(self):
- return iter(self.file_dict)
-
-
-class ComponentDictionary(object):
- """Represents a file dictionary.
-
- It maps each component path to a file dictionary.
- """
-
- def __init__(self, callstack, components):
- """Initializes the dictionary with given components."""
- self.component_dict = {}
-
- # Create file dictionary for all the components.
- for component in components:
- self.component_dict[component] = FileDictionary()
-
- # Create file dict from callstack.
- self.__CreateFileDictFromCallstack(callstack)
-
- def GetFileDict(self, component):
- """Returns a file dictionary for a given component."""
- return self.component_dict.get(component)
-
- def __GenerateFileDict(self, stack_frame_list):
- """Generates file dictionary, given an instance of StackFrame list."""
- # Iterate through the list of stackframe objects.
- for stack_frame in stack_frame_list:
- # If the component of this line is not in the list of components to
- # look for, ignore this line.
- component_path = stack_frame.component_path
- if component_path not in self.component_dict:
- continue
-
- # Get values of the variables
- file_path = stack_frame.file_path
- crashed_line_range = stack_frame.crashed_line_range
- stack_frame_index = stack_frame.index
- function = stack_frame.function
-
- # Add the file to this component's dictionary of files.
- file_dict = self.component_dict[component_path]
- file_dict.AddFile(file_path, crashed_line_range, stack_frame_index,
- function)
-
- def __CreateFileDictFromCallstack(self, callstack, top_n_frames=10):
- """Creates a file dict that maps a file to the occurrence in the stack.
-
- Args:
- callstack: A list containing parsed result from a single stack
- within a stacktrace. For example, a stacktrace from
- previously-allocated thread in release build stacktrace.
- top_n_frames: The number of frames to look for.
-
- Returns:
- Component_dict, a dictionary with key as a file name and value as another
- dictionary, which maps the file's path (because there can be multiple
- files with same name but in different directory) to the list of this
- file's place in stack, lines that this file caused a crash, and the name
- of the function.
- """
-
- # Only look at first top_n_frames of the stacktrace, below those are likely
- # to be noisy. Parse the stacktrace into the component dictionary.
- stack_list = callstack.GetTopNFrames(top_n_frames)
- self.__GenerateFileDict(stack_list)
-
- def __iter__(self):
- return iter(self.component_dict)
diff --git a/chromium/tools/findit/config.ini b/chromium/tools/findit/config.ini
deleted file mode 100644
index f6071ecf274..00000000000
--- a/chromium/tools/findit/config.ini
+++ /dev/null
@@ -1,26 +0,0 @@
-[svn:src/]
-changelog_url: http://build.chromium.org/cgi-bin/svn-log?url=http://src.chromium.org/svn/trunk/src/&range=%s
-revision_url: http://src.chromium.org/viewvc/chrome?revision=%d&view=revision
-diff_url: http://src.chromium.org/viewvc/chrome/trunk/%s?r1=%d&r2=%d&pathrev=%d
-blame_url: http://src.chromium.org/viewvc/chrome/trunk/%s?annotate=%s&pathrev=%s
-
-[svn:src/third_party/WebKit/]
-changelog_url: http://build.chromium.org/cgi-bin/svn-log?url=http://src.chromium.org/blink/trunk/&range=%s
-revision_url: http://src.chromium.org/viewvc/blink?revision=%d&view=revision
-diff_url: http://src.chromium.org/viewvc/blink/trunk/%s?r1=%d&r2=%d&pathrev=%d
-blame_url: http://src.chromium.org/viewvc/blink/trunk/%s?annotate=%s&pathrev=%s
-
-[svn:src/third_party/WebKit/Source/]
-changelog_url: http://build.chromium.org/cgi-bin/svn-log?url=http://src.chromium.org/blink/trunk/&range=%s
-revision_url: http://src.chromium.org/viewvc/blink?revision=%d&view=revision
-diff_url: http://src.chromium.org/viewvc/blink/trunk/%s?r1=%d&r2=%d&pathrev=%d
-blame_url: http://src.chromium.org/viewvc/blink/trunk/%s?annotate=%s&pathrev=%s
-
-[git]
-changelog_url: /+log/%s..%s
-revision_url: /+/%s
-diff_url: /+/%s^!/%s
-blame_url: /+blame/%s/%s?format=json
-
-[codereview]
-review_url: https://codereview.chromium.org/api/%s?message=true
diff --git a/chromium/tools/findit/crash_utils.py b/chromium/tools/findit/crash_utils.py
deleted file mode 100644
index 7e8011334e2..00000000000
--- a/chromium/tools/findit/crash_utils.py
+++ /dev/null
@@ -1,570 +0,0 @@
-# Copyright (c) 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.
-
-import atexit
-import cgi
-import ConfigParser
-import json
-import os
-import Queue
-import threading
-import time
-
-from common import utils
-from result import Result
-
-
-INFINITY = float('inf')
-
-MAX_THREAD_NUMBER = 10
-TASK_QUEUE = None
-
-
-def SignalWorkerThreads():
- global TASK_QUEUE
- if not TASK_QUEUE:
- return
-
- for i in range(MAX_THREAD_NUMBER):
- TASK_QUEUE.put(None)
-
- # Give worker threads a chance to exit.
- # Workaround the harmless bug in python 2.7 below.
- time.sleep(1)
-
-
-atexit.register(SignalWorkerThreads)
-
-
-def Worker():
- global TASK_QUEUE
- while True:
- try:
- task = TASK_QUEUE.get()
- if not task:
- return
- except TypeError:
- # According to http://bugs.python.org/issue14623, this is a harmless bug
- # in python 2.7 which won't be fixed.
- # The exception is raised on daemon threads when python interpreter is
- # shutting down.
- return
-
- function, args, kwargs, result_semaphore = task
- try:
- function(*args, **kwargs)
- except:
- pass
- finally:
- # Signal one task is done in case of exception.
- result_semaphore.release()
-
-
-def RunTasks(tasks):
- """Run given tasks. Not thread-safe: no concurrent calls of this function.
-
- Return after all tasks were completed. A task is a dict as below:
- {
- 'function': the function to call,
- 'args': the positional argument to pass to the function,
- 'kwargs': the key-value arguments to pass to the function,
- }
- """
- if not tasks:
- return
-
- global TASK_QUEUE
- if not TASK_QUEUE:
- TASK_QUEUE = Queue.Queue()
- for index in range(MAX_THREAD_NUMBER):
- thread = threading.Thread(target=Worker, name='worker_%s' % index)
- # Set as daemon, so no join is needed.
- thread.daemon = True
- thread.start()
-
- result_semaphore = threading.Semaphore(0)
- # Push task to task queue for execution.
- for task in tasks:
- TASK_QUEUE.put(
- (task['function'], task.get('args', []),
- task.get('kwargs', {}), result_semaphore))
-
- # Wait until all tasks to be executed.
- for _ in tasks:
- result_semaphore.acquire()
-
-
-def GetRepositoryType(revision_number):
- """Returns the repository type of this revision number.
-
- Args:
- revision_number: A revision number or git hash.
-
- Returns:
- 'git' or 'svn', depending on the revision_number.
- """
- if utils.IsGitHash(revision_number):
- return 'git'
- else:
- return 'svn'
-
-
-def ParseURLsFromConfig(file_name):
- """Parses URLS from the config file.
-
- The file should be in python config format, where svn section is in the
- format "svn:component_path".
- Each of the section for svn should contain changelog_url, revision_url,
- diff_url and blame_url.
-
- Args:
- file_name: The name of the file that contains URL information.
-
- Returns:
- A dictionary that maps repository type to list of URLs. For svn, it maps
- key 'svn' to another dictionary, which maps component path to the URLs
- as explained above. For git, it maps to the URLs as explained above.
- """
- config = ConfigParser.ConfigParser()
-
- # Get the absolute path of the config file, and read the file. If it fails,
- # return none.
- config_file_path = os.path.join(os.path.abspath(os.path.dirname(__file__)),
- file_name)
- config.read(config_file_path)
- if not config:
- return None
-
- # Iterate through the config file, check for sections.
- config_dict = {}
- for section in config.sections():
- # These two do not need another layer of dictionary, so add it and go
- # to next section.
- if ':' not in section:
- for option in config.options(section):
- if section not in config_dict:
- config_dict[section] = {}
-
- url = config.get(section, option)
- config_dict[section][option] = url
-
- continue
-
- # Get repository type and component name from the section name.
- repository_type_and_component = section.split(':')
- repository_type = repository_type_and_component[0]
- component_path = repository_type_and_component[1]
-
- # Add 'svn' as the key, if it is not already there.
- if repository_type not in config_dict:
- config_dict[repository_type] = {}
- url_map_for_repository = config_dict[repository_type]
-
- # Add the path to the 'svn', if it is not already there.
- if component_path not in url_map_for_repository:
- url_map_for_repository[component_path] = {}
- type_to_url = url_map_for_repository[component_path]
-
- # Add all URLs to this map.
- for option in config.options(section):
- url = config.get(section, option)
- type_to_url[option] = url
-
- return config_dict
-
-
-def NormalizePath(path, parsed_deps):
- """Normalizes the path.
-
- Args:
- path: A string representing a path.
- parsed_deps: A map from component path to its component name, repository,
- etc.
-
- Returns:
- A tuple containing a component this path is in (e.g blink, skia, etc)
- and a path in that component's repository. Returns None if the component
- repository is not supported, i.e from googlecode.
- """
- # First normalize the path by retreiving the normalized path.
- normalized_path = os.path.normpath(path).replace('\\', '/')
-
- # Iterate through all component paths in the parsed DEPS, in the decreasing
- # order of the length of the file path.
- for component_path in sorted(parsed_deps,
- key=(lambda path: -len(path))):
- # new_component_path is the component path with 'src/' removed.
- new_component_path = component_path
- if new_component_path.startswith('src/') and new_component_path != 'src/':
- new_component_path = new_component_path[len('src/'):]
-
- # We need to consider when the lowercased component path is in the path,
- # because syzyasan build returns lowercased file path.
- lower_component_path = new_component_path.lower()
-
- # If this path is the part of file path, this file must be from this
- # component.
- if new_component_path in normalized_path or \
- lower_component_path in normalized_path:
-
- # Case when the retreived path is in lowercase.
- if lower_component_path in normalized_path:
- current_component_path = lower_component_path
- else:
- current_component_path = new_component_path
-
- # Normalize the path by stripping everything off the component's relative
- # path.
- normalized_path = normalized_path.split(current_component_path, 1)[1]
- lower_normalized_path = normalized_path.lower()
-
- # Add 'src/' or 'Source/' at the front of the normalized path, depending
- # on what prefix the component path uses. For example, blink uses
- # 'Source' but chromium uses 'src/', and blink component path is
- # 'src/third_party/WebKit/Source', so add 'Source/' in front of the
- # normalized path.
- if (lower_component_path == 'src/third_party/webkit/source' and
- not lower_normalized_path.startswith('source/')):
- normalized_path = (current_component_path.split('/')[-2] + '/' +
- normalized_path)
-
- component_name = parsed_deps[component_path]['name']
-
- return (component_path, component_name, normalized_path)
-
- # If the path does not match any component, default to chromium.
- return ('src/', 'chromium', normalized_path)
-
-
-def SplitRange(regression):
- """Splits a range as retrieved from clusterfuzz.
-
- Args:
- regression: A string in format 'r1234:r5678'.
-
- Returns:
- A list containing two numbers represented in string, for example
- ['1234','5678'].
- """
- if not regression:
- return None
-
- revisions = regression.split(':')
-
- # If regression information is not available, return none.
- if len(revisions) != 2:
- return None
-
- range_start = revisions[0]
- range_end = revisions[1]
-
- # Strip 'r' off the range start/end. Not using lstrip to avoid the case when
- # the range is in git hash and it starts with 'r'.
- if range_start.startswith('r'):
- range_start = range_start[1:]
-
- if range_end.startswith('r'):
- range_end = range_end[1:]
-
- return [range_start, range_end]
-
-
-def LoadJSON(json_string):
- """Loads json object from string, or None.
-
- Args:
- json_string: A string to get object from.
-
- Returns:
- JSON object if the string represents a JSON object, None otherwise.
- """
- try:
- data = json.loads(json_string)
- except ValueError:
- data = None
-
- return data
-
-
-def GetDataFromURL(url):
- """Retrieves raw data from URL, tries 10 times.
-
- Args:
- url: URL to get data from.
- retries: Number of times to retry connection.
-
- Returns:
- None if the data retrieval fails, or the raw data.
- """
- status_code, data = utils.GetHttpClient().Get(url, retries=10)
- if status_code == 200:
- return data
- else:
- # Return None if it fails to read data.
- return None
-
-
-def FindMinLineDistance(crashed_line_list, changed_line_numbers,
- line_range=3):
- """Calculates how far the changed line is from one of the crashes.
-
- Finds the minimum distance between the lines that the file crashed on
- and the lines that the file changed. For example, if the file crashed on
- line 200 and the CL changes line 203,204 and 205, the function returns 3.
-
- Args:
- crashed_line_list: A list of lines that the file crashed on.
- changed_line_numbers: A list of lines that the file changed.
- line_range: Number of lines to look back for.
-
- Returns:
- The minimum distance. If either of the input lists is empty,
- it returns inf.
-
- """
- min_distance = INFINITY
- crashed_line = -1
- changed_line = -1
-
- crashed_line_numbers = set()
- for crashed_line_range in crashed_line_list:
- for crashed_line in crashed_line_range:
- for line in range(crashed_line - line_range, crashed_line + 1):
- crashed_line_numbers.add(line)
-
- for line in crashed_line_numbers:
- for distance in changed_line_numbers:
- # Find the current distance and update the min if current distance is
- # less than current min.
- current_distance = abs(line - distance)
- if current_distance < min_distance:
- min_distance = current_distance
- crashed_line = line
- changed_line = distance
-
- return (min_distance, crashed_line, changed_line)
-
-
-def GuessIfSameSubPath(path1, path2):
- """Guesses if two paths represent same path.
-
- Compares the name of the folders in the path (by split('/')), and checks
- if they match either more than 3 or min of path lengths.
-
- Args:
- path1: First path.
- path2: Second path to compare.
-
- Returns:
- True if it they are thought to be a same path, False otherwise.
- """
- path1 = path1.split('/')
- path2 = path2.split('/')
-
- intersection = set(path1).intersection(set(path2))
- return len(intersection) >= (min(3, min(len(path1), len(path2))))
-
-
-def FindMinStackFrameNumber(stack_frame_indices, priorities):
- """Finds the minimum stack number, from the list of stack numbers.
-
- Args:
- stack_frame_indices: A list of lists containing stack position.
- priorities: A list of of priority for each file.
-
- Returns:
- Inf if stack_frame_indices is empty, minimum stack number otherwise.
- """
- # Get the indexes of the highest priority (or low priority number).
- highest_priority = min(priorities)
- highest_priority_indices = []
- for i in range(len(priorities)):
- if priorities[i] == highest_priority:
- highest_priority_indices.append(i)
-
- # Gather the list of stack frame numbers for the files that change the
- # crash lines.
- flattened = []
- for i in highest_priority_indices:
- flattened += stack_frame_indices[i]
-
- # If no stack frame information is available, return inf. Else, return min.
- if not flattened:
- return INFINITY
- else:
- return min(flattened)
-
-
-def AddHyperlink(text, link):
- """Returns a string with HTML link tag.
-
- Args:
- text: A string to add link.
- link: A link to add to the string.
-
- Returns:
- A string with hyperlink added.
- """
- sanitized_link = cgi.escape(link, quote=True)
- sanitized_text = cgi.escape(str(text))
- return '<a href="%s">%s</a>' % (sanitized_link, sanitized_text)
-
-
-def PrettifyList(items):
- """Returns a string representation of a list.
-
- It adds comma in between the elements and removes the brackets.
- Args:
- items: A list to prettify.
- Returns:
- A string representation of the list.
- """
- return ', '.join(map(str, items))
-
-
-def PrettifyFrameInfo(frame_indices, functions):
- """Return a string to represent the frames with functions."""
- frames = []
- for frame_index, function in zip(frame_indices, functions):
- frames.append('frame #%s, "%s"' % (frame_index, function.split('(')[0]))
- return '; '.join(frames)
-
-
-def PrettifyFiles(file_list):
- """Returns a string representation of a list of file names.
-
- Args:
- file_list: A list of tuple, (file_name, file_url).
- Returns:
- A string representation of file names with their urls.
- """
- ret = ['\n']
- for file_name, file_url in file_list:
- ret.append(' %s\n' % AddHyperlink(file_name, file_url))
- return ''.join(ret)
-
-
-def Intersection(crashed_line_list, stack_frame_index, changed_line_numbers,
- function, line_range=3):
- """Finds the overlap betwee changed lines and crashed lines.
-
- Finds the intersection of the lines that caused the crash and
- lines that the file changes. The intersection looks within 3 lines
- of the line that caused the crash.
-
- Args:
- crashed_line_list: A list of lines that the file crashed on.
- stack_frame_index: A list of positions in stack for each of the lines.
- changed_line_numbers: A list of lines that the file changed.
- function: A list of functions that the file crashed on.
- line_range: Number of lines to look backwards from crashed lines.
-
- Returns:
- line_number_intersection: Intersection between crashed_line_list and
- changed_line_numbers.
- stack_frame_index_intersection: Stack number for each of the intersections.
- """
- line_number_intersection = []
- stack_frame_index_intersection = []
- function_intersection = []
-
- # Iterate through the crashed lines, and its occurence in stack.
- for (lines, stack_frame_index, function_name) in zip(
- crashed_line_list, stack_frame_index, function):
- # Also check previous 'line_range' lines. Create a set of all changed lines
- # and lines within 3 lines range before the crashed line.
- line_minus_n = set()
- for line in lines:
- for line_in_range in range(line - line_range, line + 1):
- line_minus_n.add(line_in_range)
-
- for changed_line in changed_line_numbers:
- # If a CL does not change crahsed line, check next line.
- if changed_line not in line_minus_n:
- continue
-
- intersected_line = set()
- # If the changed line is exactly the crashed line, add that line.
- for line in lines:
- if line in changed_line_numbers:
- intersected_line.add(line)
-
- # If the changed line is in 3 lines of the crashed line, add the line.
- else:
- intersected_line.add(changed_line)
-
- # Avoid adding the same line twice.
- if intersected_line not in line_number_intersection:
- line_number_intersection.append(list(intersected_line))
- stack_frame_index_intersection.append(stack_frame_index)
- function_intersection.append(function_name)
- break
-
- return (line_number_intersection, stack_frame_index_intersection,
- function_intersection)
-
-
-def MatchListToResultList(matches):
- """Convert list of matches to the list of result objects.
-
- Args:
- matches: A list of match objects along with its stack priority and revision
- number/git hash
- Returns:
- A list of result object.
-
- """
- result_list = []
-
- for _, cl, match in matches:
- suspected_cl = cl
- revision_url = match.revision_url
- component_name = match.component_name
- author = match.author
- reason = match.reason.strip()
- review_url = match.review_url
- reviewers = match.reviewers
- # For matches, line content do not exist.
- line_content = None
- message = match.message
- time = match.time
-
- result = Result(suspected_cl, revision_url, component_name, author, reason,
- review_url, reviewers, line_content, message, time)
- result_list.append(result)
-
- return result_list
-
-
-def BlameListToResultList(blame_list):
- """Convert blame list to the list of result objects.
-
- Args:
- blame_list: A list of blame objects.
-
- Returns:
- A list of result objects.
- """
- result_list = []
-
- for blame in blame_list:
- suspected_cl = blame.revision
- revision_url = blame.url
- component_name = blame.component_name
- author = blame.author
- reason = (
- 'The CL last changed line %s of file %s, which is stack frame %d.' %
- (blame.line_number, blame.file, blame.stack_frame_index))
- time = blame.time
- # Blame object does not have review url and reviewers.
- review_url = None
- reviewers = None
- line_content = blame.line_content
- message = blame.message
-
- result = Result(suspected_cl, revision_url, component_name, author, reason,
- review_url, reviewers, line_content, message, time)
- result_list.append(result)
-
- return result_list
diff --git a/chromium/tools/findit/deps_config.json b/chromium/tools/findit/deps_config.json
deleted file mode 100644
index 57b41f9b2bf..00000000000
--- a/chromium/tools/findit/deps_config.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
- "cr_rev_url": "https://cr-rev.appspot.com/_ah/api/crrev/v1/redirect/%s",
- "chromium_git_base_url": "https://chromium.googlesource.com/chromium/src/",
- "chromium_git_file_url":
- "https://chromium.googlesource.com/chromium/src/+/%s/%s?format=text",
- "host_directories": [
- "src/chrome/browser/resources/",
- "src/chrome/test/data/layout_tests/",
- "src/media/",
- "src/sdch/",
- "src/testing/",
- "src/third_party/WebKit/",
- "src/third_party/",
- "src/tools/",
- "src/"
- ]
-}
diff --git a/chromium/tools/findit/findit_for_clusterfuzz.py b/chromium/tools/findit/findit_for_clusterfuzz.py
deleted file mode 100644
index c101fbcae36..00000000000
--- a/chromium/tools/findit/findit_for_clusterfuzz.py
+++ /dev/null
@@ -1,224 +0,0 @@
-# Copyright (c) 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.
-
-import chromium_deps
-from common import utils
-import crash_utils
-import findit_for_crash as findit
-import stacktrace
-
-
-def SplitStacktrace(stacktrace_string):
- """Preprocesses stacktrace string into two parts, release and debug.
-
- Args:
- stacktrace_string: A string representation of stacktrace,
- in clusterfuzz format.
-
- Returns:
- A tuple of list of strings, release build stacktrace and
- debug build stacktrace.
- """
- # Make sure we only parse release/debug build stacktrace, and ignore
- # unsymbolised stacktrace.
- in_release_or_debug_stacktrace = False
- release_build_stacktrace_lines = None
- debug_build_stacktrace_lines = None
- current_stacktrace_lines = []
-
- # Iterate through all lines in stacktrace.
- for line in stacktrace_string.splitlines():
- line = line.strip()
-
- # If the line starts with +, it signifies the start of new stacktrace.
- if line.startswith('+-') and line.endswith('-+'):
- if 'Release Build Stacktrace' in line:
- in_release_or_debug_stacktrace = True
- current_stacktrace_lines = []
- release_build_stacktrace_lines = current_stacktrace_lines
-
- elif 'Debug Build Stacktrace' in line:
- in_release_or_debug_stacktrace = True
- current_stacktrace_lines = []
- debug_build_stacktrace_lines = current_stacktrace_lines
-
- # If the stacktrace is neither release/debug build stacktrace, ignore
- # all lines after it until we encounter release/debug build stacktrace.
- else:
- in_release_or_debug_stacktrace = False
-
- # This case, it must be that the line is an actual stack frame, so add to
- # the current stacktrace.
- elif in_release_or_debug_stacktrace:
- current_stacktrace_lines.append(line)
-
- return (release_build_stacktrace_lines, debug_build_stacktrace_lines)
-
-
-def FindCulpritCLs(stacktrace_string,
- build_type,
- chrome_regression=None,
- component_regression=None,
- chrome_crash_revision=None,
- component_crash_revision=None,
- crashing_component_path=None,
- crashing_component_name=None,
- crashing_component_repo_url=None):
- """Returns the result, a list of result.Result objects and message.
-
- If either or both of component_regression and component_crash_revision is not
- None, is is assumed that crashing_component_path and
- crashing_component_repo_url are not None.
-
- Args:
- stacktrace_string: A string representing stacktrace.
- build_type: The type of the job.
- chrome_regression: A string, chrome regression from clusterfuzz, in format
- '123456:123457'
- component_regression: A string, component regression in the same format.
- chrome_crash_revision: A crash revision of chrome, in string.
- component_crash_revision: A crash revision of the component,
- if component build.
- crashing_component_path: A relative path of the crashing component, as in
- DEPS file. For example, it would be 'src/v8' for
- v8 and 'src/third_party/WebKit' for blink.
- crashing_component_name: A name of the crashing component, such as v8.
- crashing_component_repo_url: The URL of the crashing component's repo, as
- shown in DEPS file. For example,
- 'https://chromium.googlesource.com/skia.git'
- for skia.
-
- Returns:
- A list of result objects, along with the short description on where the
- result is from.
- """
- build_type = build_type.lower()
- component_to_crash_revision_dict = {}
- component_to_regression_dict = {}
-
- # If chrome regression is available, parse DEPS file.
- chrome_regression = crash_utils.SplitRange(chrome_regression)
- if chrome_regression:
- chrome_regression_start = chrome_regression[0]
- chrome_regression_end = chrome_regression[1]
-
- # Do not parse regression information for crashes introduced before the
- # first archived build.
- if chrome_regression_start != '0':
- component_to_regression_dict = chromium_deps.GetChromiumComponentRange(
- chrome_regression_start, chrome_regression_end)
- if not component_to_regression_dict:
- return (('Failed to get component regression ranges for chromium '
- 'regression range %s:%s'
- % (chrome_regression_start, chrome_regression_end)), [])
-
- # Parse crash revision.
- if chrome_crash_revision:
- component_to_crash_revision_dict = chromium_deps.GetChromiumComponents(
- chrome_crash_revision)
- if not component_to_crash_revision_dict:
- return (('Failed to get component dependencies for chromium revision "%s"'
- % chrome_crash_revision), [])
-
- # Check if component regression information is available.
- component_regression = crash_utils.SplitRange(component_regression)
- if component_regression:
- component_regression_start = component_regression[0]
- component_regression_end = component_regression[1]
-
- # If this component already has an entry in parsed DEPS file, overwrite
- # regression range and url.
- if crashing_component_path in component_to_regression_dict:
- component_regression_info = \
- component_to_regression_dict[crashing_component_path]
- component_regression_info['old_revision'] = component_regression_start
- component_regression_info['new_revision'] = component_regression_end
- component_regression_info['repository'] = crashing_component_repo_url
-
- # if this component does not have an entry, add the entry to the parsed
- # DEPS file.
- else:
- repository_type = crash_utils.GetRepositoryType(
- component_regression_start)
- component_regression_info = {
- 'path': crashing_component_path,
- 'rolled': True,
- 'name': crashing_component_name,
- 'old_revision': component_regression_start,
- 'new_revision': component_regression_end,
- 'repository': crashing_component_repo_url,
- 'repository_type': repository_type
- }
- component_to_regression_dict[crashing_component_path] = \
- component_regression_info
-
- # If component crash revision is available, add it to the parsed crash
- # revisions.
- if component_crash_revision:
-
- # If this component has already a crash revision info, overwrite it.
- if crashing_component_path in component_to_crash_revision_dict:
- component_crash_revision_info = \
- component_to_crash_revision_dict[crashing_component_path]
- component_crash_revision_info['revision'] = component_crash_revision
- component_crash_revision_info['repository'] = crashing_component_repo_url
-
- # If not, add it to the parsed DEPS.
- else:
- if utils.IsGitHash(component_crash_revision):
- repository_type = 'git'
- else:
- repository_type = 'svn'
- component_crash_revision_info = {
- 'path': crashing_component_path,
- 'name': crashing_component_name,
- 'repository': crashing_component_repo_url,
- 'repository_type': repository_type,
- 'revision': component_crash_revision
- }
- component_to_crash_revision_dict[crashing_component_path] = \
- component_crash_revision_info
-
- # Parsed DEPS is used to normalize the stacktrace. Since parsed regression
- # and parsed crash state essentially contain same information, use either.
- if component_to_regression_dict:
- parsed_deps = component_to_regression_dict
- elif component_to_crash_revision_dict:
- parsed_deps = component_to_crash_revision_dict
- else:
- return (('Identifying culprit CL requires at lease one of regression '
- 'information or crash revision'), [])
-
- # Split stacktrace into release build/debug build and parse them.
- (release_build_stacktrace, debug_build_stacktrace) = SplitStacktrace(
- stacktrace_string)
- if not (release_build_stacktrace or debug_build_stacktrace):
- parsed_release_build_stacktrace = stacktrace.Stacktrace(
- stacktrace_string.splitlines(), build_type, parsed_deps)
- else:
- parsed_release_build_stacktrace = stacktrace.Stacktrace(
- release_build_stacktrace, build_type, parsed_deps)
-
- parsed_debug_build_stacktrace = stacktrace.Stacktrace(
- debug_build_stacktrace, build_type, parsed_deps)
-
- # Get a highest priority callstack (main_stack) from stacktrace, with release
- # build stacktrace in higher priority than debug build stacktace. This stack
- # is the callstack to find blame information for.
- if parsed_release_build_stacktrace.stack_list:
- main_stack = parsed_release_build_stacktrace.GetCrashStack()
- elif parsed_debug_build_stacktrace.stack_list:
- main_stack = parsed_debug_build_stacktrace.GetCrashStack()
- else:
- if 'mac_' in build_type:
- return ('No line information available in stacktrace.', [])
-
- return ('Findit failed to find any stack trace. Is it in a new format?', [])
-
- # Run the algorithm on the parsed stacktrace, and return the result.
- stacktrace_list = [parsed_release_build_stacktrace,
- parsed_debug_build_stacktrace]
- return findit.FindItForCrash(
- stacktrace_list, main_stack, component_to_regression_dict,
- component_to_crash_revision_dict)
diff --git a/chromium/tools/findit/findit_for_crash.py b/chromium/tools/findit/findit_for_crash.py
deleted file mode 100644
index 689294987ca..00000000000
--- a/chromium/tools/findit/findit_for_crash.py
+++ /dev/null
@@ -1,664 +0,0 @@
-# Copyright (c) 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.
-
-import os
-from threading import Lock
-
-import blame
-from common import utils
-import component_dictionary
-import crash_utils
-import git_repository_parser
-import match_set
-import svn_repository_parser
-
-
-LINE_CHANGE_PRIORITY = 1
-FILE_CHANGE_PRIORITY = 2
-_THIS_DIR = os.path.abspath(os.path.dirname(__file__))
-CONFIG = crash_utils.ParseURLsFromConfig(os.path.join(_THIS_DIR,
- 'config.ini'))
-
-
-def GenerateMatchEntry(
- matches, revision_info, revision_number, file_path, function,
- component_path, component_name, crashed_line_numbers, stack_frame_indices,
- file_change_type, repository_parser):
- """Generates a match object and adds it to the match set.
-
- Args:
- matches: A matchset object, a map from CL to a match object.
- revision_info: The revision information, a map from fields (message,
- changed files, etc) to its values.
- revision_number: The SVN revision number or git hash.
- file_path: The path of the file.
- function: The function that caused an crash.
- component_path: The path of the component this file is from.
- component_name: The name of the component the file is from.
- crashed_line_numbers: The list of the lines in the file that caused
- the crash.
- stack_frame_indices: The list of positions of this file within a stack.
- file_change_type: Whether file is modified, added or deleted.
- repository_parser: The parser object to parse line diff.
- """
- # Check if this CL should be ignored.
- with matches.matches_lock:
- if revision_number in matches.cls_to_ignore:
- return
-
- # If this CL is not already identified as suspected, create a new entry.
- if revision_number not in matches.matches:
- match = match_set.Match(revision_info, component_name)
- message = revision_info['message']
- # TODO(jeun): Don't hold lock while issuing http request.
- match.ParseMessage(message, matches.codereview_api_url)
-
- # If this match is a revert, add to the set of CLs to be ignored.
- if match.is_revert:
- matches.cls_to_ignore.add(revision_number)
-
- # If this match has info on what CL it is reverted from, add that CL.
- if match.revert_of:
- matches.cls_to_ignore.add(match.revert_of)
-
- return
-
- matches.matches[revision_number] = match
-
- else:
- match = matches.matches[revision_number]
-
- (diff_url, changed_line_numbers, changed_line_contents) = (
- repository_parser.ParseLineDiff(
- file_path, component_path, file_change_type, revision_number))
-
- # Ignore this match if the component is not supported for svn.
- if not diff_url:
- return
-
- # Find the intersection between the lines that this file crashed on and
- # the changed lines.
- (line_number_intersection, stack_frame_index_intersection, functions) = (
- crash_utils.Intersection(
- crashed_line_numbers, stack_frame_indices, changed_line_numbers,
- function))
-
- # Find the minimum distance between the changed lines and crashed lines.
- (min_distance, min_crashed_line, min_changed_line) = \
- crash_utils.FindMinLineDistance(crashed_line_numbers,
- changed_line_numbers)
-
- # Check whether this CL changes the crashed lines or not.
- if line_number_intersection:
- priority = LINE_CHANGE_PRIORITY
- else:
- priority = FILE_CHANGE_PRIORITY
-
- # Add the parsed information to the object.
- with matches.matches_lock:
- match.crashed_line_numbers.append(line_number_intersection)
-
- file_name = file_path.split('/')[-1]
- match.changed_files.append(file_name)
-
- # Update the min distance only if it is less than the current one.
- if min_distance < match.min_distance:
- match.min_distance = min_distance
- match.min_distance_info = (file_name, min_crashed_line, min_changed_line)
-
- # If this CL does not change the crashed line, all occurrence of this
- # file in the stack has the same priority.
- if not stack_frame_index_intersection:
- stack_frame_index_intersection = stack_frame_indices
- functions = function
- match.stack_frame_indices.append(stack_frame_index_intersection)
- match.changed_file_urls.append(diff_url)
- match.priorities.append(priority)
- match.function_list.append(functions)
-
-
-def FindMatch(revisions_info_map, file_to_revision_info, file_to_crash_info,
- component_path, component_name, repository_parser,
- codereview_api_url):
- """Finds a CL that modifies file in the stacktrace.
-
- Args:
- revisions_info_map: A dictionary mapping revision number to the CL
- information.
- file_to_revision_info: A dictionary mapping file to the revision that
- modifies it.
- file_to_crash_info: A dictionary mapping file to its occurrence in
- stacktrace.
- component_path: The path of the component to search for.
- component_name: The name of the component to search for.
- repository_parser: The parser object to parse the line diff.
- codereview_api_url: A code review url to retrieve data from.
-
- Returns:
- Matches, a set of match objects.
- """
- matches = match_set.MatchSet(codereview_api_url)
-
- tasks = []
- # Iterate through the crashed files in the stacktrace.
- for crashed_file_path in file_to_crash_info:
- # Ignore header file.
- if crashed_file_path.endswith('.h'):
- continue
-
- # If the file in the stacktrace is not changed in any commits, continue.
- for changed_file_path in file_to_revision_info:
- changed_file_name = changed_file_path.split('/')[-1].lower()
- crashed_file_name = crashed_file_path.split('/')[-1].lower()
- if changed_file_name != crashed_file_name:
- continue
-
- if not crash_utils.GuessIfSameSubPath(
- changed_file_path.lower(), crashed_file_path.lower()):
- continue
-
- crashed_line_numbers = file_to_crash_info.GetCrashedLineNumbers(
- crashed_file_path)
- stack_frame_nums = file_to_crash_info.GetCrashStackFrameIndices(
- crashed_file_path)
- functions = file_to_crash_info.GetCrashFunctions(crashed_file_path)
-
- # Iterate through the CLs that this file path is changed.
- for (cl, file_change_type) in file_to_revision_info[changed_file_path]:
- # If the file change is delete, ignore this CL.
- if file_change_type == 'D':
- continue
-
- revision = revisions_info_map[cl]
-
- tasks.append({
- 'function': GenerateMatchEntry,
- 'args':[matches, revision, cl, changed_file_path, functions,
- component_path, component_name, crashed_line_numbers,
- stack_frame_nums, file_change_type,
- repository_parser]})
-
- # Run all the tasks.
- crash_utils.RunTasks(tasks)
-
- matches.RemoveRevertedCLs()
-
- return matches
-
-
-def FindMatchForComponent(component_path, file_to_crash_info, changelog,
- callstack_priority, results, results_lock):
- """Parses changelog and finds suspected CLs for a given component.
-
- Args:
- component_path: The path of component to look for the culprit CL.
- file_to_crash_info: A dictionary mapping file to its occurrence in
- stackframe.
- changelog: The parsed changelog for this component.
- callstack_priority: The priority of this call stack, 0 if from crash stack,
- 1 if from freed, 2 if from previously allocated.
- results: A dictionary to store the result.
- results_lock: A lock that guards results.
- """
- (repository_parser, component_name, revisions, file_to_revision_map) = \
- changelog
-
- # Find match for this component.
- codereview_api_url = CONFIG['codereview']['review_url']
- component_result = FindMatch(
- revisions, file_to_revision_map, file_to_crash_info, component_path,
- component_name, repository_parser, codereview_api_url)
- matches = component_result.matches
-
- # For all the match results in a dictionary, add to the list so that it
- # can be sorted.
- with results_lock:
- for cl in matches:
- match = matches[cl]
- results.append((callstack_priority, cl, match))
-
-
-def FindMatchForCallstack(
- callstack, components, component_to_changelog_map, results,
- results_lock):
- """Finds culprit cl for a stack within a stacktrace.
-
- For each components to look for, create new thread that computes the matches
- and join the results at the end.
-
- Args:
- callstack: A callstack in a stacktrace to find the result for.
- components: A set of components to look for.
- component_to_changelog_map: A map from component to its parsed changelog.
- results: A list to aggregrate results from all stacktraces.
- results_lock: A lock that guards results.
- """
- # Create component dictionary from the component and call stack.
- component_dict = component_dictionary.ComponentDictionary(callstack,
- components)
- callstack_priority = callstack.priority
-
- # Iterate through all components.
- for component_path in component_dict:
- # If the component to consider in this callstack is not in the parsed list
- # of components, ignore this one.
- if component_path not in component_to_changelog_map:
- continue
-
- changelog = component_to_changelog_map[component_path]
- file_to_crash_info = component_dict.GetFileDict(component_path)
- FindMatchForComponent(component_path, file_to_crash_info, changelog,
- callstack_priority, results, results_lock)
-
-
-def FindMatchForStacktrace(stacktrace, components,
- component_to_regression_dict):
- """Finds the culprit CL for stacktrace.
-
- The passed stacktrace is either from release build stacktrace
- or debug build stacktrace.
-
- Args:
- stacktrace: A list of parsed stacks within a stacktrace.
- components: A set of components to look for.
- component_to_regression_dict: A dictionary mapping component path to
- its regression.
-
- Returns:
- A list of match results from all stacks.
- """
- # A list to aggregate results from all the callstacks in the stacktrace.
- results = []
- results_lock = Lock()
-
- # Setup parsers.
- svn_parser = svn_repository_parser.SVNParser(CONFIG['svn'])
- git_parser = git_repository_parser.GitParser(component_to_regression_dict,
- CONFIG['git'])
-
- # Create a cache of parsed revisions.
- component_to_changelog_map = {}
- for component_path in components:
- component_object = component_to_regression_dict[component_path]
- range_start = component_object['old_revision']
- range_end = component_object['new_revision']
-
- # If range start is 0, the range is too large and the crash has been
- # introduced the archived build, so ignore this case.
- if range_start == '0':
- continue
-
- component_name = component_to_regression_dict[component_path]['name']
-
- is_git = utils.IsGitHash(range_start)
- if is_git:
- repository_parser = git_parser
- else:
- repository_parser = svn_parser
-
- (revisions, file_to_revision_map) = repository_parser.ParseChangelog(
- component_path, range_start, range_end)
-
- # If the returned map from ParseChangeLog is empty, we don't need to look
- # further because either the parsing failed or the changelog is empty.
- if not (revisions and file_to_revision_map):
- continue
-
- component_to_changelog_map[component_path] = (repository_parser,
- component_name,
- revisions,
- file_to_revision_map)
-
- # Analyze each of the call stacks in the stacktrace.
- for callstack in stacktrace.stack_list:
- FindMatchForCallstack(callstack, components, component_to_changelog_map,
- results, results_lock)
-
- return results
-
-
-def SortMatchesFunction(match_with_stack_priority):
- """A function to sort the match triple.
-
- Currently, it sorts the list by:
- 1) The highest priority file change in the CL (changing crashed line is
- higher priority than just changing the file).
- 2) The callstack this match is computed (crash stack, freed, allocation).
- 3) The minimum stack frame number of the changed file in the match.
- 4) The number of files this CL changes (higher the better).
- 5) The minimum distance between the lines that the CL changes and crashed
- lines.
-
- Args:
- match_with_stack_priority: A match object, with the CL it is from and what
- callstack it is from.
-
- Returns:
- A sort key.
- """
- (stack_priority, _, match) = match_with_stack_priority
-
- return (min(match.priorities),
- stack_priority,
- match.min_distance,
- crash_utils.FindMinStackFrameNumber(match.stack_frame_indices,
- match.priorities),
- -len(match.changed_files))
-
-
-def SortAndFilterMatches(matches, num_important_frames=5):
- """Filters the list of potential culprit CLs to remove noise.
-
- Args:
- matches: A list containing match results.
- num_important_frames: A number of frames on the top of the frame to Check
- for when filtering the results. A match with a file
- that is in top num_important_frames of the stacktrace
- is regarded more probable then others.
-
- Returns:
- Filtered match results.
- """
- new_matches = []
- line_changed = False
- is_important_frame = False
- highest_priority_stack = crash_utils.INFINITY
- matches.sort(key=SortMatchesFunction)
- # Iterate through the matches to find out what results are significant.
- for stack_priority, cl, match in matches:
- # Check if the current match changes crashed line.
- is_line_change = (min(match.priorities) == LINE_CHANGE_PRIORITY)
-
- # Check which stack this match is from, and finds the highest priority
- # callstack up to this point.
- current_stack = stack_priority
- if current_stack < highest_priority_stack:
- highest_priority_stack = current_stack
-
- # Check if current match changes a file that occurs in crash state.
- flattened_stack_frame_indices = [frame for frame_indices in
- match.stack_frame_indices
- for frame in frame_indices]
- current_is_important = (
- min(flattened_stack_frame_indices) < num_important_frames)
-
- # This match and anything lower than this should be ignored if:
- # - Current match does not change crashed lines but there are matches
- # that do so.
- # - Current match is not in crash state but there are matches in it.
- # - There are other matches that came from higher priority stack.
- if (line_changed and not is_line_change) or (
- is_important_frame and not current_is_important) or (
- current_stack > highest_priority_stack):
- break
-
- # Update the variables.
- if is_line_change:
- line_changed = True
- if current_is_important:
- is_important_frame = True
-
- # Add current match to the filtered result.
- new_matches.append((stack_priority, cl, match))
-
- return new_matches
-
-
-def GenerateReasonForMatches(matches):
- """Generates a reason that a match (CL) is a culprit cl.
-
- Args:
- matches: A list of match objects.
- """
- # Iterate through the matches in the list.
- for i, _, match in matches:
- reason = []
-
- # Zip the files in the match by the reason they are suspected
- # (how the file is modified).
- match_by_priority = zip(
- match.priorities, match.crashed_line_numbers, match.changed_files,
- match.stack_frame_indices, match.function_list)
-
- # Sort the zipped changed files in the match by their priority so that the
- # changed lines comes first in the reason.
- match_by_priority.sort(
- key=lambda (priority, crashed_line_numbers, file_name,
- stack_frame_indices, function_list): priority)
-
- # Iterate through the sorted match.
- for i in range(len(match_by_priority)):
- (priority, crashed_line_numbers, file_name, stack_frame_indices,
- function_list) = match_by_priority[i]
-
- # If the file in the match is a line change, append a explanation.
- if priority == LINE_CHANGE_PRIORITY:
- crashed_line_numbers = [crashed_line_number
- for lines in crashed_line_numbers
- for crashed_line_number in lines]
- reason.append(
- 'Lines %s of file %s which potentially caused crash '
- 'are changed in this cl (%s).\n' %
- (utils.JoinLineNumbers(crashed_line_numbers, accepted_gap=4),
- file_name,
- crash_utils.PrettifyFrameInfo(stack_frame_indices, function_list)))
-
- else:
- # Get all the files that are not line change.
- rest_of_the_files = match_by_priority[i:]
-
- if len(rest_of_the_files) == 1:
- file_string = 'File %s is changed in this cl '
- else:
- file_string = 'Files %s are changed in this cl '
-
- # Create a list of file names, and prettify the list.
- file_names = [
- file_name for (_, _, file_name, _, _) in rest_of_the_files]
- pretty_file_names = crash_utils.PrettifyList(file_names)
-
- # Add the reason, break because we took care of the rest of the files.
- file_string += ('(and is part of stack %s)' %
- crash_utils.PrettifyFrameInfo(stack_frame_indices, function_list))
- reason.append(file_string % pretty_file_names)
- break
-
- # Set the reason as string.
- match.reason = '\n'.join(reason)
-
-
-def CombineMatches(matches):
- """Combine possible duplicates in matches.
-
- Args:
- matches: A list of matches object, along with its callstack priority and
- CL it is from.
- Returns:
- A combined list of matches.
- """
- combined_matches = []
-
- for stack_index, cl, match in matches:
- found_match = None
-
- # Iterate through the list of combined matches.
- for _, cl_combined, match_combined in combined_matches:
- # Check for if current CL is already higher up in the result.
- if cl == cl_combined:
- found_match = match_combined
- break
-
- # If current match is not already in, add it to the list of matches.
- if not found_match:
- combined_matches.append((stack_index, cl, match))
- continue
-
- # Combine the reason if the current match is already in there.
- found_match.reason += '\n' + match.reason
- if match.min_distance < found_match.min_distance:
- found_match.min_distance = match.min_distance
- found_match.min_distance_info = match.min_distance_info
-
- for stack_index, cl, match in combined_matches:
- if match.min_distance_info:
- file_name, min_crashed_line, min_changed_line = match.min_distance_info
- match.reason = match.reason.strip()
- match.reason += (
- '\nMinimum distance from crash line to modified line: %d. '
- '(file: %s, crashed on: %d, modified: %d).' %
- (match.min_distance, file_name, min_crashed_line, min_changed_line))
-
- return combined_matches
-
-
-def FilterAndGenerateReasonForMatches(result):
- """A wrapper function.
-
- It generates reasons for the matches and returns string representation
- of filtered results.
-
- Args:
- result: A list of match objects.
-
- Returns:
- A string representation of filtered results.
- """
- new_result = SortAndFilterMatches(result)
- GenerateReasonForMatches(new_result)
- combined_matches = CombineMatches(new_result)
- return crash_utils.MatchListToResultList(combined_matches)
-
-
-def ParseCrashComponents(main_stack):
- """Parses the crashing component.
-
- Crashing components is a component that top_n_frames of the stacktrace is
- from.
-
- Args:
- main_stack: Main stack from the stacktrace.
-
- Returns:
- A set of components.
- """
- components = set()
-
- for frame in main_stack.frame_list:
- components.add(frame.component_path)
-
- return components
-
-
-def GenerateAndFilterBlameList(callstack, component_to_crash_revision_dict,
- component_to_regression_dict):
- """A wrapper function.
-
- Finds blame information for stack and returns string representation.
-
- Args:
- callstack: A callstack to find the blame information.
- component_to_crash_revision_dict: A dictionary mapping component to its
- crash revision.
- component_to_regression_dict: A dictionary mapping component to its
- regression.
-
- Returns:
- A list of blame results.
- """
- if component_to_regression_dict:
- parsed_deps = component_to_regression_dict
- else:
- parsed_deps = component_to_crash_revision_dict
-
- # Setup parser objects to use for parsing blame information.
- svn_parser = svn_repository_parser.SVNParser(CONFIG['svn'])
- git_parser = git_repository_parser.GitParser(parsed_deps, CONFIG['git'])
- parsers = {}
- parsers['svn'] = svn_parser
- parsers['git'] = git_parser
-
- # Create and generate the blame objects from the callstack.
- blame_list = blame.BlameList()
- blame_list.FindBlame(callstack, component_to_crash_revision_dict,
- component_to_regression_dict,
- parsers)
-
- blame_list.FilterAndSortBlameList()
- return crash_utils.BlameListToResultList(blame_list)
-
-
-def FindItForCrash(stacktrace_list,
- callstack,
- component_to_regression_dict,
- component_to_crash_revision_dict):
- """Finds the culprit CL from the list of stacktrace.
-
- Args:
- stacktrace_list: A list of stacktraces to look for, in the order of
- decreasing significance.
- callstack: A callstack object to show blame information for, if there are
- no results for all stacktraces in the stacktrace_list.
- component_to_regression_dict: A parsed regression information as a
- result of parsing DEPS file.
- component_to_crash_revision_dict: A parsed crash revision information.
-
- Returns:
- A list of result objects, with the message how the result is created.
- """
- # If regression information is not available, return blame information.
- if not component_to_regression_dict:
- result = GenerateAndFilterBlameList(callstack,
- component_to_crash_revision_dict,
- component_to_regression_dict)
- if result:
- return_message = (
- 'Regression information is not available. The result is '
- 'the blame information.')
- else:
- return_message = ('Findit could not find any suspected CLs.')
-
- return (return_message, result)
-
- for stacktrace in stacktrace_list:
- # Check the next stacktrace if current one is empty.
- if not stacktrace.stack_list:
- continue
-
- # Get the crash stack for this stacktrace, and extract crashing components
- # from it.
- main_stack = stacktrace.GetCrashStack()
- components = ParseCrashComponents(main_stack)
-
- result_for_stacktrace = FindMatchForStacktrace(
- stacktrace, components, component_to_regression_dict)
- filtered_result = FilterAndGenerateReasonForMatches(result_for_stacktrace)
-
- # If the result is empty, check the next stacktrace. Else, return the
- # filtered result.
- if not filtered_result:
- continue
-
- return_message = (
- 'The result is a list of CLs that change the crashed files.')
- return (return_message, filtered_result)
-
- # If no match is found, return the blame information for the input
- # callstack.
- result = GenerateAndFilterBlameList(
- callstack, component_to_crash_revision_dict,
- component_to_regression_dict)
-
- if result:
- return_message = (
- 'No CL in the regression range changes the crashed files. '
- 'The result is the blame information.')
-
- # When findit could not find any CL that changes file in stacktrace or if
- # if cannot get any blame information, return a message saying that no
- # results are available.
- else:
- return_message = ('Findit could not find any suspected CLs.')
-
- return (return_message, result)
-
diff --git a/chromium/tools/findit/git_repository_parser.py b/chromium/tools/findit/git_repository_parser.py
deleted file mode 100644
index 765da99b667..00000000000
--- a/chromium/tools/findit/git_repository_parser.py
+++ /dev/null
@@ -1,293 +0,0 @@
-# Copyright (c) 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.
-
-import base64
-import xml.dom.minidom as minidom
-from xml.parsers.expat import ExpatError
-
-import crash_utils
-from repository_parser_interface import ParserInterface
-
-FILE_CHANGE_TYPE_MAP = {
- 'add': 'A',
- 'copy': 'C',
- 'delete': 'D',
- 'modify': 'M',
- 'rename': 'R'
-}
-
-
-def _ConvertToFileChangeType(file_action):
- # TODO(stgao): verify impact on code that checks the file change type.
- return file_action[0].upper()
-
-
-class GitParser(ParserInterface):
- """Parser for Git repository in googlesource.
-
- Attributes:
- parsed_deps: A map from component path to its repository name, regression,
- etc.
- url_parts_map: A map from url type to its url parts. This parts are added
- the base url to form different urls.
- """
-
- def __init__(self, parsed_deps, url_parts_map):
- self.component_to_url_map = parsed_deps
- self.url_parts_map = url_parts_map
-
- def ParseChangelog(self, component_path, range_start, range_end):
- file_to_revision_map = {}
- revision_map = {}
- base_url = self.component_to_url_map[component_path]['repository']
- changelog_url = base_url + self.url_parts_map['changelog_url']
- revision_url = base_url + self.url_parts_map['revision_url']
-
- # Retrieve data from the url, return empty maps if fails. Html url is a\
- # url where the changelog can be parsed from html.
- url = changelog_url % (range_start, range_end)
- html_url = url + '?pretty=fuller'
- response = crash_utils.GetDataFromURL(html_url)
- if not response:
- return (revision_map, file_to_revision_map)
-
- # Parse xml out of the returned string. If it failes, Try parsing
- # from JSON objects.
- try:
- dom = minidom.parseString(response)
- except ExpatError:
- self.ParseChangelogFromJSON(range_start, range_end, changelog_url,
- revision_url, revision_map,
- file_to_revision_map)
- return (revision_map, file_to_revision_map)
-
- # The revisions information are in from the third divs to the second
- # to last one.
- divs = dom.getElementsByTagName('div')[2:-1]
- pres = dom.getElementsByTagName('pre')
- uls = dom.getElementsByTagName('ul')
-
- # Divs, pres and uls each contain revision information for one CL, so
- # they should have same length.
- if not divs or len(divs) != len(pres) or len(pres) != len(uls):
- self.ParseChangelogFromJSON(range_start, range_end, changelog_url,
- revision_url, revision_map,
- file_to_revision_map)
- return (revision_map, file_to_revision_map)
-
- # Iterate through divs and parse revisions
- for (div, pre, ul) in zip(divs, pres, uls):
- # Create new revision object for each revision.
- revision = {}
-
- # There must be three <tr>s. If not, this page is wrong.
- trs = div.getElementsByTagName('tr')
- if len(trs) != 3:
- continue
-
- # Retrieve git hash.
- githash = trs[0].getElementsByTagName('a')[0].firstChild.nodeValue
-
- # Retrieve and set author.
- author = trs[1].getElementsByTagName(
- 'td')[0].firstChild.nodeValue.split('<')[0]
- revision['author'] = author
- revision['time'] = trs[1].getElementsByTagName(
- 'td')[1].firstChild.nodeValue
-
- # Retrive and set message.
- revision['message'] = pre.firstChild.nodeValue
-
- # Set url of this CL.
- revision_url_part = self.url_parts_map['revision_url'] % githash
- revision['url'] = base_url + revision_url_part
-
- # Go through changed files, they are in li.
- lis = ul.getElementsByTagName('li')
- for li in lis:
- # Retrieve path and action of the changed file
- file_path = li.getElementsByTagName('a')[0].firstChild.nodeValue
- file_change_type = li.getElementsByTagName('span')[
- 0].getAttribute('class')
-
- # Normalize file action so that it is same as SVN parser.
- file_change_type = _ConvertToFileChangeType(file_change_type)
-
- # Add the changed file to the map.
- if file_path not in file_to_revision_map:
- file_to_revision_map[file_path] = []
- file_to_revision_map[file_path].append((githash, file_change_type))
-
- # Add this revision object to the map.
- revision_map[githash] = revision
-
- # Parse one revision for the start range, because googlesource does not
- # include the start of the range.
- self.ParseRevision(revision_url, range_start, revision_map,
- file_to_revision_map)
-
- return (revision_map, file_to_revision_map)
-
- def ParseChangelogFromJSON(self, range_start, range_end, changelog_url,
- revision_url, revision_map, file_to_revision_map):
- """Parses changelog by going over the JSON file.
-
- Args:
- range_start: Starting range of the regression.
- range_end: Ending range of the regression.
- changelog_url: The url to retrieve changelog from.
- revision_url: The url to retrieve individual revision from.
- revision_map: A map from a git hash number to its revision information.
- file_to_revision_map: A map from file to a git hash in which it occurs.
- """
- # Compute URLs from given range, and retrieves changelog. Stop if it fails.
- changelog_url %= (range_start, range_end)
- json_url = changelog_url + '?format=json'
- response = crash_utils.GetDataFromURL(json_url)
- if not response:
- return
-
- # Parse changelog from the returned object. The returned string should
- # start with ")}]'\n", so start from the 6th character.
- revisions = crash_utils.LoadJSON(response[5:])
- if not revisions:
- return
-
- # Parse individual revision in the log.
- for revision in revisions['log']:
- githash = revision['commit']
- self.ParseRevision(revision_url, githash, revision_map,
- file_to_revision_map)
-
- # Parse the revision with range_start, because googlesource ignores
- # that one.
- self.ParseRevision(revision_url, range_start, revision_map,
- file_to_revision_map)
-
- def ParseRevision(self, revision_url, githash, revision_map,
- file_to_revision_map):
-
- # Retrieve data from the URL, return if it fails.
- url = revision_url % githash
- response = crash_utils.GetDataFromURL(url + '?format=json')
- if not response:
- return
-
- # Load JSON object from the string. If it fails, terminate the function.
- json_revision = crash_utils.LoadJSON(response[5:])
- if not json_revision:
- return
-
- # Create a map representing object and get githash from the JSON object.
- revision = {}
- githash = json_revision['commit']
-
- # Set author, message and URL of this CL.
- revision['author'] = json_revision['author']['name']
- revision['time'] = json_revision['author']['time']
- revision['message'] = json_revision['message']
- revision['url'] = url
-
- # Iterate through the changed files.
- for diff in json_revision['tree_diff']:
- file_path = diff['new_path']
- file_change_type = diff['type']
-
- # Normalize file action so that it fits with svn_repository_parser.
- file_change_type = _ConvertToFileChangeType(file_change_type)
-
- # Add the file to the map.
- if file_path not in file_to_revision_map:
- file_to_revision_map[file_path] = []
- file_to_revision_map[file_path].append((githash, file_change_type))
-
- # Add this CL to the map.
- revision_map[githash] = revision
-
- return
-
- def ParseLineDiff(self, path, component, file_change_type, githash):
- changed_line_numbers = []
- changed_line_contents = []
- base_url = self.component_to_url_map[component]['repository']
- backup_url = (base_url + self.url_parts_map['revision_url']) % githash
-
- # If the file is added (not modified), treat it as if it is not changed.
- if file_change_type in ('A', 'C', 'R'):
- # TODO(stgao): Maybe return whole file change for Add, Rename, and Copy?
- return (backup_url, changed_line_numbers, changed_line_contents)
-
- # Retrieves the diff data from URL, and if it fails, return emptry lines.
- url = (base_url + self.url_parts_map['diff_url']) % (githash, path)
- data = crash_utils.GetDataFromURL(url + '?format=text')
- if not data:
- return (backup_url, changed_line_numbers, changed_line_contents)
-
- # Decode the returned object to line diff info
- diff = base64.b64decode(data).splitlines()
-
- # Iterate through the lines in diff. Set current line to -1 so that we know
- # that current line is part of the diff chunk.
- current_line = -1
- for line in diff:
- line = line.strip()
-
- # If line starts with @@, a new chunk starts.
- if line.startswith('@@'):
- current_line = int(line.split('+')[1].split(',')[0])
-
- # If we are in a chunk.
- elif current_line != -1:
- # If line is either added or modified.
- if line.startswith('+'):
- changed_line_numbers.append(current_line)
- changed_line_contents.append(line[2:])
-
- # Do not increment current line if the change is 'delete'.
- if not line.startswith('-'):
- current_line += 1
-
- # Return url without '?format=json'
- return (url, changed_line_numbers, changed_line_contents)
-
- def ParseBlameInfo(self, component, file_path, line, revision):
- base_url = self.component_to_url_map[component]['repository']
-
- # Retrieve blame JSON file from googlesource. If it fails, return None.
- url_part = self.url_parts_map['blame_url'] % (revision, file_path)
- blame_url = base_url + url_part
- json_string = crash_utils.GetDataFromURL(blame_url)
- if not json_string:
- return
-
- # Parse JSON object from the string. The returned string should
- # start with ")}]'\n", so start from the 6th character.
- annotation = crash_utils.LoadJSON(json_string[5:])
- if not annotation:
- return
-
- # Go through the regions, which is a list of consecutive lines with same
- # author/revision.
- for blame_line in annotation['regions']:
- start = blame_line['start']
- count = blame_line['count']
-
- # For each region, check if the line we want the blame info of is in this
- # region.
- if start <= line and line <= start + count - 1:
- # If we are in the right region, get the information from the line.
- revision = blame_line['commit']
- author = blame_line['author']['name']
- revision_url_parts = self.url_parts_map['revision_url'] % revision
- revision_url = base_url + revision_url_parts
- # TODO(jeun): Add a way to get content from JSON object.
- content = None
-
- (revision_info, _) = self.ParseChangelog(component, revision, revision)
- message = revision_info[revision]['message']
- time = revision_info[revision]['time']
- return (content, revision, author, revision_url, message, time)
-
- # Return none if the region does not exist.
- return None
diff --git a/chromium/tools/findit/match_set.py b/chromium/tools/findit/match_set.py
deleted file mode 100644
index 52114b8c2bb..00000000000
--- a/chromium/tools/findit/match_set.py
+++ /dev/null
@@ -1,128 +0,0 @@
-# Copyright (c) 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.
-
-import re
-
-from threading import Lock
-
-import crash_utils
-
-
-REVIEW_URL_PATTERN = re.compile(r'Review URL:( *)(.*?)/(\d+)')
-
-
-class Match(object):
- """Represents a match entry.
-
- A match is a CL that is suspected to have caused the crash. A match object
- contains information about files it changes, their authors, etc.
-
- Attributes:
- is_revert: True if this CL is reverted by other CL.
- revert_of: If this CL is a revert of some other CL, a revision number/
- git hash of that CL.
- crashed_line_numbers: The list of lines that caused crash for this CL.
- function_list: The list of functions that caused the crash.
- min_distance: The minimum distance between the lines that CL changed and
- lines that caused the crash.
- changed_files: The list of files that the CL changed.
- changed_file_urls: The list of URLs for the file.
- author: The author of the CL.
- component_name: The name of the component that this CL belongs to.
- stack_frame_indices: For files that caused crash, list of where in the
- stackframe they occur.
- priorities: A list of priorities for each of the changed file. A priority
- is 1 if the file changes a crashed line, and 2 if it changes
- the file but not the crashed line.
- reivision_url: The revision URL of the CL.
- review_url: The codereview URL that reviews this CL.
- reviewers: The list of people that reviewed this CL.
- reason: The reason why this CL is suspected.
- time: When this CL was committed.
- """
- REVERT_PATTERN = re.compile(r'(revert\w*) r?(\d+)', re.I)
-
- def __init__(self, revision, component_name):
- self.is_revert = False
- self.revert_of = None
- self.message = None
- self.crashed_line_numbers = []
- self.function_list = []
- self.min_distance = crash_utils.INFINITY
- self.min_distance_info = None
- self.changed_files = []
- self.changed_file_urls = []
- self.author = revision['author']
- self.component_name = component_name
- self.stack_frame_indices = []
- self.priorities = []
- self.revision_url = revision['url']
- self.review_url = ''
- self.reviewers = []
- self.reason = None
- self.time = revision['time']
-
- def ParseMessage(self, message, codereview_api_url):
- """Parses the message.
-
- It checks the message to extract the code review website and list of
- reviewers, and it also checks if the CL is a revert of another CL.
-
- Args:
- message: The message to parse.
- codereview_api_url: URL to retrieve codereview data from.
- """
- self.message = message
- for line in message.splitlines():
- line = line.strip()
- review_url_line_match = REVIEW_URL_PATTERN.match(line)
-
- # Check if the line has the code review information.
- if review_url_line_match:
-
- # Get review number for the code review site from the line.
- issue_number = review_url_line_match.group(3)
-
- # Get JSON from the code review site, ignore the line if it fails.
- url = codereview_api_url % issue_number
- json_string = crash_utils.GetDataFromURL(url)
- if not json_string:
- continue
-
- # Load the JSON from the string, and get the list of reviewers.
- code_review = crash_utils.LoadJSON(json_string)
- if code_review:
- self.reviewers = code_review['reviewers']
-
- # Check if this CL is a revert of other CL.
- if line.lower().startswith('revert'):
- self.is_revert = True
-
- # Check if the line says what CL this CL is a revert of.
- revert = self.REVERT_PATTERN.match(line)
- if revert:
- self.revert_of = revert.group(2)
- return
-
-
-class MatchSet(object):
- """Represents a set of matches.
-
- Attributes:
- matches: A map from CL to a match object.
- cls_to_ignore: A set of CLs to ignore.
- matches_lock: A lock guarding matches dictionary.
- """
-
- def __init__(self, codereview_api_url):
- self.codereview_api_url = codereview_api_url
- self.matches = {}
- self.cls_to_ignore = set()
- self.matches_lock = Lock()
-
- def RemoveRevertedCLs(self):
- """Removes CLs that are revert."""
- for cl in self.matches:
- if cl in self.cls_to_ignore:
- del self.matches[cl]
diff --git a/chromium/tools/findit/repository_parser_interface.py b/chromium/tools/findit/repository_parser_interface.py
deleted file mode 100644
index aca4c62b9c8..00000000000
--- a/chromium/tools/findit/repository_parser_interface.py
+++ /dev/null
@@ -1,58 +0,0 @@
-# Copyright (c) 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.
-
-
-class ParserInterface(object):
- """The interface for parsers."""
-
- def ParseChangelog(self, component_path, range_start, range_end):
- """Parses changelog from the URL stored in the parser object.
-
- Args:
- component_path: A string, path of the component. Path is used because
- path is unique while component name is not.
- range_start: The start range of the regression.
- range_end: The end range of the regression.
-
- Returns:
- A tuple containing revision_map and file_to_revision_map,
- revision_map maps a CL number to a dictionary containing revision
- information such as author, commit message and the revision url.
- file_to_revision_map maps a name of a file to a tuple containing the CL
- number and path of the file that CL changes.
- """
- raise NotImplementedError()
-
- def ParseLineDiff(self, path, component, file_action, githash):
- """Parses the line diff of the given hash.
-
- Args:
- path: The path of the file.
- component: The component the file is from.
- file_action: Whether file is modified, deleted or added.
- githash: The git hashcode to check the line diff.
-
- Returns:
- url: The URL of the diff page, returns the changelog page for the
- file if the diff cannot be retrieved.
- changed_line_numbers: The list of the line numbers that has been
- changed.
- changed_line_contents: The content of the changed lines.
- """
- raise NotImplementedError()
-
- def ParseBlameInfo(self, component, file_path, line, revision):
- """Parses blame information of the given file/line in revision.
-
- Args:
- component: The component this line is from.
- file_path: The path of the file.
- line: The line that caused the crash.
- revision: The revision to parse blame information for.
-
- Returns:
- The content of the line, the last changed revision of the line, author
- and the url of the revision.
- """
- raise NotImplementedError()
diff --git a/chromium/tools/findit/result.py b/chromium/tools/findit/result.py
deleted file mode 100644
index 360a69bb6be..00000000000
--- a/chromium/tools/findit/result.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright (c) 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.
-
-
-class Result(object):
-
- def __init__(self, suspected_cl, revision_url, component_name, author,
- reason, review_url, reviewers, line_content, message, time):
- self.suspected_cl = suspected_cl
- self.revision_url = revision_url
- self.component_name = component_name
- self.author = author
- self.reason = reason
- self.review_url = review_url
- self.reviewers = reviewers
- self.line_content = line_content
- self.commit_message = message
- self.time = time
diff --git a/chromium/tools/findit/run_all_tests.py b/chromium/tools/findit/run_all_tests.py
deleted file mode 100755
index 230537a6176..00000000000
--- a/chromium/tools/findit/run_all_tests.py
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 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.
-
-import sys
-import unittest
-
-from chromium_deps_unittest import ChromiumDEPSTest
-from common.http_client_local_unittest import HttpClientLocalTest
-
-
-if __name__ == '__main__':
- all_tests_suite = unittest.defaultTestLoader.loadTestsFromModule(
- sys.modules[__name__])
- tests = unittest.TestSuite(all_tests_suite)
- result = unittest.TextTestRunner(stream=sys.stdout, verbosity=2).run(tests)
- sys.exit(len(result.failures) + len(result.errors))
diff --git a/chromium/tools/findit/stacktrace.py b/chromium/tools/findit/stacktrace.py
deleted file mode 100644
index 137e6fc92f9..00000000000
--- a/chromium/tools/findit/stacktrace.py
+++ /dev/null
@@ -1,321 +0,0 @@
-# Copyright (c) 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.
-
-import re
-
-import crash_utils
-
-
-SYZYASAN_STACK_FRAME_PATTERN = re.compile(
- r'(CF: )?(.*?)( \(FPO: .*\) )?( \(CONV: .*\) )?\[(.*) @ (\d+)\]')
-FILE_PATH_AND_LINE_PATTERN = re.compile(r'(.*?):(\d+)(:\d+)?')
-
-
-class StackFrame(object):
- """Represents a frame in stacktrace.
-
- Attributes:
- index: An index of the stack frame.
- component_path: The path of the component this frame represents.
- component_name: The name of the component this frame represents.
- file_name: The name of the file that crashed.
- function: The function that caused the crash.
- file_path: The path of the crashed file.
- crashed_line_range: The line of the file that caused the crash.
- """
-
- def __init__(self, stack_frame_index, component_path, component_name,
- file_name, function, file_path, crashed_line_range):
- self.index = stack_frame_index
- self.component_path = component_path
- self.component_name = component_name
- self.file_name = file_name
- self.function = function
- self.file_path = file_path
- self.crashed_line_range = crashed_line_range
-
-
-class CallStack(object):
- """Represents a call stack within a stacktrace.
-
- It is a list of StackFrame object, and the object keeps track of whether
- the stack is crash stack, freed or previously-allocated.
- """
-
- def __init__(self, stack_priority):
- self.frame_list = []
- self.priority = stack_priority
-
- def Add(self, stacktrace_line):
- self.frame_list.append(stacktrace_line)
-
- def GetTopNFrames(self, n):
- return self.frame_list[:n]
-
-
-class Stacktrace(object):
- """Represents Stacktrace object.
-
- Contains a list of callstacks, because one stacktrace might have more than
- one callstacks.
- """
-
- def __init__(self, stacktrace, build_type, parsed_deps):
- self.stack_list = None
- self.ParseStacktrace(stacktrace, build_type, parsed_deps)
-
- def ParseStacktrace(self, stacktrace, build_type, parsed_deps):
- """Parses stacktrace and normalizes it.
-
- If there are multiple callstacks within the stacktrace,
- it will parse each of them separately, and store them in the stack_list
- variable.
-
- Args:
- stacktrace: A string containing stacktrace.
- build_type: A string containing the build type of the crash.
- parsed_deps: A parsed DEPS file to normalize path with.
- """
- # If the passed in string is empty, the object does not represent anything.
- if not stacktrace:
- return
- # Reset the stack list.
- self.stack_list = []
- reached_new_callstack = False
- # Note that we do not need exact stack frame index, we only need relative
- # position of a frame within a callstack. The reason for not extracting
- # index from a line is that some stack frames do not have index.
- stack_frame_index = 0
- current_stack = CallStack(-1)
-
- for line in stacktrace:
- line = line.strip()
- (is_new_callstack, stack_priority) = self.__IsStartOfNewCallStack(
- line, build_type)
- if is_new_callstack:
- # If this callstack is crash stack, update the boolean.
- if not reached_new_callstack:
- reached_new_callstack = True
- current_stack = CallStack(stack_priority)
-
- # If this is from freed or allocation, add the callstack we have
- # to the list of callstacks, and increment the stack priority.
- else:
- stack_frame_index = 0
- if current_stack and current_stack.frame_list:
- self.stack_list.append(current_stack)
- current_stack = CallStack(stack_priority)
-
- # Generate stack frame object from the line.
- parsed_stack_frame = self.__GenerateStackFrame(
- stack_frame_index, line, build_type, parsed_deps)
-
- # If the line does not represent the stack frame, ignore this line.
- if not parsed_stack_frame:
- continue
-
- # Add the parsed stack frame object to the current stack.
- current_stack.Add(parsed_stack_frame)
- stack_frame_index += 1
-
- # Add the current callstack only if there are frames in it.
- if current_stack and current_stack.frame_list:
- self.stack_list.append(current_stack)
-
- def __IsStartOfNewCallStack(self, line, build_type):
- """Check if this line is the start of the new callstack.
-
- Since each builds have different format of stacktrace, the logic for
- checking the line for all builds is handled in here.
-
- Args:
- line: Line to check for.
- build_type: The name of the build.
-
- Returns:
- True if the line is the start of new callstack, False otherwise. If True,
- it also returns the priority of the line.
- """
- if 'syzyasan' in build_type:
- # In syzyasan build, new stack starts with 'crash stack:',
- # 'freed stack:', etc.
- callstack_start_pattern = re.compile(r'^(.*) stack:$')
- match = callstack_start_pattern.match(line)
-
- # If the line matches the callstack start pattern.
- if match:
- # Check the type of the new match.
- stack_type = match.group(1)
-
- # Crash stack gets priority 0.
- if stack_type == 'Crash':
- return (True, 0)
-
- # Other callstacks all get priority 1.
- else:
- return (True, 1)
-
- elif 'tsan' in build_type:
- # Create patterns for each callstack type.
- crash_callstack_start_pattern1 = re.compile(
- r'^(Read|Write) of size \d+')
-
- crash_callstack_start_pattern2 = re.compile(
- r'^[A-Z]+: ThreadSanitizer')
-
- allocation_callstack_start_pattern = re.compile(
- r'^Previous (write|read) of size \d+')
-
- location_callstack_start_pattern = re.compile(
- r'^Location is heap block of size \d+')
-
- # Crash stack gets priority 0.
- if (crash_callstack_start_pattern1.match(line) or
- crash_callstack_start_pattern2.match(line)):
- return (True, 0)
-
- # All other stacks get priority 1.
- if allocation_callstack_start_pattern.match(line):
- return (True, 1)
-
- if location_callstack_start_pattern.match(line):
- return (True, 1)
-
- else:
- # In asan and other build types, crash stack can start
- # in two different ways.
- crash_callstack_start_pattern1 = re.compile(r'^==\d+== ?[A-Z]+:')
- crash_callstack_start_pattern2 = re.compile(
- r'^(READ|WRITE) of size \d+ at')
- crash_callstack_start_pattern3 = re.compile(r'^backtrace:')
-
- freed_callstack_start_pattern = re.compile(
- r'^freed by thread T\d+ (.* )?here:')
-
- allocation_callstack_start_pattern = re.compile(
- r'^previously allocated by thread T\d+ (.* )?here:')
-
- other_callstack_start_pattern = re.compile(
- r'^Thread T\d+ (.* )?created by')
-
- # Crash stack gets priority 0.
- if (crash_callstack_start_pattern1.match(line) or
- crash_callstack_start_pattern2.match(line) or
- crash_callstack_start_pattern3.match(line)):
- return (True, 0)
-
- # All other callstack gets priority 1.
- if freed_callstack_start_pattern.match(line):
- return (True, 1)
-
- if allocation_callstack_start_pattern.match(line):
- return (True, 1)
-
- if other_callstack_start_pattern.match(line):
- return (True, 1)
-
- # If the line does not match any pattern, return false and a dummy for
- # stack priority.
- return (False, -1)
-
- def __GenerateStackFrame(self, stack_frame_index, line, build_type,
- parsed_deps):
- """Extracts information from a line in stacktrace.
-
- Args:
- stack_frame_index: A stack frame index of this line.
- line: A stacktrace string to extract data from.
- build_type: A string containing the build type
- of this crash (e.g. linux_asan_chrome_mp).
- parsed_deps: A parsed DEPS file to normalize path with.
-
- Returns:
- A triple containing the name of the function, the path of the file and
- the crashed line number.
- """
- line_parts = line.split()
- try:
-
- if 'syzyasan' in build_type:
- stack_frame_match = SYZYASAN_STACK_FRAME_PATTERN.match(line)
-
- if not stack_frame_match:
- return None
- file_path = stack_frame_match.group(5)
- crashed_line_range = [int(stack_frame_match.group(6))]
- function = stack_frame_match.group(2)
-
- else:
- if not line_parts[0].startswith('#'):
- return None
-
- if 'tsan' in build_type:
- file_path_and_line = line_parts[-2]
- function = ' '.join(line_parts[1:-2])
- else:
- file_path_and_line = line_parts[-1]
- function = ' '.join(line_parts[3:-1])
-
- # Get file path and line info from the line.
- file_path_and_line_match = FILE_PATH_AND_LINE_PATTERN.match(
- file_path_and_line)
-
- # Return None if the file path information is not available
- if not file_path_and_line_match:
- return None
-
- file_path = file_path_and_line_match.group(1)
-
- # Get the crashed line range. For example, file_path:line_number:range.
- crashed_line_range_num = file_path_and_line_match.group(3)
-
- if crashed_line_range_num:
- # Strip ':' prefix.
- crashed_line_range_num = int(crashed_line_range_num[1:])
- else:
- crashed_line_range_num = 0
-
- crashed_line_number = int(file_path_and_line_match.group(2))
- # For example, 655:1 has crashed lines 655 and 656.
- crashed_line_range = \
- range(crashed_line_number,
- crashed_line_number + crashed_line_range_num + 1)
-
- # Return None if the line is malformed.
- except IndexError:
- return None
- except ValueError:
- return None
-
- # Normalize the file path so that it can be compared to repository path.
- (component_path, component_name, file_path) = (
- crash_utils.NormalizePath(file_path, parsed_deps))
-
- # Return a new stack frame object with the parsed information.
- file_name = file_path.split('/')[-1]
-
- # If we have the common stack frame index pattern, then use it
- # since it is more reliable.
- index_match = re.match('\s*#(\d+)\s.*', line)
- if index_match:
- stack_frame_index = int(index_match.group(1))
-
- return StackFrame(stack_frame_index, component_path, component_name,
- file_name, function, file_path, crashed_line_range)
-
- def __getitem__(self, index):
- return self.stack_list[index]
-
- def GetCrashStack(self):
- """Returns the callstack with the highest priority.
-
- Crash stack has priority 0, and allocation/freed/other thread stacks
- get priority 1.
-
- Returns:
- The highest priority callstack in the stacktrace.
- """
- sorted_stacklist = sorted(self.stack_list,
- key=lambda callstack: callstack.priority)
- return sorted_stacklist[0]
diff --git a/chromium/tools/findit/svn_repository_parser.py b/chromium/tools/findit/svn_repository_parser.py
deleted file mode 100644
index 64a4503d495..00000000000
--- a/chromium/tools/findit/svn_repository_parser.py
+++ /dev/null
@@ -1,250 +0,0 @@
-# Copyright (c) 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.
-
-import xml.dom.minidom as minidom
-from xml.parsers.expat import ExpatError
-
-import crash_utils
-from repository_parser_interface import ParserInterface
-
-
-# This number is 6 because each linediff page in src.chromium.org should
-# contain the following tables: table with revision number, table with actual
-# diff, table with dropdown menu, table with legend, a border table and a table
-# containing page information.
-NUM_TABLES_IN_LINEDIFF_PAGE = 6
-# Each of the linediff info should contain 3 tds, one for changed line number,
-# and two for line contents before/after.
-NUM_TDS_IN_LINEDIFF_PAGE = 3
-
-
-class SVNParser(ParserInterface):
- """Parser for SVN repository using chromium.org, for components in config.
-
- Attributes:
- url_map: A map from component to the urls, where urls are for changelog,
- revision, line diff and annotation.
- """
-
- def __init__(self, url_map):
- self.component_to_urls_map = url_map
-
- def ParseChangelog(self, component, range_start, range_end):
- file_to_revision_map = {}
- revision_map = {}
-
- # Check if the current component is supported by reading the components
- # parsed from config file. If it is not, fail.
-
- url_map = self.component_to_urls_map.get(component)
- if not url_map:
- return (revision_map, file_to_revision_map)
-
- # Retrieve data from the url, return empty map if fails.
- revision_range_str = '%s:%s' % (range_start, range_end)
- url = url_map['changelog_url'] % revision_range_str
- response = crash_utils.GetDataFromURL(url)
- if not response:
- return (revision_map, file_to_revision_map)
-
- # Parse xml out of the returned string. If it fails, return empty map.
- try:
- xml_revisions = minidom.parseString(response)
- except ExpatError:
- return (revision_map, file_to_revision_map)
-
- # Iterate through the returned XML object.
- revisions = xml_revisions.getElementsByTagName('logentry')
- for revision in revisions:
- # Create new revision object for each of the revision.
- revision_object = {}
-
- # Set author of the CL.
- revision_object['author'] = revision.getElementsByTagName(
- 'author')[0].firstChild.nodeValue
-
- # Get the revision number from xml.
- revision_number = int(revision.getAttribute('revision'))
-
- # Iterate through the changed paths in the CL.
- paths = revision.getElementsByTagName('paths')
- if paths:
- for changed_path in paths[0].getElementsByTagName('path'):
- # Get path and file change type from the xml.
- file_path = changed_path.firstChild.nodeValue
- file_change_type = changed_path.getAttribute('action')
-
- if file_path.startswith('/trunk/'):
- file_path = file_path[len('/trunk/'):]
-
- # Add file to the map.
- if file_path not in file_to_revision_map:
- file_to_revision_map[file_path] = []
- file_to_revision_map[file_path].append(
- (revision_number, file_change_type))
-
- # Set commit message of the CL.
- revision_object['message'] = revision.getElementsByTagName('msg')[
- 0].firstChild.nodeValue
-
- # Set url of this CL.
- revision_url = url_map['revision_url'] % revision_number
- revision_object['url'] = revision_url
-
- # Add this CL to the revision map.
- revision_map[revision_number] = revision_object
-
- return (revision_map, file_to_revision_map)
-
- def ParseLineDiff(self, path, component, file_change_type, revision_number):
- changed_line_numbers = []
- changed_line_contents = []
-
- url_map = self.component_to_urls_map.get(component)
- if not url_map:
- return (None, None, None)
-
- # If the file is added (not modified), treat it as if it is not changed.
- backup_url = url_map['revision_url'] % revision_number
- if file_change_type == 'A':
- return (backup_url, changed_line_numbers, changed_line_contents)
-
- # Retrieve data from the url. If no data is retrieved, return empty lists.
- url = url_map['diff_url'] % (path, revision_number - 1,
- revision_number, revision_number)
- data = crash_utils.GetDataFromURL(url)
- if not data:
- return (backup_url, changed_line_numbers, changed_line_contents)
-
- line_diff_html = minidom.parseString(data)
- tables = line_diff_html.getElementsByTagName('table')
- # If there are not NUM_TABLES tables in the html page, there should be an
- # error in the html page.
- if len(tables) != NUM_TABLES_IN_LINEDIFF_PAGE:
- return (backup_url, changed_line_numbers, changed_line_contents)
-
- # Diff content is in the second table. Each line of the diff content
- # is in <tr>.
- trs = tables[1].getElementsByTagName('tr')
- prefix_len = len('vc_diff_')
-
- # Filter trs so that it only contains diff chunk with contents.
- filtered_trs = []
- for tr in trs:
- tr_class = tr.getAttribute('class')
-
- # Check for the classes of the <tr>s.
- if tr_class:
- tr_class = tr_class[prefix_len:]
-
- # Do not have to add header.
- if tr_class == 'header' or tr_class == 'chunk_header':
- continue
-
- # If the class of tr is empty, this page does not have any change.
- if tr_class == 'empty':
- return (backup_url, changed_line_numbers, changed_line_contents)
-
- filtered_trs.append(tr)
-
- # Iterate through filtered trs, and grab line diff information.
- for tr in filtered_trs:
- tds = tr.getElementsByTagName('td')
-
- # If there aren't 3 tds, this line does should not contain line diff.
- if len(tds) != NUM_TDS_IN_LINEDIFF_PAGE:
- continue
-
- # If line number information is not in hyperlink, ignore this line.
- try:
- line_num = tds[0].getElementsByTagName('a')[0].firstChild.nodeValue
- left_diff_type = tds[1].getAttribute('class')[prefix_len:]
- right_diff_type = tds[2].getAttribute('class')[prefix_len:]
- except IndexError:
- continue
-
- # Treat the line as modified only if both left and right diff has type
- # changed or both have different change type, and if the change is not
- # deletion.
- if (left_diff_type != right_diff_type) or (
- left_diff_type == 'change' and right_diff_type == 'change'):
-
- # Check if the line content is not empty.
- try:
- new_line = tds[2].firstChild.nodeValue
- except AttributeError:
- new_line = ''
-
- if not (left_diff_type == 'remove' and right_diff_type == 'empty'):
- changed_line_numbers.append(int(line_num))
- changed_line_contents.append(new_line.strip())
-
- return (url, changed_line_numbers, changed_line_contents)
-
- def ParseBlameInfo(self, component, file_path, line, revision):
- url_map = self.component_to_urls_map.get(component)
- if not url_map:
- return None
-
- # Retrieve blame data from url, return None if fails.
- url = url_map['blame_url'] % (file_path, revision, revision)
- data = crash_utils.GetDataFromURL(url)
- if not data:
- return None
-
- blame_html = minidom.parseString(data)
-
- title = blame_html.getElementsByTagName('title')
- # If the returned html page is an exception page, return None.
- if title[0].firstChild.nodeValue == 'ViewVC Exception':
- return None
-
- # Each of the blame result is in <tr>.
- blame_results = blame_html.getElementsByTagName('tr')
- try:
- blame_result = blame_results[line]
- except IndexError:
- return None
-
- # There must be 4 <td> for each <tr>. If not, this page is wrong.
- tds = blame_result.getElementsByTagName('td')
- if len(tds) != 4:
- return None
-
- # The third <td> has the line content, separated by <span>s. Combine
- # those to get a string of changed line. If it has nothing, the line
- # is empty.
- line_content = ''
- if tds[3].hasChildNodes():
- contents = tds[3].childNodes
-
- for content in contents:
- # Nodetype 3 means it is text node.
- if content.nodeType == minidom.Node.TEXT_NODE:
- line_content += content.nodeValue
- else:
- line_content += content.firstChild.nodeValue
-
- line_content = line_content.strip()
-
- # If the current line has the same author/revision as the previous lines,
- # the result is not shown. Propagate up until we find the line with info.
- while not tds[1].firstChild:
- line -= 1
- blame_result = blame_results[line]
- tds = blame_result.getElementsByTagName('td')
- author = tds[1].firstChild.nodeValue
-
- # Revision can either be in hyperlink or plain text.
- try:
- revision = tds[2].getElementsByTagName('a')[0].firstChild.nodeValue
- except IndexError:
- revision = tds[2].firstChild.nodeValue
-
- (revision_info, _) = self.ParseChangelog(component, revision, revision)
- message = revision_info[int(revision)]['message']
-
- # Return the parsed information.
- revision_url = url_map['revision_url'] % int(revision)
- return (line_content, revision, author, revision_url, message)
diff --git a/chromium/tools/gdb/gdb_chrome.py b/chromium/tools/gdb/gdb_chrome.py
index dc6514944fe..9d727437b6e 100644
--- a/chromium/tools/gdb/gdb_chrome.py
+++ b/chromium/tools/gdb/gdb_chrome.py
@@ -211,7 +211,7 @@ pp_set.add_printer('base::TimeDelta', '^base::TimeDelta$', TimeDeltaPrinter)
class TimeTicksPrinter(TimeDeltaPrinter):
def __init__(self, val):
- self._timedelta = datetime.timedelta(microseconds=int(val['ticks_']))
+ self._timedelta = datetime.timedelta(microseconds=int(val['us_']))
pp_set.add_printer('base::TimeTicks', '^base::TimeTicks$', TimeTicksPrinter)
diff --git a/chromium/tools/generate_shim_headers/generate_shim_headers.py b/chromium/tools/generate_shim_headers/generate_shim_headers.py
index 81c531b2e6a..1b8e27f7682 100755
--- a/chromium/tools/generate_shim_headers/generate_shim_headers.py
+++ b/chromium/tools/generate_shim_headers/generate_shim_headers.py
@@ -65,7 +65,11 @@ def GeneratorMain(argv):
if options.outputs:
yield os.path.join(target_directory, header_filename)
if options.generate:
- with open(os.path.join(target_directory, header_filename), 'w') as f:
+ header_path = os.path.join(target_directory, header_filename)
+ header_dir = os.path.dirname(header_path)
+ if not os.path.exists(header_dir):
+ os.makedirs(header_dir)
+ with open(header_path, 'w') as f:
f.write(SHIM_TEMPLATE)
if options.define:
diff --git a/chromium/tools/gn/BUILD.gn b/chromium/tools/gn/BUILD.gn
index 2728c0d0906..2dfcf7f9f47 100644
--- a/chromium/tools/gn/BUILD.gn
+++ b/chromium/tools/gn/BUILD.gn
@@ -146,6 +146,8 @@ static_library("gn_lib") {
"path_output.h",
"pattern.cc",
"pattern.h",
+ "qt_creator_writer.cc",
+ "qt_creator_writer.h",
"runtime_deps.cc",
"runtime_deps.h",
"scheduler.cc",
@@ -207,6 +209,10 @@ static_library("gn_lib") {
"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",
]
@@ -252,6 +258,7 @@ executable("gn") {
":last_commit_position",
"//base",
"//build/config/sanitizers:deps",
+ "//build/win:default_exe_manifest",
]
}
@@ -277,7 +284,6 @@ test("gn_unittests") {
"function_write_file_unittest.cc",
"functions_target_unittest.cc",
"functions_unittest.cc",
- "group_target_generator_unittest.cc",
"header_checker_unittest.cc",
"inherited_libraries_unittest.cc",
"input_conversion_unittest.cc",
diff --git a/chromium/tools/gn/DEPS b/chromium/tools/gn/DEPS
new file mode 100644
index 00000000000..0de07bbaf08
--- /dev/null
+++ b/chromium/tools/gn/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+ "+third_party/re2",
+]
diff --git a/chromium/tools/gn/args.cc b/chromium/tools/gn/args.cc
index 60ee7b2ce33..d83c6789793 100644
--- a/chromium/tools/gn/args.cc
+++ b/chromium/tools/gn/args.cc
@@ -194,25 +194,12 @@ bool Args::VerifyAllOverridesUsed(Err* err) const {
if (all_overrides.empty())
return true;
- // Get a list of all possible overrides for help with error finding.
- //
- // It might be nice to do edit distance checks to see if we can find one close
- // to what you typed.
- std::string all_declared_str;
- for (const auto& map_pair : declared_arguments_per_toolchain_) {
- for (const auto& cur_str : map_pair.second) {
- if (!all_declared_str.empty())
- all_declared_str += ", ";
- all_declared_str += cur_str.first.as_string();
- }
- }
-
*err = Err(
all_overrides.begin()->second.origin(), "Build argument has no effect.",
"The variable \"" + all_overrides.begin()->first.as_string() +
"\" was set as a build argument\nbut never appeared in a " +
- "declare_args() block in any buildfile.\n\nPossible arguments: " +
- all_declared_str);
+ "declare_args() block in any buildfile.\n\n"
+ "To view possible args, run \"gn args --list <builddir>\"");
return false;
}
@@ -245,6 +232,7 @@ void Args::SetSystemVarsLocked(Scope* dest) const {
static const char kX86[] = "x86";
static const char kX64[] = "x64";
static const char kArm[] = "arm";
+ static const char kMips[] = "mipsel";
const char* arch = nullptr;
// Set the host CPU architecture based on the underlying OS, not
@@ -254,8 +242,10 @@ void Args::SetSystemVarsLocked(Scope* dest) const {
arch = kX86;
else if (os_arch == "x86_64")
arch = kX64;
- else if (os_arch.substr(3) == "arm")
+ else if (os_arch.substr(0, 3) == "arm")
arch = kArm;
+ else if (os_arch == "mips")
+ arch = kMips;
else
CHECK(false) << "OS architecture not handled.";
diff --git a/chromium/tools/gn/bin/gn-format.py b/chromium/tools/gn/bin/gn-format.py
index c835753eefb..4769640297f 100644
--- a/chromium/tools/gn/bin/gn-format.py
+++ b/chromium/tools/gn/bin/gn-format.py
@@ -38,7 +38,7 @@ def main():
p = subprocess.Popen([binary, 'format', '--stdin'],
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
stdin=subprocess.PIPE, startupinfo=startupinfo,
- universal_newlines=True)
+ shell=True, universal_newlines=True)
stdout, stderr = p.communicate(input=text)
if p.returncode != 0:
print 'Formatting failed, please report to gn-dev@chromium.org.'
diff --git a/chromium/tools/gn/bin/roll_gn.py b/chromium/tools/gn/bin/roll_gn.py
index 10b218c43af..b15aaf0b6ae 100755
--- a/chromium/tools/gn/bin/roll_gn.py
+++ b/chromium/tools/gn/bin/roll_gn.py
@@ -432,8 +432,7 @@ class GNRoller(object):
'\n'
'TBR=%s\n'
'CQ_EXTRA_TRYBOTS=tryserver.chromium.mac:mac_chromium_gn_dbg;'
- 'tryserver.chromium.win:win8_chromium_gn_dbg,'
- 'win_chromium_gn_x64_rel\n' % (
+ 'tryserver.chromium.win:win8_chromium_gn_dbg\n' % (
old_buildtools_commitish[:COMMITISH_DIGITS],
new_buildtools_commitish[:COMMITISH_DIGITS],
self.old_gn_commitish[:COMMITISH_DIGITS],
diff --git a/chromium/tools/gn/binary_target_generator.cc b/chromium/tools/gn/binary_target_generator.cc
index 7c81232dacc..78280132bed 100644
--- a/chromium/tools/gn/binary_target_generator.cc
+++ b/chromium/tools/gn/binary_target_generator.cc
@@ -7,8 +7,10 @@
#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"
@@ -34,6 +36,9 @@ void BinaryTargetGenerator::DoRun() {
if (!FillOutputPrefixOverride())
return;
+ if (!FillOutputDir())
+ return;
+
if (!FillOutputExtension())
return;
@@ -98,6 +103,29 @@ bool BinaryTargetGenerator::FillOutputPrefixOverride() {
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)
diff --git a/chromium/tools/gn/binary_target_generator.h b/chromium/tools/gn/binary_target_generator.h
index 40ed432b228..0788a2042c0 100644
--- a/chromium/tools/gn/binary_target_generator.h
+++ b/chromium/tools/gn/binary_target_generator.h
@@ -27,6 +27,7 @@ class BinaryTargetGenerator : public TargetGenerator {
bool FillCompleteStaticLib();
bool FillOutputName();
bool FillOutputPrefixOverride();
+ bool FillOutputDir();
bool FillOutputExtension();
bool FillAllowCircularIncludesFrom();
diff --git a/chromium/tools/gn/bootstrap/bootstrap.py b/chromium/tools/gn/bootstrap/bootstrap.py
index f1988331b3a..fea931245da 100755
--- a/chromium/tools/gn/bootstrap/bootstrap.py
+++ b/chromium/tools/gn/bootstrap/bootstrap.py
@@ -114,22 +114,31 @@ def main(argv):
return 0
+def write_buildflag_header_manually(root_gen_dir, header, flags):
+ mkdir_p(os.path.join(root_gen_dir, os.path.dirname(header)))
+ with tempfile.NamedTemporaryFile() as f:
+ f.write('--flags')
+ for name,value in flags.items():
+ f.write(' ' + name + '=' + value)
+ f.flush()
+
+ check_call([
+ os.path.join(SRC_ROOT, 'build', 'write_buildflag_header.py'),
+ '--output', header,
+ '--gen-dir', root_gen_dir,
+ '--definitions', f.name,
+ ])
+
+
def build_gn_with_ninja_manually(tempdir, options):
root_gen_dir = os.path.join(tempdir, 'gen')
mkdir_p(root_gen_dir)
- if is_linux:
- mkdir_p(os.path.join(root_gen_dir, 'base', 'allocator'))
- with tempfile.NamedTemporaryFile() as f:
- f.write('--flags USE_EXPERIMENTAL_ALLOCATOR_SHIM=true')
- f.flush()
-
- check_call([
- os.path.join(SRC_ROOT, 'build', 'write_buildflag_header.py'),
- '--output', 'base/allocator/features.h',
- '--gen-dir', root_gen_dir,
- '--definitions', f.name,
- ])
+ write_buildflag_header_manually(root_gen_dir, 'base/allocator/features.h',
+ {'USE_EXPERIMENTAL_ALLOCATOR_SHIM': 'true' if is_linux else 'false'})
+
+ write_buildflag_header_manually(root_gen_dir, 'base/debug/debugging_flags.h',
+ {'ENABLE_PROFILING': 'false'})
if is_mac:
# //base/build_time.cc needs base/generated_build_date.h,
@@ -198,8 +207,8 @@ def write_ninja(path, root_gen_dir, options):
'base/third_party/superfasthash/superfasthash.c',
])
static_libraries['base']['sources'].extend([
+ 'base/allocator/allocator_check.cc',
'base/allocator/allocator_extension.cc',
- 'base/allocator/allocator_shim.cc',
'base/at_exit.cc',
'base/base_paths.cc',
'base/base_switches.cc',
@@ -215,6 +224,7 @@ def write_ninja(path, root_gen_dir, options):
'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',
@@ -279,9 +289,9 @@ def write_ninja(path, root_gen_dir, options):
'base/third_party/dmg_fp/g_fmt.cc',
'base/third_party/icu/icu_utf.cc',
'base/third_party/nspr/prtime.cc',
- 'base/thread_task_runner_handle.cc',
'base/threading/non_thread_safe_impl.cc',
'base/threading/post_task_and_reply_impl.cc',
+ 'base/threading/sequenced_task_runner_handle.cc',
'base/threading/sequenced_worker_pool.cc',
'base/threading/simple_thread.cc',
'base/threading/thread.cc',
@@ -290,6 +300,7 @@ def write_ninja(path, root_gen_dir, options):
'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/threading/worker_pool.cc',
'base/time/time.cc',
'base/timer/elapsed_timer.cc',
@@ -385,6 +396,7 @@ def write_ninja(path, root_gen_dir, options):
'tool': 'cxx',
}
static_libraries['base']['sources'].extend([
+ 'base/allocator/allocator_shim.cc',
'base/allocator/allocator_shim_default_dispatch_to_glibc.cc',
'base/memory/shared_memory_posix.cc',
'base/nix/xdg_util.cc',
diff --git a/chromium/tools/gn/bundle_data.cc b/chromium/tools/gn/bundle_data.cc
index 7faccbdc51a..e1823653ba4 100644
--- a/chromium/tools/gn/bundle_data.cc
+++ b/chromium/tools/gn/bundle_data.cc
@@ -5,6 +5,7 @@
#include "tools/gn/bundle_data.h"
#include "base/logging.h"
+#include "tools/gn/filesystem_utils.h"
#include "tools/gn/output_file.h"
#include "tools/gn/settings.h"
#include "tools/gn/target.h"
@@ -103,10 +104,33 @@ void BundleData::GetOutputsAsSourceFiles(
if (!asset_catalog_sources_.empty())
outputs_as_source->push_back(GetCompiledAssetCatalogPath());
+
+ if (!root_dir_.is_null())
+ outputs_as_source->push_back(GetBundleRootDirOutput(settings));
}
SourceFile BundleData::GetCompiledAssetCatalogPath() const {
DCHECK(!asset_catalog_sources_.empty());
- std::string assets_car_path = resources_dir_ + "/Assets.car";
+ 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 {
+ const SourceDir& build_dir = settings->build_settings()->build_dir();
+ std::string bundle_root_relative = RebasePath(root_dir().value(), build_dir);
+
+ size_t first_component = bundle_root_relative.find('/');
+ if (first_component != std::string::npos) {
+ base::StringPiece outermost_bundle_dir =
+ base::StringPiece(bundle_root_relative).substr(0, first_component);
+ std::string return_value(build_dir.value());
+ outermost_bundle_dir.AppendToString(&return_value);
+ return SourceFile(SourceFile::SWAP_IN, &return_value);
+ }
+ return SourceFile(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
index e78589e9e91..3a1ce95ab7c 100644
--- a/chromium/tools/gn/bundle_data.h
+++ b/chromium/tools/gn/bundle_data.h
@@ -9,6 +9,7 @@
#include <vector>
#include "tools/gn/bundle_file_rule.h"
+#include "tools/gn/source_dir.h"
#include "tools/gn/unique_vector.h"
class OutputFile;
@@ -64,6 +65,21 @@ class BundleData {
// asset_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& asset_catalog_sources() { return asset_catalog_sources_; }
const SourceFiles& asset_catalog_sources() const {
@@ -73,17 +89,20 @@ class BundleData {
BundleFileRules& file_rules() { return file_rules_; }
const BundleFileRules& file_rules() const { return file_rules_; }
- std::string& root_dir() { return root_dir_; }
- const std::string& root_dir() const { return root_dir_; }
+ SourceDir& root_dir() { return root_dir_; }
+ const SourceDir& root_dir() const { return root_dir_; }
+
+ SourceDir& resources_dir() { return resources_dir_; }
+ const SourceDir& resources_dir() const { return resources_dir_; }
- std::string& resources_dir() { return resources_dir_; }
- const std::string& resources_dir() const { return resources_dir_; }
+ SourceDir& executable_dir() { return executable_dir_; }
+ const SourceDir& executable_dir() const { return executable_dir_; }
- std::string& executable_dir() { return executable_dir_; }
- const std::string& executable_dir() const { return executable_dir_; }
+ SourceDir& plugins_dir() { return plugins_dir_; }
+ const SourceDir& plugins_dir() const { return plugins_dir_; }
- std::string& plugins_dir() { return plugins_dir_; }
- const std::string& plugins_dir() const { return plugins_dir_; }
+ std::string& product_type() { return product_type_; }
+ const std::string& product_type() const { return product_type_; }
// Recursive collection of all bundle_data that the target depends on.
const UniqueTargets& bundle_deps() const { return bundle_deps_; }
@@ -95,10 +114,16 @@ class BundleData {
// 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.
- std::string root_dir_;
- std::string resources_dir_;
- std::string executable_dir_;
- std::string plugins_dir_;
+ SourceDir root_dir_;
+ SourceDir resources_dir_;
+ SourceDir executable_dir_;
+ SourceDir plugins_dir_;
+
+ // 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_;
+
+ DISALLOW_COPY_AND_ASSIGN(BundleData);
};
#endif // TOOLS_GN_BUNDLE_DATA_H_
diff --git a/chromium/tools/gn/bundle_file_rule.cc b/chromium/tools/gn/bundle_file_rule.cc
index 7684196c356..9f78667779d 100644
--- a/chromium/tools/gn/bundle_file_rule.cc
+++ b/chromium/tools/gn/bundle_file_rule.cc
@@ -29,16 +29,16 @@ SourceFile BundleFileRule::ApplyPatternToSource(
output_path.append(subrange.literal);
break;
case SUBSTITUTION_BUNDLE_ROOT_DIR:
- output_path.append(bundle_data.root_dir());
+ output_path.append(bundle_data.root_dir().value());
break;
case SUBSTITUTION_BUNDLE_RESOURCES_DIR:
- output_path.append(bundle_data.resources_dir());
+ output_path.append(bundle_data.resources_dir().value());
break;
case SUBSTITUTION_BUNDLE_EXECUTABLE_DIR:
- output_path.append(bundle_data.executable_dir());
+ output_path.append(bundle_data.executable_dir().value());
break;
case SUBSTITUTION_BUNDLE_PLUGINS_DIR:
- output_path.append(bundle_data.plugins_dir());
+ output_path.append(bundle_data.plugins_dir().value());
break;
default:
output_path.append(SubstitutionWriter::GetSourceSubstitution(
diff --git a/chromium/tools/gn/command_desc.cc b/chromium/tools/gn/command_desc.cc
index 15efe77cd6e..f2371e9d7cb 100644
--- a/chromium/tools/gn/command_desc.cc
+++ b/chromium/tools/gn/command_desc.cc
@@ -21,6 +21,7 @@
#include "tools/gn/setup.h"
#include "tools/gn/standard_out.h"
#include "tools/gn/substitution_writer.h"
+#include "tools/gn/switches.h"
#include "tools/gn/target.h"
#include "tools/gn/variables.h"
@@ -119,7 +120,7 @@ void PrintDeps(const Target* target, bool display_header) {
// Tree mode is separate.
if (cmdline->HasSwitch(kTree)) {
if (display_header)
- OutputString("\nDependency tree:\n");
+ OutputString("\nDependency tree\n");
if (cmdline->HasSwitch("all")) {
// Show all tree deps with no eliding.
@@ -136,7 +137,7 @@ void PrintDeps(const Target* target, bool display_header) {
if (cmdline->HasSwitch("all")) {
// Show all dependencies.
if (display_header)
- OutputString("\nAll recursive dependencies:\n");
+ OutputString("\nAll recursive dependencies\n");
std::set<const Target*> all_deps;
RecursiveCollectChildDeps(target, &all_deps);
@@ -147,7 +148,7 @@ void PrintDeps(const Target* target, bool display_header) {
if (display_header) {
OutputString(
"\nDirect dependencies "
- "(try also \"--all\", \"--tree\", or even \"--all --tree\"):\n");
+ "(try also \"--all\", \"--tree\", or even \"--all --tree\")\n");
}
for (const auto& pair : target->GetDeps(Target::DEPS_ALL))
deps.push_back(pair.ptr);
@@ -185,7 +186,7 @@ void PrintLibs(const Target* target, bool display_header) {
void PrintPublic(const Target* target, bool display_header) {
if (display_header)
- OutputString("\npublic:\n");
+ OutputString("\npublic\n");
if (target->all_headers_public()) {
OutputString(" [All headers listed in the sources are public.]\n");
@@ -200,7 +201,7 @@ void PrintPublic(const Target* target, bool display_header) {
void PrintCheckIncludes(const Target* target, bool display_header) {
if (display_header)
- OutputString("\ncheck_includes:\n");
+ OutputString("\ncheck_includes\n");
if (target->check_includes())
OutputString(" true\n");
@@ -210,7 +211,7 @@ void PrintCheckIncludes(const Target* target, bool display_header) {
void PrintAllowCircularIncludesFrom(const Target* target, bool display_header) {
if (display_header)
- OutputString("\nallow_circular_includes_from:\n");
+ OutputString("\nallow_circular_includes_from\n");
Label toolchain_label = target->label().GetToolchainLabel();
for (const auto& cur : target->allow_circular_includes_from())
@@ -219,14 +220,14 @@ void PrintAllowCircularIncludesFrom(const Target* target, bool display_header) {
void PrintVisibility(const Target* target, bool display_header) {
if (display_header)
- OutputString("\nvisibility:\n");
+ OutputString("\nvisibility\n");
OutputString(target->visibility().Describe(2, false));
}
void PrintTestonly(const Target* target, bool display_header) {
if (display_header)
- OutputString("\ntestonly:\n");
+ OutputString("\ntestonly\n");
if (target->testonly())
OutputString(" true\n");
@@ -251,7 +252,7 @@ void PrintSubConfigs(const Config* config, int indent_level) {
// This allows configs stored as either std::vector<LabelConfigPair> or
// UniqueVector<LabelConfigPair> to be printed.
template <class VectorType>
-void PrintConfigsVector(const Target* target,
+void PrintConfigsVector(const Item* item,
const VectorType& configs,
const std::string& heading,
bool display_header) {
@@ -263,12 +264,12 @@ void PrintConfigsVector(const Target* target,
// Don't sort since the order determines how things are processed.
if (display_header) {
if (tree)
- OutputString("\n" + heading + " tree (in order applying):\n");
+ OutputString("\n" + heading + " tree (in order applying)\n");
else
- OutputString("\n" + heading + " (in order applying, try also --tree):\n");
+ OutputString("\n" + heading + " (in order applying, try also --tree)\n");
}
- Label toolchain_label = target->label().GetToolchainLabel();
+ Label toolchain_label = item->label().GetToolchainLabel();
for (const auto& config : configs) {
OutputString(" " + config.label.GetUserVisibleName(toolchain_label) +
"\n");
@@ -282,6 +283,11 @@ void PrintConfigs(const Target* target, bool display_header) {
display_header);
}
+void PrintConfigs(const Config* config, bool display_header) {
+ PrintConfigsVector(config, config->configs().vector(), "configs",
+ display_header);
+}
+
void PrintPublicConfigs(const Target* target, bool display_header) {
PrintConfigsVector(target, target->public_configs(),
"public_configs", display_header);
@@ -300,7 +306,7 @@ void PrintFileList(const Target::FileList& files,
return;
if (display_header)
- OutputString("\n" + header + ":\n");
+ OutputString("\n" + header + "\n");
std::string indent = indent_extra ? " " : " ";
@@ -320,7 +326,7 @@ void PrintInputs(const Target* target, bool display_header) {
void PrintOutputs(const Target* target, bool display_header) {
if (display_header)
- OutputString("\noutputs:\n");
+ OutputString("\noutputs\n");
if (target->output_type() == Target::ACTION) {
// Action, print out outputs, don't apply sources to it.
@@ -337,12 +343,12 @@ void PrintOutputs(const Target* target, bool display_header) {
if (!outputs.required_types().empty()) {
// Display the pattern and resolved pattern separately, since there are
// subtitutions used.
- OutputString(" Output pattern:\n");
+ OutputString(" Output pattern\n");
for (const auto& elem : outputs.list())
OutputString(" " + elem.AsString() + "\n");
// Now display what that resolves to given the sources.
- OutputString("\n Resolved output file list:\n");
+ OutputString("\n Resolved output file list\n");
}
// Resolved output list.
@@ -355,13 +361,13 @@ void PrintOutputs(const Target* target, bool display_header) {
void PrintScript(const Target* target, bool display_header) {
if (display_header)
- OutputString("\nscript:\n");
+ OutputString("\nscript\n");
OutputString(" " + target->action_values().script().value() + "\n");
}
void PrintArgs(const Target* target, bool display_header) {
if (display_header)
- OutputString("\nargs:\n");
+ OutputString("\nargs\n");
for (const auto& elem : target->action_values().args().list()) {
OutputString(" " + elem.AsString() + "\n");
}
@@ -371,7 +377,7 @@ void PrintDepfile(const Target* target, bool display_header) {
if (target->action_values().depfile().empty())
return;
if (display_header)
- OutputString("\ndepfile:\n");
+ OutputString("\ndepfile\n");
OutputString(" " + target->action_values().depfile().AsString() + "\n");
}
@@ -392,12 +398,22 @@ template<> struct DescValueWriter<std::string> {
out << " " << str << "\n";
}
};
+
template<> struct DescValueWriter<SourceDir> {
void operator()(const SourceDir& dir, std::ostream& out) const {
out << " " << FormatSourceDir(dir) << "\n";
}
};
+template<> struct DescValueWriter<LibFile> {
+ void operator()(const LibFile& lib, std::ostream& out) const {
+ if (lib.is_source_file())
+ out << " " << lib.source_file().value() << "\n";
+ else
+ out << " " << lib.value() << "\n";
+ }
+};
+
// Writes a given config value type to the string, optionally with attribution.
// This should match RecursiveTargetConfigToStream in the order it traverses.
template<typename T> void OutputRecursiveTargetConfig(
@@ -433,7 +449,26 @@ template<typename T> void OutputRecursiveTargetConfig(
std::string out_str = out.str();
if (!out_str.empty()) {
- OutputString("\n" + std::string(header_name) + "\n");
+ if (header_name)
+ OutputString("\n" + std::string(header_name) + "\n");
+ OutputString(out_str);
+ }
+}
+
+template<typename T> void OutputConfigValueArray(
+ const ConfigValues& values,
+ const char* header_name,
+ const std::vector<T>& (ConfigValues::* getter)() const) {
+ std::ostringstream out;
+
+ DescValueWriter<T> writer;
+ for (const T& cur : (values.*getter)())
+ writer(cur, out);
+
+ std::string out_str = out.str();
+ if (!out_str.empty()) {
+ if (header_name)
+ OutputString("\n" + std::string(header_name) + "\n");
OutputString(out_str);
}
}
@@ -462,78 +497,295 @@ void PrintRuntimeDeps(const Target* target) {
}
}
+// If "what" is empty, prints all PCH info. If "what" is nonempty, prints only
+// the things that match (if any). Returns true if anything was printed.
+bool PrintPrecompiledHeaderInfo(const ConfigValues& values,
+ const std::string& what,
+ bool display_headers) {
+ bool found_match = false;
+ if (what == variables::kPrecompiledHeader || what.empty()) {
+ if (!values.precompiled_header().empty()) {
+ if (display_headers)
+ OutputString("\nprecompiled_header\n");
+ OutputString(values.precompiled_header() + "\n");
+ }
+ found_match = true;
+ }
+ if (what == variables::kPrecompiledSource || what.empty()) {
+ if (!values.precompiled_source().is_null()) {
+ if (display_headers)
+ OutputString("\nprecompiled_source\n");
+ OutputString(values.precompiled_source().value() + "\n");
+ }
+ found_match = true;
+ }
+ return found_match;
+}
+
+bool PrintTarget(const Target* target,
+ const std::string& what,
+ bool display_target_header) {
+ if (display_target_header) {
+ OutputString("Target: ", DECORATION_YELLOW);
+ OutputString(target->label().GetUserVisibleName(false) + "\n");
+ OutputString("Type: ", DECORATION_YELLOW);
+ OutputString(std::string(
+ Target::GetStringForOutputType(target->output_type())) + "\n");
+ OutputString("Toolchain: ", DECORATION_YELLOW);
+ OutputString(
+ target->label().GetToolchainLabel().GetUserVisibleName(false) + "\n");
+ }
+
+ // Display headers when outputting everything.
+ bool display_headers = what.empty();
+ bool is_binary_output = target->IsBinary();
+
+ bool found_match = false;
+
+ // General target meta variables.
+ if (what.empty() || what == variables::kVisibility) {
+ PrintVisibility(target, display_headers);
+ found_match = true;
+ }
+ if (what.empty() || what == variables::kTestonly) {
+ PrintTestonly(target, display_headers);
+ found_match = true;
+ }
+
+ // Binary target meta variables.
+ if (is_binary_output) {
+ if (what.empty() || what == variables::kCheckIncludes) {
+ PrintCheckIncludes(target, display_headers);
+ found_match = true;
+ }
+ if (what.empty() || what == variables::kAllowCircularIncludesFrom) {
+ PrintAllowCircularIncludesFrom(target, display_headers);
+ found_match = true;
+ }
+ }
+
+ // Sources and inputs.
+ if (what.empty() || what == variables::kSources) {
+ PrintSources(target, display_headers);
+ found_match = true;
+ }
+ if (what.empty() || what == variables::kPublic) {
+ PrintPublic(target, display_headers);
+ found_match = true;
+ }
+ if (what.empty() || what == variables::kInputs) {
+ PrintInputs(target, display_headers);
+ found_match = true;
+ }
+
+ // Configs. Configs set directly on a target are only relevant for binary
+ // targets
+ if (is_binary_output && (what.empty() || what == variables::kConfigs)) {
+ PrintConfigs(target, display_headers);
+ found_match = true;
+ }
+
+ // Dependent/public configs can be applied to anything.
+ if (what.empty() || what == variables::kPublicConfigs) {
+ PrintPublicConfigs(target, display_headers);
+ found_match = true;
+ }
+ if (what.empty() || what == variables::kAllDependentConfigs) {
+ PrintAllDependentConfigs(target, display_headers);
+ found_match = true;
+ }
+
+ // Action values.
+ if (target->output_type() == Target::ACTION ||
+ target->output_type() == Target::ACTION_FOREACH) {
+ if (what.empty() || what == variables::kScript) {
+ PrintScript(target, display_headers);
+ found_match = true;
+ }
+ if (what.empty() || what == variables::kArgs) {
+ PrintArgs(target, display_headers);
+ found_match = true;
+ }
+ if (what.empty() || what == variables::kDepfile) {
+ PrintDepfile(target, display_headers);
+ found_match = true;
+ }
+ }
+
+ // Outputs.
+ if (target->output_type() == Target::ACTION ||
+ target->output_type() == Target::ACTION_FOREACH ||
+ target->output_type() == Target::COPY_FILES ||
+ target->output_type() == Target::CREATE_BUNDLE) {
+ if (what.empty() || what == variables::kOutputs) {
+ PrintOutputs(target, display_headers);
+ found_match = true;
+ }
+ }
+
+ // Values from configs only apply to binary targets.
+ if (is_binary_output) {
+ #define CONFIG_VALUE_ARRAY_HANDLER(name, type) \
+ if (what.empty() || what == #name) { \
+ OutputRecursiveTargetConfig<type>( \
+ target, display_headers ? #name : nullptr, &ConfigValues::name); \
+ found_match = true; \
+ }
+
+ 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(ldflags, std::string)
+ // Libs and lib_dirs are handled specially below.
+
+ #undef CONFIG_VALUE_ARRAY_HANDLER
+
+ found_match |= PrintPrecompiledHeaderInfo(target->config_values(),
+ what, display_headers);
+ }
+
+ // Deps
+ if (what.empty() || what == "deps") {
+ PrintDeps(target, display_headers);
+ found_match = true;
+ }
+
+ // Runtime deps are special, print only when explicitly asked for and not in
+ // overview mode.
+ if (what == "runtime_deps") {
+ PrintRuntimeDeps(target);
+ found_match = true;
+ }
+
+ // Libs can be part of any target and get recursively pushed up the chain,
+ // so display them regardless of target type.
+ if (what.empty() || what == variables::kLibs) {
+ PrintLibs(target, display_headers);
+ found_match = true;
+ }
+ if (what.empty() || what == variables::kLibDirs) {
+ PrintLibDirs(target, display_headers);
+ found_match = true;
+ }
+
+ if (!found_match) {
+ OutputString("Don't know how to display \"" + what + "\" for \"" +
+ Target::GetStringForOutputType(target->output_type()) + "\".\n");
+ return false;
+ }
+ return true;
+}
+
+bool PrintConfig(const Config* config,
+ const std::string& what,
+ bool display_config_header) {
+ const ConfigValues& values = config->resolved_values();
+
+ if (display_config_header) {
+ OutputString("Config: ", DECORATION_YELLOW);
+ OutputString(config->label().GetUserVisibleName(false) + "\n");
+ OutputString("Toolchain: ", DECORATION_YELLOW);
+ OutputString(
+ config->label().GetToolchainLabel().GetUserVisibleName(false) + "\n");
+ if (what.empty() && !config->configs().empty()) {
+ OutputString(
+ "(This is a composite config, the values below are after the\n"
+ "expansion of the child configs.)\n");
+ }
+ }
+
+ // Display headers when outputting everything.
+ bool display_headers = what.empty();
+
+ if (what.empty() || what == variables::kConfigs)
+ PrintConfigs(config, display_headers);
+
+#define CONFIG_VALUE_ARRAY_HANDLER(name, type) \
+ if (what.empty() || what == #name) { \
+ OutputConfigValueArray<type>(values, display_headers ? #name : nullptr, \
+ &ConfigValues::name); \
+ found_match = true; \
+ }
+
+ bool found_match = false;
+
+ 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(ldflags, std::string)
+ CONFIG_VALUE_ARRAY_HANDLER(lib_dirs, SourceDir)
+ CONFIG_VALUE_ARRAY_HANDLER(libs, LibFile)
+
+#undef CONFIG_VALUE_ARRAY_HANDLER
+
+ // Handles all PCH-related variables.
+ found_match |= PrintPrecompiledHeaderInfo(config->resolved_values(),
+ what, display_headers);
+
+ if (!found_match) {
+ OutputString("Don't know how to display \"" + what + "\" for a config.\n");
+ return false;
+ }
+ return true;
+}
+
} // namespace
// desc ------------------------------------------------------------------------
const char kDesc[] = "desc";
const char kDesc_HelpShort[] =
- "desc: Show lots of insightful information about a target.";
+ "desc: Show lots of insightful information about a target or config.";
const char kDesc_Help[] =
- "gn desc <out_dir> <target label> [<what to show>] [--blame]\n"
+ "gn desc <out_dir> <label or pattern> [<what to show>] [--blame]\n"
"\n"
- " Displays information about a given labeled target for the given build.\n"
- " The build parameters will be taken for the build in the given\n"
- " <out_dir>.\n"
+ " Displays information about a given target or config. The build\n"
+ " build parameters will be taken for the build in the given <out_dir>.\n"
"\n"
- "Possibilities for <what to show>\n"
- " (If unspecified an overall summary will be displayed.)\n"
- "\n"
- " sources\n"
- " Source files.\n"
- "\n"
- " inputs\n"
- " Additional input dependencies.\n"
- "\n"
- " public\n"
- " Public header files.\n"
- "\n"
- " check_includes\n"
- " Whether \"gn check\" checks this target for include usage.\n"
+ " The <label or pattern> can be a target label, a config label, or a\n"
+ " label pattern (see \"gn help label_pattern\"). A label pattern will\n"
+ " only match targets.\n"
"\n"
- " allow_circular_includes_from\n"
- " Permit includes from these targets.\n"
- "\n"
- " visibility\n"
- " Prints which targets can depend on this one.\n"
- "\n"
- " testonly\n"
- " Whether this target may only be used in tests.\n"
- "\n"
- " configs\n"
- " Shows configs applied to the given target, sorted in the order\n"
- " they're specified. This includes both configs specified in the\n"
- " \"configs\" variable, as well as configs pushed onto this target\n"
- " via dependencies specifying \"all\" or \"direct\" dependent\n"
- " configs.\n"
+ "Possibilities for <what to show>\n"
"\n"
- " deps\n"
- " Show immediate or recursive dependencies. See below for flags that\n"
- " control deps printing.\n"
+ " (If unspecified an overall summary will be displayed.)\n"
"\n"
- " public_configs\n"
" all_dependent_configs\n"
- " Shows the labels of configs applied to targets that depend on this\n"
- " one (either directly or all of them).\n"
- "\n"
- " script\n"
+ " allow_circular_includes_from\n"
+ " arflags [--blame]\n"
" args\n"
+ " cflags [--blame]\n"
+ " cflags_cc [--blame]\n"
+ " cflags_cxx [--blame]\n"
+ " check_includes\n"
+ " configs [--tree] (see below)\n"
+ " defines [--blame]\n"
" depfile\n"
- " Actions only. The script and related values.\n"
- "\n"
- " outputs\n"
- " Outputs for script and copy target types.\n"
- "\n"
- " defines [--blame]\n"
- " include_dirs [--blame]\n"
- " cflags [--blame]\n"
- " cflags_cc [--blame]\n"
- " cflags_cxx [--blame]\n"
- " ldflags [--blame]\n"
+ " deps [--all] [--tree] (see below)\n"
+ " include_dirs [--blame]\n"
+ " inputs\n"
+ " ldflags [--blame]\n"
" lib_dirs\n"
" libs\n"
- " Shows the given values taken from the target and all configs\n"
- " applying. See \"--blame\" below.\n"
+ " outputs\n"
+ " public_configs\n"
+ " public\n"
+ " script\n"
+ " sources\n"
+ " testonly\n"
+ " visibility\n"
"\n"
" runtime_deps\n"
" Compute all runtime deps for the given target. This is a\n"
@@ -547,13 +799,32 @@ const char kDesc_Help[] =
"\n"
"Shared flags\n"
"\n"
+ ALL_TOOLCHAINS_SWITCH_HELP
+ "\n"
+ "Target flags\n"
+ "\n"
" --blame\n"
- " Used with any value specified by a config, this will name\n"
- " the config that specified the value. This doesn't currently work\n"
- " for libs and lib_dirs because those are inherited and are more\n"
- " complicated to figure out the blame (patches welcome).\n"
+ " Used with any value specified on a config, this will name\n"
+ " the config that cause that target to get the flag. This doesn't\n"
+ " currently work for libs and lib_dirs because those are inherited\n"
+ " and are more complicated to figure out the blame (patches\n"
+ " welcome).\n"
+ "\n"
+ "Configs\n"
+ "\n"
+ " The \"configs\" section will list all configs that apply. For targets\n"
+ " this will include configs specified in the \"configs\" variable of\n"
+ " the target, and also configs pushed onto this target via public\n"
+ " or \"all dependent\" configs.\n"
+ "\n"
+ " Configs can have child configs. Specifying --tree will show the\n"
+ " hierarchy.\n"
+ "\n"
+ "Printing deps\n"
"\n"
- "Flags that control how deps are printed\n"
+ " Deps will include all public, private, and data deps (TODO this could\n"
+ " be clarified and enhanced) sorted in order applying. The following\n"
+ " may be used:\n"
"\n"
" --all\n"
" Collects all recursive dependencies and prints a sorted flat list.\n"
@@ -597,9 +868,6 @@ const char kDesc_Help[] =
" Shows defines set for the //base:base target, annotated by where\n"
" each one was set from.\n";
-#define OUTPUT_CONFIG_VALUE(name, type) \
- OutputRecursiveTargetConfig<type>(target, #name, &ConfigValues::name);
-
int RunDesc(const std::vector<std::string>& args) {
if (args.size() != 2 && args.size() != 3) {
Err(Location(), "You're holding it wrong.",
@@ -607,6 +875,7 @@ int RunDesc(const std::vector<std::string>& args) {
.PrintToStdout();
return 1;
}
+ const base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess();
// Deliberately leaked to avoid expensive process teardown.
Setup* setup = new Setup;
@@ -616,147 +885,48 @@ int RunDesc(const std::vector<std::string>& args) {
if (!setup->Run())
return 1;
- const Target* target = ResolveTargetFromCommandLineString(setup, args[1]);
- if (!target)
- return 1;
-
-#define CONFIG_VALUE_HANDLER(name, type) \
- } else if (what == #name) { OUTPUT_CONFIG_VALUE(name, type)
-
- if (args.size() == 3) {
- // User specified one thing to display.
- const std::string& what = args[2];
- if (what == variables::kConfigs) {
- PrintConfigs(target, false);
- } else if (what == variables::kPublicConfigs) {
- PrintPublicConfigs(target, false);
- } else if (what == variables::kAllDependentConfigs) {
- PrintAllDependentConfigs(target, false);
- } else if (what == variables::kSources) {
- PrintSources(target, false);
- } else if (what == variables::kPublic) {
- PrintPublic(target, false);
- } else if (what == variables::kCheckIncludes) {
- PrintCheckIncludes(target, false);
- } else if (what == variables::kAllowCircularIncludesFrom) {
- PrintAllowCircularIncludesFrom(target, false);
- } else if (what == variables::kVisibility) {
- PrintVisibility(target, false);
- } else if (what == variables::kTestonly) {
- PrintTestonly(target, false);
- } else if (what == variables::kInputs) {
- PrintInputs(target, false);
- } else if (what == variables::kScript) {
- PrintScript(target, false);
- } else if (what == variables::kArgs) {
- PrintArgs(target, false);
- } else if (what == variables::kDepfile) {
- PrintDepfile(target, false);
- } else if (what == variables::kOutputs) {
- PrintOutputs(target, false);
- } else if (what == variables::kDeps) {
- PrintDeps(target, false);
- } else if (what == variables::kLibDirs) {
- PrintLibDirs(target, false);
- } else if (what == variables::kLibs) {
- PrintLibs(target, false);
- } else if (what == "runtime_deps") {
- PrintRuntimeDeps(target);
-
- CONFIG_VALUE_HANDLER(defines, std::string)
- CONFIG_VALUE_HANDLER(include_dirs, SourceDir)
- CONFIG_VALUE_HANDLER(asmflags, std::string)
- CONFIG_VALUE_HANDLER(cflags, std::string)
- CONFIG_VALUE_HANDLER(cflags_c, std::string)
- CONFIG_VALUE_HANDLER(cflags_cc, std::string)
- CONFIG_VALUE_HANDLER(cflags_objc, std::string)
- CONFIG_VALUE_HANDLER(cflags_objcc, std::string)
- CONFIG_VALUE_HANDLER(ldflags, std::string)
-
- } else {
- OutputString("Don't know how to display \"" + what + "\".\n");
- return 1;
- }
-
-#undef CONFIG_VALUE_HANDLER
- return 0;
- }
-
- // Display summary.
-
- // Display this only applicable to binary targets.
- bool is_binary_output =
- target->output_type() != Target::GROUP &&
- target->output_type() != Target::COPY_FILES &&
- target->output_type() != Target::ACTION &&
- target->output_type() != Target::ACTION_FOREACH &&
- target->output_type() != Target::BUNDLE_DATA &&
- target->output_type() != Target::CREATE_BUNDLE;
+ // 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;
- // Generally we only want to display toolchains on labels when the toolchain
- // is different than the default one for this target (which we always print
- // in the header).
- Label target_toolchain = target->label().GetToolchainLabel();
+ std::vector<std::string> target_list;
+ target_list.push_back(args[1]);
- // Header.
- OutputString("Target: ", DECORATION_YELLOW);
- OutputString(target->label().GetUserVisibleName(false) + "\n");
- OutputString("Type: ", DECORATION_YELLOW);
- OutputString(std::string(
- Target::GetStringForOutputType(target->output_type())) + "\n");
- OutputString("Toolchain: ", DECORATION_YELLOW);
- OutputString(target_toolchain.GetUserVisibleName(false) + "\n");
+ if (!ResolveFromCommandLineInput(
+ setup, target_list, cmdline->HasSwitch(switches::kAllToolchains),
+ &target_matches, &config_matches, &toolchain_matches, &file_matches))
+ return 1;
- PrintSources(target, true);
- if (is_binary_output) {
- PrintPublic(target, true);
- PrintCheckIncludes(target, true);
- PrintAllowCircularIncludesFrom(target, true);
- }
- PrintVisibility(target, true);
- if (is_binary_output) {
- PrintTestonly(target, true);
- PrintConfigs(target, true);
- }
+ std::string what_to_print;
+ if (args.size() == 3)
+ what_to_print = args[2];
- PrintPublicConfigs(target, true);
- PrintAllDependentConfigs(target, true);
+ bool multiple_outputs = (target_matches.size() + config_matches.size()) > 1;
- PrintInputs(target, true);
+ // Display headers for each target when printing all values, or when printing
+ // multiple targets or configs.
+ bool display_item_header = multiple_outputs || what_to_print.empty();
- if (is_binary_output) {
- OUTPUT_CONFIG_VALUE(defines, std::string)
- OUTPUT_CONFIG_VALUE(include_dirs, SourceDir)
- OUTPUT_CONFIG_VALUE(asmflags, std::string)
- OUTPUT_CONFIG_VALUE(cflags, std::string)
- OUTPUT_CONFIG_VALUE(cflags_c, std::string)
- OUTPUT_CONFIG_VALUE(cflags_cc, std::string)
- OUTPUT_CONFIG_VALUE(cflags_objc, std::string)
- OUTPUT_CONFIG_VALUE(cflags_objcc, std::string)
- OUTPUT_CONFIG_VALUE(ldflags, std::string)
- }
+ bool printed_output = false;
+ for (const Target* target : target_matches) {
+ if (printed_output)
+ OutputString("\n\n");
+ printed_output = true;
- if (target->output_type() == Target::ACTION ||
- target->output_type() == Target::ACTION_FOREACH) {
- PrintScript(target, true);
- PrintArgs(target, true);
- PrintDepfile(target, true);
+ if (!PrintTarget(target, what_to_print, display_item_header))
+ return 1;
}
+ for (const Config* config : config_matches) {
+ if (printed_output)
+ OutputString("\n\n");
+ printed_output = true;
- if (target->output_type() == Target::ACTION ||
- target->output_type() == Target::ACTION_FOREACH ||
- target->output_type() == Target::COPY_FILES ||
- target->output_type() == Target::CREATE_BUNDLE) {
- PrintOutputs(target, true);
+ if (!PrintConfig(config, what_to_print, display_item_header))
+ return 1;
}
- // Libs can be part of any target and get recursively pushed up the chain,
- // so always display them, even for groups and such.
- PrintLibs(target, true);
- PrintLibDirs(target, true);
-
- PrintDeps(target, true);
-
return 0;
}
diff --git a/chromium/tools/gn/command_format.cc b/chromium/tools/gn/command_format.cc
index a054b21b9b9..7b8f2f34201 100644
--- a/chromium/tools/gn/command_format.cc
+++ b/chromium/tools/gn/command_format.cc
@@ -181,7 +181,7 @@ class Printer {
// bracket.
template <class PARSENODE> // Just for const covariance.
void Sequence(SequenceStyle style,
- const std::vector<PARSENODE*>& list,
+ const std::vector<std::unique_ptr<PARSENODE>>& list,
const ParseNode* end,
bool force_multiline);
@@ -194,7 +194,7 @@ class Printer {
void InitializeSub(Printer* sub);
template <class PARSENODE>
- bool ListWillBeMultiline(const std::vector<PARSENODE*>& list,
+ bool ListWillBeMultiline(const std::vector<std::unique_ptr<PARSENODE>>& list,
const ParseNode* end);
std::string output_; // Output buffer.
@@ -385,7 +385,7 @@ void Printer::Block(const ParseNode* root) {
size_t i = 0;
for (const auto& stmt : block->statements()) {
- Expr(stmt, kPrecedenceLowest, std::string());
+ Expr(stmt.get(), kPrecedenceLowest, std::string());
Newline();
if (stmt->comments()) {
// Why are before() not printed here too? before() are handled inside
@@ -399,8 +399,8 @@ void Printer::Block(const ParseNode* root) {
}
}
if (i < block->statements().size() - 1 &&
- (ShouldAddBlankLineInBetween(block->statements()[i],
- block->statements()[i + 1]))) {
+ (ShouldAddBlankLineInBetween(block->statements()[i].get(),
+ block->statements()[i + 1].get()))) {
Newline();
}
++i;
@@ -648,7 +648,7 @@ int Printer::Expr(const ParseNode* root,
template <class PARSENODE>
void Printer::Sequence(SequenceStyle style,
- const std::vector<PARSENODE*>& list,
+ const std::vector<std::unique_ptr<PARSENODE>>& list,
const ParseNode* end,
bool force_multiline) {
if (style == kSequenceStyleList)
@@ -665,7 +665,7 @@ void Printer::Sequence(SequenceStyle style,
// No elements, and not forcing newlines, print nothing.
} else if (list.size() == 1 && !force_multiline) {
Print(" ");
- Expr(list[0], kPrecedenceLowest, std::string());
+ Expr(list[0].get(), kPrecedenceLowest, std::string());
CHECK(!list[0]->comments() || list[0]->comments()->after().empty());
Print(" ");
} else {
@@ -687,11 +687,11 @@ void Printer::Sequence(SequenceStyle style,
bool body_of_list = i < list.size() - 1 || style == kSequenceStyleList;
bool want_comma =
body_of_list && (style == kSequenceStyleList && !x->AsBlockComment());
- Expr(x, kPrecedenceLowest, want_comma ? "," : std::string());
+ 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], list[i + 1]))
+ ShouldAddBlankLineInBetween(list[i].get(), list[i + 1].get()))
Newline();
}
++i;
@@ -734,7 +734,7 @@ int Printer::FunctionCall(const FunctionCallNode* func_call,
bool have_block = func_call->block() != nullptr;
bool force_multiline = false;
- const std::vector<const ParseNode*>& list = func_call->args()->contents();
+ const auto& list = func_call->args()->contents();
const ParseNode* end = func_call->args()->End();
if (end && end->comments() && !end->comments()->before().empty())
@@ -767,7 +767,7 @@ int Printer::FunctionCall(const FunctionCallNode* func_call,
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], kPrecedenceLowest,
+ penalty_one_line += sub1.Expr(list[i].get(), kPrecedenceLowest,
i < list.size() - 1 ? ", " : std::string());
}
sub1.Print(terminator);
@@ -785,8 +785,9 @@ int Printer::FunctionCall(const FunctionCallNode* func_call,
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], kPrecedenceLowest, i < list.size() - 1 ? "," : std::string());
+ penalty_multiline_start_same_line +=
+ sub2.Expr(list[i].get(), kPrecedenceLowest,
+ i < list.size() - 1 ? "," : std::string());
if (i < list.size() - 1) {
sub2.Newline();
}
@@ -807,8 +808,9 @@ int Printer::FunctionCall(const FunctionCallNode* func_call,
std::abs(sub3.CurrentColumn() - start_column) *
kPenaltyHorizontalSeparation;
}
- penalty_multiline_start_next_line += sub3.Expr(
- list[i], kPrecedenceLowest, i < list.size() - 1 ? "," : std::string());
+ penalty_multiline_start_next_line +=
+ sub3.Expr(list[i].get(), kPrecedenceLowest,
+ i < list.size() - 1 ? "," : std::string());
if (i < list.size() - 1) {
sub3.Newline();
}
@@ -852,7 +854,7 @@ int Printer::FunctionCall(const FunctionCallNode* func_call,
Newline();
}
bool want_comma = i < list.size() - 1 && !x->AsBlockComment();
- Expr(x, kPrecedenceLowest, want_comma ? "," : std::string());
+ Expr(x.get(), kPrecedenceLowest, want_comma ? "," : std::string());
CHECK(!x->comments() || x->comments()->after().empty());
if (i < list.size() - 1) {
if (!want_comma)
@@ -900,8 +902,9 @@ void Printer::InitializeSub(Printer* sub) {
}
template <class PARSENODE>
-bool Printer::ListWillBeMultiline(const std::vector<PARSENODE*>& list,
- const ParseNode* end) {
+bool Printer::ListWillBeMultiline(
+ const std::vector<std::unique_ptr<PARSENODE>>& list,
+ const ParseNode* end) {
if (list.size() > 1)
return true;
diff --git a/chromium/tools/gn/command_gen.cc b/chromium/tools/gn/command_gen.cc
index fee3f1a31f8..7bdb6d81fe3 100644
--- a/chromium/tools/gn/command_gen.cc
+++ b/chromium/tools/gn/command_gen.cc
@@ -13,6 +13,7 @@
#include "tools/gn/eclipse_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"
@@ -20,6 +21,7 @@
#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 {
@@ -29,10 +31,15 @@ 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 kSwitchIdeValueXcode[] = "xcode";
+const char kSwitchNinjaExtraArgs[] = "ninja-extra-args";
+const char kSwitchRootTarget[] = "root-target";
const char kSwitchSln[] = "sln";
+const char kSwitchWorkspace[] = "workspace";
// Called on worker thread to write the ninja file.
void BackgroundDoWrite(const Target* target) {
@@ -188,6 +195,31 @@ bool RunIdeWriter(const std::string& ide,
"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 && !command_line->HasSwitch(switches::kQuiet)) {
+ 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 && !command_line->HasSwitch(switches::kQuiet)) {
+ OutputString("Generating QtCreator projects took " +
+ base::Int64ToString(timer.Elapsed().InMilliseconds()) +
+ "ms\n");
+ }
+ return res;
}
*err = Err(Location(), "Unknown IDE: " + ide);
@@ -225,16 +257,44 @@ const char kGen_Help[] =
" (default Visual Studio version: 2015)\n"
" \"vs2013\" - Visual Studio 2013 project/solution files.\n"
" \"vs2015\" - Visual Studio 2015 project/solution files.\n"
- "\n"
- " --sln=<file_name>\n"
- " Override default sln file name (\"all\"). Solution file is written\n"
- " to the root build directory. Only for Visual Studio.\n"
+ " \"xcode\" - Xcode workspace/solution files.\n"
+ " \"qtcreator\" - QtCreator project files.\n"
"\n"
" --filters=<path_prefixes>\n"
" Semicolon-separated list of label patterns used to limit the set\n"
" of generated projects (see \"gn help label_pattern\"). Only\n"
- " matching targets will be included to the solution. Only for Visual\n"
- " Studio.\n"
+ " matching targets will be included to the solution. Only used for\n"
+ " Visual Studio and Xcode.\n"
+ "\n"
+ "Visual Studio Flags\n"
+ "\n"
+ " --sln=<file_name>\n"
+ " Override default sln file name (\"all\"). Solution file is written\n"
+ " to the root build directory.\n"
+ "\n"
+ "Xcode Flags\n"
+ "\n"
+ " --workspace=<file_name>\n"
+ " Override defaut workspace file name (\"all\"). The workspace file\n"
+ " is written to the root build directory.\n"
+ "\n"
+ " --ninja-extra-args=<string>\n"
+ " This string is passed without any quoting to the ninja invocation\n"
+ " command-line. Can be used to configure ninja flags, like \"-j\" if\n"
+ " using goma for example.\n"
+ "\n"
+ " --root-target=<target_name>\n"
+ " Name of the target corresponding to \"All\" target in Xcode.\n"
+ " If unset, \"All\" invokes ninja without any target\n"
+ " and builds everything.\n"
+ "\n"
+ "QtCreator Flags\n"
+ "\n"
+ " --root-target=<target_name>\n"
+ " Name of the root target for which the QtCreator project will be\n"
+ " generated to contain files of it and its dependencies. If unset, \n"
+ " the whole build graph will be emitted.\n"
+ "\n"
"\n"
"Eclipse IDE Support\n"
"\n"
diff --git a/chromium/tools/gn/command_ls.cc b/chromium/tools/gn/command_ls.cc
index eddb51c3797..c9b9672cf80 100644
--- a/chromium/tools/gn/command_ls.cc
+++ b/chromium/tools/gn/command_ls.cc
@@ -10,6 +10,7 @@
#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 {
@@ -34,11 +35,7 @@ const char kLs_Help[] =
"\n"
TARGET_PRINTING_MODE_COMMAND_LINE_HELP
"\n"
- " --all-toolchains\n"
- " Matches all toolchains. When set, if the label pattern does not\n"
- " specify an explicit toolchain, labels from all toolchains will be\n"
- " matched. When unset, only targets in the default toolchain will\n"
- " be matched unless an explicit toolchain in the label is set.\n"
+ ALL_TOOLCHAINS_SWITCH_HELP
"\n"
TARGET_TESTONLY_FILTER_COMMAND_LINE_HELP
"\n"
@@ -81,7 +78,7 @@ int RunLs(const std::vector<std::string>& args) {
return 1;
const base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess();
- bool all_toolchains = cmdline->HasSwitch("all-toolchains");
+ bool all_toolchains = cmdline->HasSwitch(switches::kAllToolchains);
std::vector<const Target*> matches;
if (args.size() > 1) {
diff --git a/chromium/tools/gn/command_refs.cc b/chromium/tools/gn/command_refs.cc
index 821fd88d7e9..413a98f89c7 100644
--- a/chromium/tools/gn/command_refs.cc
+++ b/chromium/tools/gn/command_refs.cc
@@ -17,6 +17,7 @@
#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 {
@@ -315,16 +316,7 @@ const char kRefs_Help[] =
"\n"
" When used with --tree, turns off eliding to show a complete tree.\n"
"\n"
- " --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 and\n"
- " printed (potentially with its recursive dependencies, depending on\n"
- " the other options). With this flag, both will be printed\n"
- " (potentially with both of their recursive dependencies).\n"
+ ALL_TOOLCHAINS_SWITCH_HELP
"\n"
TARGET_PRINTING_MODE_COMMAND_LINE_HELP
"\n"
@@ -397,7 +389,7 @@ int RunRefs(const std::vector<std::string>& args) {
const base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess();
bool tree = cmdline->HasSwitch("tree");
bool all = cmdline->HasSwitch("all");
- bool all_toolchains = cmdline->HasSwitch("all-toolchains");
+ bool all_toolchains = cmdline->HasSwitch(switches::kAllToolchains);
Setup* setup = new Setup;
setup->build_settings().set_check_for_bad_items(false);
diff --git a/chromium/tools/gn/commands.cc b/chromium/tools/gn/commands.cc
index ed7a009d6af..8682d920dfb 100644
--- a/chromium/tools/gn/commands.cc
+++ b/chromium/tools/gn/commands.cc
@@ -5,6 +5,7 @@
#include "tools/gn/commands.h"
#include "base/command_line.h"
+#include "base/strings/string_split.h"
#include "tools/gn/builder.h"
#include "tools/gn/filesystem_utils.h"
#include "tools/gn/item.h"
@@ -468,6 +469,27 @@ void FilterTargetsByPatterns(const std::vector<const Target*>& input,
}
}
+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 =
+ SourceDirForCurrentDirectory(build_settings->root_path());
+
+ filters->reserve(tokens.size());
+ for (const std::string& token : tokens) {
+ LabelPattern pattern =
+ LabelPattern::GetPattern(root_dir, Value(nullptr, token), err);
+ if (err->has_error())
+ return false;
+ filters->push_back(pattern);
+ }
+
+ return true;
+}
+
void FilterAndPrintTargets(bool indent, std::vector<const Target*>* targets) {
if (targets->empty())
return;
diff --git a/chromium/tools/gn/commands.h b/chromium/tools/gn/commands.h
index 9d8af5cb7d0..fdd10fcc231 100644
--- a/chromium/tools/gn/commands.h
+++ b/chromium/tools/gn/commands.h
@@ -140,6 +140,12 @@ 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.
diff --git a/chromium/tools/gn/config_values.cc b/chromium/tools/gn/config_values.cc
index 73486cd84bf..cfcb9e4387b 100644
--- a/chromium/tools/gn/config_values.cc
+++ b/chromium/tools/gn/config_values.cc
@@ -24,6 +24,7 @@ ConfigValues::~ConfigValues() {
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_);
diff --git a/chromium/tools/gn/config_values.h b/chromium/tools/gn/config_values.h
index 823f1df9fc4..af97c2bc62c 100644
--- a/chromium/tools/gn/config_values.h
+++ b/chromium/tools/gn/config_values.h
@@ -30,6 +30,11 @@ class ConfigValues {
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)
@@ -40,7 +45,10 @@ class ConfigValues {
DIR_VALUES_ACCESSOR (include_dirs)
STRING_VALUES_ACCESSOR(ldflags)
DIR_VALUES_ACCESSOR (lib_dirs)
- // If you add a new one, be sure to update AppendValues().
+ // =================================================================
+ // IMPORTANT: If you add a new one, be sure to update AppendValues()
+ // and command_desc.cc.
+ // =================================================================
#undef STRING_VALUES_ACCESSOR
#undef DIR_VALUES_ACCESSOR
@@ -65,6 +73,7 @@ class ConfigValues {
}
private:
+ std::vector<std::string> arflags_;
std::vector<std::string> asmflags_;
std::vector<std::string> cflags_;
std::vector<std::string> cflags_c_;
diff --git a/chromium/tools/gn/config_values_generator.cc b/chromium/tools/gn/config_values_generator.cc
index 3cc8235face..e92f091352d 100644
--- a/chromium/tools/gn/config_values_generator.cc
+++ b/chromium/tools/gn/config_values_generator.cc
@@ -67,6 +67,7 @@ void ConfigValuesGenerator::Run() {
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)
diff --git a/chromium/tools/gn/create_bundle_target_generator.cc b/chromium/tools/gn/create_bundle_target_generator.cc
index 206a91861e9..83749983e6d 100644
--- a/chromium/tools/gn/create_bundle_target_generator.cc
+++ b/chromium/tools/gn/create_bundle_target_generator.cc
@@ -25,7 +25,7 @@ void CreateBundleTargetGenerator::DoRun() {
target_->set_output_type(Target::CREATE_BUNDLE);
BundleData& bundle_data = target_->bundle_data();
- if (!GetBundleDir(std::string(),
+ if (!GetBundleDir(SourceDir(),
variables::kBundleRootDir,
&bundle_data.root_dir()))
return;
@@ -41,29 +41,39 @@ void CreateBundleTargetGenerator::DoRun() {
variables::kBundlePlugInsDir,
&bundle_data.plugins_dir()))
return;
+
+ const Value* value = scope_->GetValue(variables::kProductType, true);
+ if (value) {
+ if (!value->VerifyTypeIs(Value::STRING, err_))
+ return;
+
+ bundle_data.product_type().assign(value->string_value());
+ }
}
bool CreateBundleTargetGenerator::GetBundleDir(
- const std::string& bundle_root_dir,
+ const SourceDir& bundle_root_dir,
const base::StringPiece& name,
- std::string* bundle_dir) {
+ SourceDir* bundle_dir) {
const Value* value = scope_->GetValue(name, true);
if (!value)
return true;
if (!value->VerifyTypeIs(Value::STRING, err_))
return false;
- const std::string& str = value->string_value();
+ 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 &&
- !IsStringInOutputDir(SourceDir(bundle_root_dir), str)) {
+ 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->assign(value->string_value());
+ bundle_dir->SwapValue(&str);
return true;
}
diff --git a/chromium/tools/gn/create_bundle_target_generator.h b/chromium/tools/gn/create_bundle_target_generator.h
index db82b8a4c0b..50040b8744d 100644
--- a/chromium/tools/gn/create_bundle_target_generator.h
+++ b/chromium/tools/gn/create_bundle_target_generator.h
@@ -8,6 +8,8 @@
#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:
@@ -21,9 +23,9 @@ class CreateBundleTargetGenerator : public TargetGenerator {
void DoRun() override;
private:
- bool GetBundleDir(const std::string& bundle_root_dir,
+ bool GetBundleDir(const SourceDir& bundle_root_dir,
const base::StringPiece& name,
- std::string* bundle_dir);
+ SourceDir* bundle_dir);
DISALLOW_COPY_AND_ASSIGN(CreateBundleTargetGenerator);
};
diff --git a/chromium/tools/gn/docs/cookbook.md b/chromium/tools/gn/docs/cookbook.md
index febc16c17a6..687d9eb9e01 100644
--- a/chromium/tools/gn/docs/cookbook.md
+++ b/chromium/tools/gn/docs/cookbook.md
@@ -122,6 +122,7 @@ component("base") {
'sources': [
'a.cc',
'b.cc',
+ 'c.cc',
],
'dependencies': [
'<(DEPTH)/base/base.gyp:foo',
@@ -149,22 +150,26 @@ component("base") {
```
sources = [
- "a.cc",
- "b.cc",
+ "c.cc",
]
deps = [
"//base:foo",
]
if (is_win) {
- sources -= [ "a.cc" ]
- sources += [ "foo.cc" ]
+ sources += [
+ "b.cc",
+ "foo.cc',
+ ]
deps += [ "//base:bar" ]
} else {
- sources -= [ "b.cc" ]
+ sources += [ "a.cc" ]
}
```
+Note that in GN we prefer to only add files when needed, and don't add all of
+them at first only to remove them later like in gyp.
+
## Variable mappings
### Build configuration
@@ -279,8 +284,6 @@ places are noted in the table below.
| `use_gnome_keyring` (0/1) | `is_desktop_linux` (true/false) | |
| `use_goma` (0/1) | `use_goma` (true/false) | `//build/toolchain/goma.gni` |
| `use_nss_certs` (0/1) | `use_nss_certs` (true/false) | `//build/config/crypto.gni` (Many of these conditions can be deleted, see the "SSL" notes on targets below.) |
-| `use_nss_verifier` (0/1) | `use_nss_verifier` (true/false) | `//build/config/crypto.gni` (Many of these conditions can be deleted, see the "SSL" notes on targets below.) |
-| `use_openssl` (0/1) | `use_openssl` (true/false) | `//build/config/crypto.gni` (Many of these conditions can be deleted, see the "SSL" notes on targets below.) |
| `use_pango` (0/1) | `use_pango` (true/false) | `//build/config/ui.gni` |
| `use_ozone` (0/1) | `use_ozone` (true/false) | `//build/config/ui.gni` |
| `use_seccomp_bpf` (0/1) | `use_seccomp_bpf` (true/false) | `//build/config/features.gni` |
@@ -302,8 +305,8 @@ targets only, don't add stuff here just because you converted it.)
| `base/base.gyp:run_all_unittests` | `//base/test:run_all_unittests` | |
| `base/base.gyp:test_support_base` | `//base/test:test_support` | |
| `base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations` | `//base/third_party/dynamic_annotations` | |
-| `build/linux/system.gyp:*` (except ssl) | `//build/config/linux:*` | Linux system targets |
-| `build/linux/system.gyp:ssl` | `//crypto:platform` | SSL |
+| `build/linux/system.gyp:*` (except nss) | `//build/config/linux:*` | Linux system targets |
+| `build/linux/system.gyp:nss` | `//crypto:platform` | SSL |
| `net/third_party/nss/ssl.gyp:libssl` | `//crypto:platform` | SSL |
| `skia/skia.gyp:skia` | `//skia` | |
| `testing/gmock.gyp:gmock` | `//testing/gmock` | Secondary tree |
diff --git a/chromium/tools/gn/docs/reference.md b/chromium/tools/gn/docs/reference.md
index 22cbee0aa68..c596b27f25c 100644
--- a/chromium/tools/gn/docs/reference.md
+++ b/chromium/tools/gn/docs/reference.md
@@ -70,7 +70,29 @@
```
-## **\--markdown**: write the output in the Markdown format.
+## **\--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.
+
+
+```
+## **\--markdown**: Write help output in the Markdown format.
## **\--[no]color**: Forces colored output on or off.
@@ -154,6 +176,16 @@
```
+## **\--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.
+
+
+```
## **\--threads**: Specify number of worker threads.
```
@@ -414,74 +446,47 @@
```
-## **gn desc <out_dir> <target label> [<what to show>] [\--blame]**
+## **gn desc <out_dir> <label or pattern> [<what to show>] [\--blame]**
```
- Displays information about a given labeled target for the given build.
- The build parameters will be taken for the build in the given
- <out_dir>.
+ 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.)
- sources
- Source files.
-
- inputs
- Additional input dependencies.
-
- public
- Public header files.
-
- check_includes
- Whether "gn check" checks this target for include usage.
-
- allow_circular_includes_from
- Permit includes from these targets.
-
- visibility
- Prints which targets can depend on this one.
-
- testonly
- Whether this target may only be used in tests.
-
- configs
- Shows configs applied to the given target, sorted in the order
- they're specified. This includes both configs specified in the
- "configs" variable, as well as configs pushed onto this target
- via dependencies specifying "all" or "direct" dependent
- configs.
-
- deps
- Show immediate or recursive dependencies. See below for flags that
- control deps printing.
-
- public_configs
all_dependent_configs
- Shows the labels of configs applied to targets that depend on this
- one (either directly or all of them).
-
- script
+ allow_circular_includes_from
+ arflags [--blame]
args
+ cflags [--blame]
+ cflags_cc [--blame]
+ cflags_cxx [--blame]
+ check_includes
+ configs [--tree] (see below)
+ defines [--blame]
depfile
- Actions only. The script and related values.
-
- outputs
- Outputs for script and copy target types.
-
- defines [--blame]
- include_dirs [--blame]
- cflags [--blame]
- cflags_cc [--blame]
- cflags_cxx [--blame]
- ldflags [--blame]
+ deps [--all] [--tree] (see below)
+ include_dirs [--blame]
+ inputs
+ ldflags [--blame]
lib_dirs
libs
- Shows the given values taken from the target and all configs
- applying. See "--blame" below.
+ outputs
+ public_configs
+ public
+ script
+ sources
+ testonly
+ visibility
runtime_deps
Compute all runtime deps for the given target. This is a
@@ -498,17 +503,49 @@
### **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.
+
+```
+
+### **Target flags**
+
+```
--blame
- Used with any value specified by a config, this will name
- the config that specified the value. 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).
+ 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).
```
-### **Flags that control how deps are printed**
+### **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 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).
@@ -654,16 +691,53 @@
(default Visual Studio version: 2015)
"vs2013" - Visual Studio 2013 project/solution files.
"vs2015" - Visual Studio 2015 project/solution files.
-
- --sln=<file_name>
- Override default sln file name ("all"). Solution file is written
- to the root build directory. Only for Visual Studio.
+ "xcode" - Xcode workspace/solution files.
+ "qtcreator" - QtCreator project files.
--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 will be included to the solution. Only for Visual
- Studio.
+ matching targets will be included to the solution. Only used for
+ Visual Studio and Xcode.
+
+```
+
+### **Visual Studio Flags**
+
+```
+ --sln=<file_name>
+ Override default sln file name ("all"). Solution file is written
+ to the root build directory.
+
+```
+
+### **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" if
+ using goma for example.
+
+ --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 omitted.
+
```
@@ -738,10 +812,13 @@
root build directory.
--all-toolchains
- Matches all toolchains. When set, if the label pattern does not
- specify an explicit toolchain, labels from all toolchains will be
- matched. When unset, only targets in the default toolchain will
- be matched unless an explicit toolchain in the label is set.
+ 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
@@ -870,10 +947,8 @@
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 and
- printed (potentially with its recursive dependencies, depending on
- the other options). With this flag, both will be printed
- (potentially with both of their recursive dependencies).
+ 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.
@@ -1349,7 +1424,8 @@
```
bundle_root_dir*, bundle_resources_dir*, bundle_executable_dir*,
- bundle_plugins_dir*, deps, data_deps, public_deps, visibility
+ bundle_plugins_dir*, deps, data_deps, public_deps, visibility,
+ product_type
* = required
```
@@ -1399,6 +1475,7 @@
}
create_bundle("${app_name}.app") {
+ product_type = "com.apple.product-type.application"
deps = [
":${app_name}_bundle_executable",
":${app_name}_bundle_info_plist",
@@ -2730,6 +2807,20 @@
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
@@ -2746,7 +2837,7 @@
Example: default_output_extension = ".exe"
- depfile [string]
+ depfile [string with substitutions]
Valid for: compiler tools (optional)
If the tool can write ".d" files, this specifies the name of
@@ -2808,13 +2899,11 @@
]
Example for a linker tool that produces a .dll and a .lib. The
- use of {{output_extension}} rather than hardcoding ".dll"
- allows the extension of the library to be overridden on a
- target-by-target basis, but in this example, it always
- produces a ".lib" import library:
+ use of {{target_output_name}}, {{output_extension}} and
+ {{output_dir}} allows the target to override these values.
outputs = [
- "{{root_out_dir}}/{{target_output_name}}{{output_extension}}",
- "{{root_out_dir}}/{{target_output_name}}.lib",
+ "{{output_dir}}/{{target_output_name}}{{output_extension}}",
+ "{{output_dir}}/{{target_output_name}}.lib",
]
link_output [string with substitutions]
@@ -2827,7 +2916,7 @@
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. If link_output is set but runtime_link_output
+ below for more. If link_output is set but runtime_link_output
is not set, runtime_link_output defaults to link_output.
On Windows, where the tools produce a .dll shared library and
@@ -2937,7 +3026,7 @@
{{target_out_dir}}
The directory of the generated file and output directories,
respectively, for the current target. There is no trailing
- slash.
+ slash. See also {{output_dir}} for linker tools.
Example: "out/base/test"
{{target_output_name}}
@@ -2991,6 +3080,7 @@
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}}
@@ -3020,6 +3110,21 @@
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
@@ -3035,6 +3140,9 @@
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.
@@ -3075,13 +3183,13 @@
tool("solink") {
command = "..."
outputs = [
- "{{root_out_dir}}/{{target_output_name}}{{output_extension}}",
- "{{root_out_dir}}/{{target_output_name}}{{output_extension}}.TOC",
+ "{{output_dir}}/{{target_output_name}}{{output_extension}}",
+ "{{output_dir}}/{{target_output_name}}{{output_extension}}.TOC",
]
link_output =
- "{{root_out_dir}}/{{target_output_name}}{{output_extension}}"
+ "{{output_dir}}/{{target_output_name}}{{output_extension}}"
depend_output =
- "{{root_out_dir}}/{{target_output_name}}{{output_extension}}.TOC"
+ "{{output_dir}}/{{target_output_name}}{{output_extension}}.TOC"
restat = true
}
@@ -3698,6 +3806,42 @@
```
+## **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 occurance 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.
+
+
+```
## **args**: Arguments passed to an action.
```
@@ -4075,9 +4219,16 @@
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. Since GN does not unpack
- static libraries to forward their contents up the dependency chain,
- it is an error for complete static libraries to depend on other static
+ 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.
@@ -4241,7 +4392,7 @@
generated files both in the "outputs" list as well as the "data"
list.
- By convention, directories are be listed with a trailing slash:
+ 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.
@@ -4660,6 +4811,36 @@
```
+## **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"
+ ...
+ }
+
+
+```
## **output_extension**: Value to use for the output's file extension.
```
@@ -4857,6 +5038,18 @@
```
+## **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.
+
+
+```
## **public**: Declare public header files for a target.
```
@@ -5724,6 +5917,10 @@
### **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
@@ -5824,11 +6021,13 @@
** \--args**: Specifies build arguments overrides.
** \--color**: Force colored output.
** \--dotfile**: Override the name of the ".gn" file.
-** \--markdown**: write the output in the Markdown format.
+** \--fail-on-unused-args**: Treat unused build args as fatal errors.
+** \--markdown**: Write help output in the Markdown format.
** \--nocolor**: Force non-colored output.
** -q**: Quiet mode. Don't print output on success.
** \--root**: Explicitly specify source root.
** \--runtime-deps-list-file**: Save runtime dependencies for targets in file.
+** \--script-executable**: Set the executable used to execute scripts.
** \--threads**: Specify number of worker threads.
** \--time**: Outputs a summary of how long everything took.
** \--tracelog**: Writes a Chrome-compatible trace log to the given file.
diff --git a/chromium/tools/gn/example/build/toolchain/BUILD.gn b/chromium/tools/gn/example/build/toolchain/BUILD.gn
index 77e33fecf61..d9457d7eae4 100644
--- a/chromium/tools/gn/example/build/toolchain/BUILD.gn
+++ b/chromium/tools/gn/example/build/toolchain/BUILD.gn
@@ -37,9 +37,10 @@ toolchain("gcc") {
tool("solink") {
soname = "{{target_output_name}}{{output_extension}}" # e.g. "libfoo.so".
+ sofile = "{{output_dir}}/$soname"
rspfile = soname + ".rsp"
- command = "g++ -shared {{ldflags}} -o $soname -Wl,-soname=$soname @$rspfile"
+ 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"
@@ -49,11 +50,15 @@ toolchain("gcc") {
# 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 = [
- soname,
+ sofile,
]
- link_output = soname
- depend_output = soname
+ link_output = sofile
+ depend_output = sofile
output_prefix = "lib"
}
@@ -62,6 +67,7 @@ toolchain("gcc") {
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,
diff --git a/chromium/tools/gn/function_foreach.cc b/chromium/tools/gn/function_foreach.cc
index 549ebe407c1..b74fc186af1 100644
--- a/chromium/tools/gn/function_foreach.cc
+++ b/chromium/tools/gn/function_foreach.cc
@@ -47,7 +47,7 @@ Value RunForEach(Scope* scope,
const FunctionCallNode* function,
const ListNode* args_list,
Err* err) {
- const std::vector<const ParseNode*>& args_vector = args_list->contents();
+ const auto& args_vector = args_list->contents();
if (args_vector.size() != 2) {
*err = Err(function, "Wrong number of arguments to foreach().",
"Expecting exactly two.");
@@ -57,7 +57,8 @@ Value RunForEach(Scope* scope,
// Extract the loop variable.
const IdentifierNode* identifier = args_vector[0]->AsIdentifier();
if (!identifier) {
- *err = Err(args_vector[0], "Expected an identifier for the loop var.");
+ *err =
+ Err(args_vector[0].get(), "Expected an identifier for the loop var.");
return Value();
}
base::StringPiece loop_var(identifier->value().value());
@@ -69,7 +70,7 @@ Value RunForEach(Scope* scope,
if (list_identifier) {
list_value = scope->GetValue(list_identifier->value().value(), true);
if (!list_value) {
- *err = Err(args_vector[1], "Undefined identifier.");
+ *err = Err(args_vector[1].get(), "Undefined identifier.");
return Value();
}
} else {
diff --git a/chromium/tools/gn/function_forward_variables_from.cc b/chromium/tools/gn/function_forward_variables_from.cc
index ee141287715..8f3b90dec71 100644
--- a/chromium/tools/gn/function_forward_variables_from.cc
+++ b/chromium/tools/gn/function_forward_variables_from.cc
@@ -54,6 +54,18 @@ void ForwardValuesFromList(Scope* source,
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
@@ -153,7 +165,7 @@ Value RunForwardVariablesFrom(Scope* scope,
const FunctionCallNode* function,
const ListNode* args_list,
Err* err) {
- const std::vector<const ParseNode*>& args_vector = args_list->contents();
+ 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.");
@@ -166,7 +178,7 @@ Value RunForwardVariablesFrom(Scope* scope,
// to execute the ParseNode and get the value out if it's not an identifer.
const IdentifierNode* identifier = args_vector[0]->AsIdentifier();
if (!identifier) {
- *err = Err(args_vector[0], "Expected an identifier for the scope.");
+ *err = Err(args_vector[0].get(), "Expected an identifier for the scope.");
return Value();
}
diff --git a/chromium/tools/gn/function_forward_variables_from_unittest.cc b/chromium/tools/gn/function_forward_variables_from_unittest.cc
index e5137a48b26..2e6f5a2800c 100644
--- a/chromium/tools/gn/function_forward_variables_from_unittest.cc
+++ b/chromium/tools/gn/function_forward_variables_from_unittest.cc
@@ -8,28 +8,46 @@
TEST(FunctionForwardVariablesFrom, List) {
Scheduler scheduler;
- 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\"])\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");
-
- 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();
+ 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(FunctionForwardVariablesFrom, ListWithExclusion) {
diff --git a/chromium/tools/gn/function_toolchain.cc b/chromium/tools/gn/function_toolchain.cc
index f3344ffdfe8..aaa9b7efaa7 100644
--- a/chromium/tools/gn/function_toolchain.cc
+++ b/chromium/tools/gn/function_toolchain.cc
@@ -194,8 +194,8 @@ bool IsCompilerTool(Toolchain::ToolType type) {
}
bool IsLinkerTool(Toolchain::ToolType type) {
- return type == Toolchain::TYPE_ALINK ||
- type == Toolchain::TYPE_SOLINK ||
+ // "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;
}
@@ -418,6 +418,20 @@ const char kTool_Help[] =
"\n"
" The command to run.\n"
"\n"
+ " default_output_dir [string with substitutions]\n"
+ " Valid for: linker tools\n"
+ "\n"
+ " Default directory name for the output file relative to the\n"
+ " root_build_dir. It can contain other substitution patterns.\n"
+ " This will be the default value for the {{output_dir}} expansion\n"
+ " (discussed below) but will be overridden by the \"output_dir\"\n"
+ " variable in a target, if one is specified.\n"
+ "\n"
+ " GN doesn't do anything with this string other than pass it\n"
+ " along, potentially with target-specific overrides. It is the\n"
+ " tool's job to use the expansion so that the files will be in\n"
+ " the right place.\n"
+ "\n"
" default_output_extension [string]\n"
" Valid for: linker tools\n"
"\n"
@@ -434,7 +448,7 @@ const char kTool_Help[] =
"\n"
" Example: default_output_extension = \".exe\"\n"
"\n"
- " depfile [string]\n"
+ " depfile [string with substitutions]\n"
" Valid for: compiler tools (optional)\n"
"\n"
" If the tool can write \".d\" files, this specifies the name of\n"
@@ -496,14 +510,12 @@ const char kTool_Help[] =
" ]\n"
"\n"
" Example for a linker tool that produces a .dll and a .lib. The\n"
- " use of {{output_extension}} rather than hardcoding \".dll\"\n"
- " allows the extension of the library to be overridden on a\n"
- " target-by-target basis, but in this example, it always\n"
- " produces a \".lib\" import library:\n"
+ " use of {{target_output_name}}, {{output_extension}} and\n"
+ " {{output_dir}} allows the target to override these values.\n"
" outputs = [\n"
- " \"{{root_out_dir}}/{{target_output_name}}"
+ " \"{{output_dir}}/{{target_output_name}}"
"{{output_extension}}\",\n"
- " \"{{root_out_dir}}/{{target_output_name}}.lib\",\n"
+ " \"{{output_dir}}/{{target_output_name}}.lib\",\n"
" ]\n"
"\n"
" link_output [string with substitutions]\n"
@@ -516,7 +528,7 @@ const char kTool_Help[] =
" should match entries in the \"outputs\". If unspecified, the\n"
" first item in the \"outputs\" array will be used for all. See\n"
" \"Separate linking and dependencies for shared libraries\"\n"
- " below for more. If link_output is set but runtime_link_output\n"
+ " below for more. If link_output is set but runtime_link_output\n"
" is not set, runtime_link_output defaults to link_output.\n"
"\n"
" On Windows, where the tools produce a .dll shared library and\n"
@@ -624,7 +636,7 @@ const char kTool_Help[] =
" {{target_out_dir}}\n"
" The directory of the generated file and output directories,\n"
" respectively, for the current target. There is no trailing\n"
- " slash.\n"
+ " slash. See also {{output_dir}} for linker tools.\n"
" Example: \"out/base/test\"\n"
"\n"
" {{target_output_name}}\n"
@@ -678,6 +690,7 @@ const char kTool_Help[] =
" Example: \"gen/base/test\"\n"
"\n"
" Linker tools have multiple inputs and (potentially) multiple outputs\n"
+ " The static library tool (\"alink\") is not considered a linker tool.\n"
" The following expansions are available:\n"
"\n"
" {{inputs}}\n"
@@ -707,6 +720,21 @@ const char kTool_Help[] =
"\n"
" Example: \"-lfoo -lbar\"\n"
"\n"
+ " {{output_dir}}\n"
+ " The value of the \"output_dir\" variable in the target, or the\n"
+ " the value of the \"default_output_dir\" value in the tool if the\n"
+ " target does not override the output directory. This will be\n"
+ " relative to the root_build_dir and will not end in a slash.\n"
+ " Will be \".\" for output to the root_build_dir.\n"
+ "\n"
+ " This is subtly different than {{target_out_dir}} which is\n"
+ " defined by GN based on the target's path and not overridable.\n"
+ " {{output_dir}} is for the final output, {{target_out_dir}} is\n"
+ " generally for object files and other outputs.\n"
+ "\n"
+ " Usually {{output_dir}} would be defined in terms of either\n"
+ " {{target_out_dir}} or {{root_out_dir}}\n"
+ "\n"
" {{output_extension}}\n"
" The value of the \"output_extension\" variable in the target,\n"
" or the value of the \"default_output_extension\" value in the\n"
@@ -722,6 +750,9 @@ const char kTool_Help[] =
" These should generally be treated the same as libs by your tool.\n"
" Example: \"libfoo.so libbar.so\"\n"
"\n"
+ " The static library (\"alink\") tool allows {{arflags}} plus the common\n"
+ " tool substitutions.\n"
+ "\n"
" The copy tool allows the common compiler/linker substitutions, plus\n"
" {{source}} which is the source of the copy. The stamp tool allows\n"
" only the common tool substitutions.\n"
@@ -759,14 +790,14 @@ const char kTool_Help[] =
" tool(\"solink\") {\n"
" command = \"...\"\n"
" outputs = [\n"
- " \"{{root_out_dir}}/{{target_output_name}}{{output_extension}}\",\n"
- " \"{{root_out_dir}}/{{target_output_name}}"
+ " \"{{output_dir}}/{{target_output_name}}{{output_extension}}\",\n"
+ " \"{{output_dir}}/{{target_output_name}}"
"{{output_extension}}.TOC\",\n"
" ]\n"
" link_output =\n"
- " \"{{root_out_dir}}/{{target_output_name}}{{output_extension}}\"\n"
+ " \"{{output_dir}}/{{target_output_name}}{{output_extension}}\"\n"
" depend_output =\n"
- " \"{{root_out_dir}}/{{target_output_name}}"
+ " \"{{output_dir}}/{{target_output_name}}"
"{{output_extension}}.TOC\"\n"
" restat = true\n"
" }\n"
@@ -832,6 +863,10 @@ Value RunTool(Scope* scope,
} 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;
@@ -866,6 +901,8 @@ Value RunTool(Scope* scope,
tool.get(), &Tool::set_runtime_link_output, 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(),
diff --git a/chromium/tools/gn/functions.cc b/chromium/tools/gn/functions.cc
index f6d405d0a56..af413d655b3 100644
--- a/chromium/tools/gn/functions.cc
+++ b/chromium/tools/gn/functions.cc
@@ -464,7 +464,7 @@ Value RunDefined(Scope* scope,
const FunctionCallNode* function,
const ListNode* args_list,
Err* err) {
- const std::vector<const ParseNode*>& args_vector = args_list->contents();
+ const auto& args_vector = args_list->contents();
if (args_vector.size() != 1) {
*err = Err(function, "Wrong number of arguments to defined().",
"Expecting exactly one.");
diff --git a/chromium/tools/gn/functions_target.cc b/chromium/tools/gn/functions_target.cc
index 7ec5a50dd26..a5f55741296 100644
--- a/chromium/tools/gn/functions_target.cc
+++ b/chromium/tools/gn/functions_target.cc
@@ -331,7 +331,8 @@ const char kCreateBundle_Help[] =
"Variables\n"
"\n"
" bundle_root_dir*, bundle_resources_dir*, bundle_executable_dir*,\n"
- " bundle_plugins_dir*, deps, data_deps, public_deps, visibility\n"
+ " bundle_plugins_dir*, deps, data_deps, public_deps, visibility,\n"
+ " product_type\n"
" * = required\n"
"\n"
"Example\n"
@@ -378,6 +379,7 @@ const char kCreateBundle_Help[] =
" }\n"
"\n"
" create_bundle(\"${app_name}.app\") {\n"
+ " product_type = \"com.apple.product-type.application\"\n"
" deps = [\n"
" \":${app_name}_bundle_executable\",\n"
" \":${app_name}_bundle_info_plist\",\n"
@@ -654,6 +656,7 @@ const char kStaticLibrary_Help[] =
"\n"
"Variables\n"
"\n"
+ "complete_static_lib\n"
CONFIG_VALUES_VARS_HELP
DEPS_VARS
DEPENDENT_CONFIG_VARS
diff --git a/chromium/tools/gn/gn.gyp b/chromium/tools/gn/gn.gyp
index 79f83a719c8..8428948872d 100644
--- a/chromium/tools/gn/gn.gyp
+++ b/chromium/tools/gn/gn.gyp
@@ -146,6 +146,8 @@
'path_output.h',
'pattern.cc',
'pattern.h',
+ 'qt_creator_writer.cc',
+ 'qt_creator_writer.h',
'runtime_deps.cc',
'runtime_deps.h',
'scheduler.cc',
@@ -207,6 +209,10 @@
'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',
],
diff --git a/chromium/tools/gn/gn_main.cc b/chromium/tools/gn/gn_main.cc
index 135ed561a9c..245270ee52d 100644
--- a/chromium/tools/gn/gn_main.cc
+++ b/chromium/tools/gn/gn_main.cc
@@ -73,9 +73,12 @@ int main(int argc, char** argv) {
if (found_command != command_map.end()) {
retval = found_command->second.runner(args);
} else {
- Err(Location(),
- "Command \"" + command + "\" unknown.").PrintToStdout();
- commands::RunHelp(std::vector<std::string>());
+ 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;
}
diff --git a/chromium/tools/gn/group_target_generator_unittest.cc b/chromium/tools/gn/group_target_generator_unittest.cc
deleted file mode 100644
index 3b0c8244368..00000000000
--- a/chromium/tools/gn/group_target_generator_unittest.cc
+++ /dev/null
@@ -1,46 +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/group_target_generator.h"
-#include "tools/gn/scheduler.h"
-#include "tools/gn/test_with_scope.h"
-
-namespace {
-
-// Returns true on success, false if write_file signaled an error.
-bool ParseWriteRuntimeDeps(Scope* scope, const std::string& value) {
- TestParseInput input(
- "group(\"foo\") { write_runtime_deps = " + value + "}");
- if (input.has_error())
- return false;
-
- Err err;
- input.parsed()->Execute(scope, &err);
- return !err.has_error();
-}
-
-} // namespace
-
-
-// Tests that actions can't have output substitutions.
-TEST(GroupTargetGenerator, WriteRuntimeDeps) {
- Scheduler scheduler;
- TestWithScope setup;
- Scope::ItemVector items_;
- setup.scope()->set_item_collector(&items_);
-
- // Should refuse to write files outside of the output dir.
- EXPECT_FALSE(ParseWriteRuntimeDeps(setup.scope(), "\"//foo.txt\""));
- EXPECT_EQ(0U, scheduler.GetWriteRuntimeDepsTargets().size());
-
- // Should fail for garbage inputs.
- EXPECT_FALSE(ParseWriteRuntimeDeps(setup.scope(), "0"));
- EXPECT_EQ(0U, scheduler.GetWriteRuntimeDepsTargets().size());
-
- // Should be able to write inside the out dir.
- EXPECT_TRUE(ParseWriteRuntimeDeps(setup.scope(), "\"//out/Debug/foo.txt\""));
- EXPECT_EQ(1U, scheduler.GetWriteRuntimeDepsTargets().size());
-}
-
diff --git a/chromium/tools/gn/import_manager.cc b/chromium/tools/gn/import_manager.cc
index 83cc09020cd..01c88b5a68c 100644
--- a/chromium/tools/gn/import_manager.cc
+++ b/chromium/tools/gn/import_manager.cc
@@ -4,9 +4,7 @@
#include "tools/gn/import_manager.h"
-#include <memory>
-
-#include "base/stl_util.h"
+#include "tools/gn/err.h"
#include "tools/gn/parse_tree.h"
#include "tools/gn/scheduler.h"
#include "tools/gn/scope_per_file_provider.h"
@@ -14,10 +12,10 @@
namespace {
// Returns a newly-allocated scope on success, null on failure.
-Scope* UncachedImport(const Settings* settings,
- const SourceFile& file,
- const ParseNode* node_for_err,
- Err* err) {
+std::unique_ptr<Scope> UncachedImport(const Settings* settings,
+ const SourceFile& file,
+ const ParseNode* node_for_err,
+ Err* err) {
const ParseNode* node = g_scheduler->input_file_manager()->SyncLoadFile(
node_for_err->GetRange(), settings->build_settings(), file, err);
if (!node)
@@ -33,20 +31,39 @@ Scope* UncachedImport(const Settings* settings,
scope->SetProcessingImport();
node->Execute(scope.get(), err);
- if (err->has_error())
+ 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.release();
+ return scope;
}
-} // namesapce
+} // namespace
+
+struct ImportManager::ImportInfo {
+ ImportInfo() {}
+ ~ImportInfo() {}
+
+ // 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() {
}
ImportManager::~ImportManager() {
- STLDeleteContainerPairSecondPointers(imports_.begin(), imports_.end());
}
bool ImportManager::DoImport(const SourceFile& file,
@@ -55,39 +72,50 @@ bool ImportManager::DoImport(const SourceFile& file,
Err* err) {
// See if we have a cached import, but be careful to actually do the scope
// copying outside of the lock.
- const Scope* imported_scope = nullptr;
+ ImportInfo* import_info = nullptr;
{
- base::AutoLock lock(lock_);
- ImportMap::const_iterator found = imports_.find(file);
- if (found != imports_.end())
- imported_scope = found->second;
+ base::AutoLock lock(imports_lock_);
+ std::unique_ptr<ImportInfo>& info_ptr = imports_[file];
+ if (!info_ptr)
+ info_ptr.reset(new ImportInfo);
+
+ // Promote the ImportInfo to outside of the imports lock.
+ import_info = info_ptr.get();
}
- if (!imported_scope) {
- // Do a new import of the file.
- imported_scope = UncachedImport(scope->settings(), file,
- node_for_err, err);
- if (!imported_scope)
- return false;
-
- // We loaded the file outside the lock. This means that there could be a
- // race and the file was already loaded on a background thread. Recover
- // from this and use the existing one if that happens.
- {
- base::AutoLock lock(lock_);
- ImportMap::const_iterator found = imports_.find(file);
- if (found != imports_.end()) {
- delete imported_scope;
- imported_scope = found->second;
- } else {
- imports_[file] = imported_scope;
+ // 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::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;
}
}
+
+ // 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.
- return imported_scope->NonRecursiveMergeTo(scope, options, node_for_err,
- "import", err);
+ 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
index 70aeee727c5..f371520df8c 100644
--- a/chromium/tools/gn/import_manager.h
+++ b/chromium/tools/gn/import_manager.h
@@ -6,6 +6,8 @@
#define TOOLS_GN_IMPORT_MANAGER_H_
#include <map>
+#include <memory>
+#include <vector>
#include "base/macros.h"
#include "base/synchronization/lock.h"
@@ -29,11 +31,16 @@ class ImportManager {
Scope* scope,
Err* err);
+ std::vector<SourceFile> GetImportedFiles() const;
+
private:
- base::Lock lock_;
+ struct ImportInfo;
+
+ // Protects access to imports_. Do not hold when actually executing imports.
+ base::Lock imports_lock_;
// Owning pointers to the scopes.
- typedef std::map<SourceFile, const Scope*> ImportMap;
+ typedef std::map<SourceFile, std::unique_ptr<ImportInfo>> ImportMap;
ImportMap imports_;
DISALLOW_COPY_AND_ASSIGN(ImportManager);
diff --git a/chromium/tools/gn/input_file_manager.cc b/chromium/tools/gn/input_file_manager.cc
index a3e64606b0d..36c0bf3c264 100644
--- a/chromium/tools/gn/input_file_manager.cc
+++ b/chromium/tools/gn/input_file_manager.cc
@@ -94,9 +94,6 @@ InputFileManager::InputFileManager() {
InputFileManager::~InputFileManager() {
// Should be single-threaded by now.
- STLDeleteContainerPairSecondPointers(input_files_.begin(),
- input_files_.end());
- STLDeleteContainerPointers(dynamic_inputs_.begin(), dynamic_inputs_.end());
}
bool InputFileManager::AsyncLoadFile(const LocationRange& origin,
@@ -114,18 +111,18 @@ bool InputFileManager::AsyncLoadFile(const LocationRange& origin,
InputFileMap::const_iterator found = input_files_.find(file_name);
if (found == input_files_.end()) {
// New file, schedule load.
- InputFileData* data = new InputFileData(file_name);
+ std::unique_ptr<InputFileData> data(new InputFileData(file_name));
data->scheduled_callbacks.push_back(callback);
- input_files_[file_name] = data;
-
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;
+ InputFileData* data = found->second.get();
// Prevent mixing async and sync loads. See SyncLoadFile for discussion.
if (data->sync_invocation) {
@@ -167,16 +164,17 @@ const ParseNode* InputFileManager::SyncLoadFile(
InputFileMap::iterator found = input_files_.find(file_name);
if (found == input_files_.end()) {
// Haven't seen this file yet, start loading right now.
- data = new InputFileData(file_name);
+ std::unique_ptr<InputFileData> new_data(new InputFileData(file_name));
+ data = new_data.get();
data->sync_invocation = true;
- input_files_[file_name] = data;
+ 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;
+ data = found->second.get();
if (!data->sync_invocation) {
// Don't allow mixing of sync and async loads. If an async load is
@@ -231,14 +229,14 @@ void InputFileManager::AddDynamicInput(
InputFile** file,
std::vector<Token>** tokens,
std::unique_ptr<ParseNode>** parse_root) {
- InputFileData* data = new InputFileData(name);
- {
- base::AutoLock lock(lock_);
- dynamic_inputs_.push_back(data);
- }
+ std::unique_ptr<InputFileData> data(new 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 {
@@ -286,7 +284,7 @@ bool InputFileManager::LoadFile(const LocationRange& origin,
base::AutoLock lock(lock_);
DCHECK(input_files_.find(name) != input_files_.end());
- InputFileData* data = input_files_[name];
+ InputFileData* data = input_files_[name].get();
data->loaded = true;
if (success) {
data->tokens.swap(tokens);
diff --git a/chromium/tools/gn/input_file_manager.h b/chromium/tools/gn/input_file_manager.h
index ba055e219c5..dd166048e9b 100644
--- a/chromium/tools/gn/input_file_manager.h
+++ b/chromium/tools/gn/input_file_manager.h
@@ -137,7 +137,8 @@ class InputFileManager : public base::RefCountedThreadSafe<InputFileManager> {
mutable base::Lock lock_;
// Maps repo-relative filenames to the corresponding owned pointer.
- typedef base::hash_map<SourceFile, InputFileData*> InputFileMap;
+ typedef base::hash_map<SourceFile, std::unique_ptr<InputFileData>>
+ InputFileMap;
InputFileMap input_files_;
// Tracks all dynamic inputs. The data are holders for memory management
@@ -146,9 +147,7 @@ class InputFileManager : public base::RefCountedThreadSafe<InputFileManager> {
// charge of the threadsafety requirements.
//
// See AddDynamicInput().
- //
- // Owning pointers.
- std::vector<InputFileData*> dynamic_inputs_;
+ std::vector<std::unique_ptr<InputFileData>> dynamic_inputs_;
DISALLOW_COPY_AND_ASSIGN(InputFileManager);
};
diff --git a/chromium/tools/gn/loader.cc b/chromium/tools/gn/loader.cc
index 9061be82a0b..e3165b9c6f7 100644
--- a/chromium/tools/gn/loader.cc
+++ b/chromium/tools/gn/loader.cc
@@ -7,7 +7,6 @@
#include "base/bind.h"
#include "base/memory/ptr_util.h"
#include "base/message_loop/message_loop.h"
-#include "base/stl_util.h"
#include "tools/gn/build_settings.h"
#include "tools/gn/err.h"
#include "tools/gn/filesystem_utils.h"
@@ -106,8 +105,6 @@ LoaderImpl::LoaderImpl(const BuildSettings* build_settings)
}
LoaderImpl::~LoaderImpl() {
- STLDeleteContainerPairSecondPointers(toolchain_records_.begin(),
- toolchain_records_.end());
}
void LoaderImpl::Load(const SourceFile& file,
@@ -120,13 +117,14 @@ void LoaderImpl::Load(const SourceFile& file,
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 intial load
+ // Nothing loaded, need to load the default build config. The initial load
// should not specify a toolchain.
DCHECK(toolchain_name.is_null());
- ToolchainRecord* record =
- new ToolchainRecord(build_settings_, Label(), Label());
- toolchain_records_[Label()] = record;
+ std::unique_ptr<ToolchainRecord> new_record(
+ new 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
@@ -135,22 +133,24 @@ void LoaderImpl::Load(const SourceFile& file,
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_];
+ record = toolchain_records_[default_toolchain_label_].get();
else
- record = toolchain_records_[toolchain_name];
+ record = toolchain_records_[toolchain_name].get();
if (!record) {
DCHECK(!default_toolchain_label_.is_null());
// No reference to this toolchain found yet, make one.
- record = new ToolchainRecord(build_settings_, toolchain_name,
- default_toolchain_label_);
- toolchain_records_[toolchain_name] = record;
+ std::unique_ptr<ToolchainRecord> new_record(new 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_);
@@ -163,12 +163,13 @@ void LoaderImpl::Load(const SourceFile& file,
}
void LoaderImpl::ToolchainLoaded(const Toolchain* toolchain) {
- ToolchainRecord* record = toolchain_records_[toolchain->label()];
+ ToolchainRecord* record = toolchain_records_[toolchain->label()].get();
if (!record) {
DCHECK(!default_toolchain_label_.is_null());
- record = new ToolchainRecord(build_settings_, toolchain->label(),
- default_toolchain_label_);
- toolchain_records_[toolchain->label()] = record;
+ std::unique_ptr<ToolchainRecord> new_record(new 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;
@@ -210,7 +211,7 @@ void LoaderImpl::ScheduleLoadFile(const Settings* settings,
pending_loads_++;
if (!AsyncLoadFile(origin, settings->build_settings(), file,
base::Bind(&LoaderImpl::BackgroundLoadFile, this,
- settings, file),
+ settings, file, origin),
&err)) {
g_scheduler->FailWithError(err);
DecrementPendingLoads();
@@ -234,6 +235,7 @@ void LoaderImpl::ScheduleLoadBuildConfig(
void LoaderImpl::BackgroundLoadFile(const Settings* settings,
const SourceFile& file_name,
+ const LocationRange& origin,
const ParseNode* root) {
if (!root) {
main_loop_->PostTask(FROM_HERE,
@@ -259,11 +261,15 @@ void LoaderImpl::BackgroundLoadFile(const Settings* settings,
Err err;
root->Execute(&our_scope, &err);
- if (err.has_error())
- g_scheduler->FailWithError(err);
+ if (!err.has_error())
+ our_scope.CheckForUnusedVars(&err);
- if (!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) {
@@ -356,8 +362,10 @@ void LoaderImpl::DidLoadBuildConfig(const Label& label) {
CHECK(empty_label != toolchain_records_.end());
// Fix up the toolchain record.
- record = empty_label->second;
- toolchain_records_[label] = 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.
@@ -383,7 +391,7 @@ void LoaderImpl::DidLoadBuildConfig(const Label& label) {
}
}
} else {
- record = found_toolchain->second;
+ record = found_toolchain->second.get();
}
DCHECK(!record->is_config_loaded);
diff --git a/chromium/tools/gn/loader.h b/chromium/tools/gn/loader.h
index 3d61fe4b4e8..a610835aa39 100644
--- a/chromium/tools/gn/loader.h
+++ b/chromium/tools/gn/loader.h
@@ -6,6 +6,7 @@
#define TOOLS_GN_LOADER_H_
#include <map>
+#include <memory>
#include <set>
#include "base/callback.h"
@@ -128,6 +129,7 @@ class LoaderImpl : public Loader {
// input file manager.
void BackgroundLoadFile(const Settings* settings,
const SourceFile& file_name,
+ const LocationRange& origin,
const ParseNode* root);
void BackgroundLoadBuildConfig(
Settings* settings,
@@ -173,8 +175,7 @@ class LoaderImpl : public Loader {
Label default_toolchain_label_;
// Records for the build config file loads.
- // Owning pointers.
- typedef std::map<Label, ToolchainRecord*> ToolchainRecordMap;
+ typedef std::map<Label, std::unique_ptr<ToolchainRecord>> ToolchainRecordMap;
ToolchainRecordMap toolchain_records_;
};
diff --git a/chromium/tools/gn/location.h b/chromium/tools/gn/location.h
index 44d1a6fe68f..647c6f71227 100644
--- a/chromium/tools/gn/location.h
+++ b/chromium/tools/gn/location.h
@@ -19,6 +19,7 @@ class Location {
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;
@@ -45,6 +46,10 @@ class LocationRange {
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;
diff --git a/chromium/tools/gn/misc/emacs/gn-mode.el b/chromium/tools/gn/misc/emacs/gn-mode.el
index 66822907c67..435e872c9ad 100644
--- a/chromium/tools/gn/misc/emacs/gn-mode.el
+++ b/chromium/tools/gn/misc/emacs/gn-mode.el
@@ -36,6 +36,11 @@
: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
@@ -123,6 +128,20 @@ variable name or the '{{' and '}}' which surround it."
;; 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)."
diff --git a/chromium/tools/gn/ninja_binary_target_writer.cc b/chromium/tools/gn/ninja_binary_target_writer.cc
index eaae098ef71..30658f21ed1 100644
--- a/chromium/tools/gn/ninja_binary_target_writer.cc
+++ b/chromium/tools/gn/ninja_binary_target_writer.cc
@@ -51,12 +51,6 @@ namespace {
EscapeOptions GetFlagOptions() {
EscapeOptions opts;
opts.mode = ESCAPE_NINJA_COMMAND;
-
- // Some flag strings are actually multiple flags that expect to be just
- // added to the command line. We assume that quoting is done by the
- // buildfiles if it wants such things quoted.
- opts.inhibit_quoting = true;
-
return opts;
}
@@ -109,14 +103,15 @@ const char* GetPCHLangSuffixForToolType(Toolchain::ToolType type) {
}
}
-std::string GetWindowsPCHObjectExtension(Toolchain::ToolType tool_type) {
+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.o ->
- // obj/foo/target_name.precompile.cc.o
+ // obj/foo/target_name.precompile.obj ->
+ // obj/foo/target_name.precompile.cc.obj
result += lang_suffix;
- result += ".o";
+ result += obj_extension;
return result;
}
@@ -188,7 +183,8 @@ void GetPCHOutputFiles(const Target* target,
Tool::PrecompiledHeaderType header_type = tool->precompiled_header_type();
switch (header_type) {
case Tool::PCH_MSVC:
- output_extension = GetWindowsPCHObjectExtension(tool_type);
+ output_extension = GetWindowsPCHObjectExtension(
+ tool_type, output_value.substr(extension_offset - 1));
break;
case Tool::PCH_GCC:
output_extension = GetGCCPCHOutputExtension(tool_type);
@@ -627,7 +623,7 @@ void NinjaBinaryTargetWriter::WriteSources(
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.o (a CXX PCH file) as a dep
+ // 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
@@ -637,9 +633,13 @@ void NinjaBinaryTargetWriter::WriteSources(
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_extension = GetWindowsPCHObjectExtension(
+ tool_type, output_value.substr(extension_offset - 1));
} else if (tool->precompiled_header_type() == Tool::PCH_GCC) {
output_extension = GetGCCPCHOutputExtension(tool_type);
}
@@ -785,8 +785,13 @@ void NinjaBinaryTargetWriter::WriteLinkerStuff(
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;
}
- WriteOutputExtension();
+ WriteOutputSubstitutions();
WriteSolibs(solibs);
}
@@ -795,9 +800,8 @@ void NinjaBinaryTargetWriter::WriteLinkerFlags(
out_ << " ldflags =";
// First the ldflags from the target and its config.
- EscapeOptions flag_options = GetFlagOptions();
RecursiveTargetConfigStringsToStream(target_, &ConfigValues::ldflags,
- flag_options, out_);
+ GetFlagOptions(), out_);
// Followed by library search paths that have been recursively pushed
// through the dependency tree.
@@ -853,11 +857,15 @@ void NinjaBinaryTargetWriter::WriteLibs() {
out_ << std::endl;
}
-void NinjaBinaryTargetWriter::WriteOutputExtension() {
+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(
@@ -930,7 +938,14 @@ void NinjaBinaryTargetWriter::ClassifyDependency(
// don't link at all.
bool can_link_libs = target_->IsFinal();
- if (dep->output_type() == Target::SOURCE_SET) {
+ 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
@@ -946,6 +961,8 @@ void NinjaBinaryTargetWriter::ClassifyDependency(
// 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 {
diff --git a/chromium/tools/gn/ninja_binary_target_writer.h b/chromium/tools/gn/ninja_binary_target_writer.h
index db2b15d12af..1876486ff1f 100644
--- a/chromium/tools/gn/ninja_binary_target_writer.h
+++ b/chromium/tools/gn/ninja_binary_target_writer.h
@@ -99,7 +99,7 @@ class NinjaBinaryTargetWriter : public NinjaTargetWriter {
const std::vector<SourceFile>& other_files);
void WriteLinkerFlags(const SourceFile* optional_def_file);
void WriteLibs();
- void WriteOutputExtension();
+ void WriteOutputSubstitutions();
void WriteSolibs(const std::vector<OutputFile>& solibs);
// Writes the stamp line for a source set. These are not linked.
diff --git a/chromium/tools/gn/ninja_binary_target_writer_unittest.cc b/chromium/tools/gn/ninja_binary_target_writer_unittest.cc
index 1e02446dfe3..f2297fbf206 100644
--- a/chromium/tools/gn/ninja_binary_target_writer_unittest.cc
+++ b/chromium/tools/gn/ninja_binary_target_writer_unittest.cc
@@ -82,7 +82,8 @@ TEST(NinjaBinaryTargetWriter, SourceSet) {
"|| obj/foo/bar.stamp\n"
" ldflags =\n"
" libs =\n"
- " output_extension = .so\n";
+ " output_extension = .so\n"
+ " output_dir = \n";
std::string out_str = out.str();
EXPECT_EQ(expected, out_str);
}
@@ -110,7 +111,9 @@ TEST(NinjaBinaryTargetWriter, SourceSet) {
// 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"
- " output_extension = \n";
+ " arflags =\n"
+ " output_extension = \n"
+ " output_dir = \n";
std::string out_str = out.str();
EXPECT_EQ(expected, out_str);
}
@@ -136,15 +139,124 @@ TEST(NinjaBinaryTargetWriter, SourceSet) {
"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"
- " output_extension = \n";
+ " arflags =\n"
+ " output_extension = \n"
+ " output_dir = \n";
std::string out_str = out.str();
EXPECT_EQ(expected, out_str);
}
}
-// This tests that output extension overrides apply, and input dependencies
-// are applied.
-TEST(NinjaBinaryTargetWriter, ProductExtensionAndInputDeps) {
+TEST(NinjaBinaryTargetWriter, 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(NinjaBinaryTargetWriter, 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(NinjaBinaryTargetWriter, OutputExtensionAndInputDeps) {
TestWithScope setup;
Err err;
@@ -157,10 +269,11 @@ TEST(NinjaBinaryTargetWriter, ProductExtensionAndInputDeps) {
action.SetToolchain(setup.toolchain());
ASSERT_TRUE(action.OnResolved(&err));
- // A shared library w/ the product_extension set to a custom value.
+ // 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));
@@ -192,7 +305,8 @@ TEST(NinjaBinaryTargetWriter, ProductExtensionAndInputDeps) {
"obj/foo/libshlib.input2.o || obj/foo/action.stamp\n"
" ldflags =\n"
" libs =\n"
- " output_extension = .so.6\n";
+ " output_extension = .so.6\n"
+ " output_dir = foo\n";
std::string out_str = out.str();
EXPECT_EQ(expected, out_str);
@@ -229,19 +343,20 @@ TEST(NinjaBinaryTargetWriter, LibsAndLibDirs) {
"build ./libshlib.so: solink | ../../foo/lib1.a\n"
" ldflags = -L../../foo/bar\n"
" libs = ../../foo/lib1.a -lfoo\n"
- " output_extension = .so\n";
+ " output_extension = .so\n"
+ " output_dir = \n";
std::string out_str = out.str();
EXPECT_EQ(expected, out_str);
}
-TEST(NinjaBinaryTargetWriter, EmptyProductExtension) {
+TEST(NinjaBinaryTargetWriter, EmptyOutputExtension) {
TestWithScope setup;
Err err;
setup.build_settings()->SetBuildDir(SourceDir("//out/Debug/"));
- // This test is the same as ProductExtension, except that we call
+ // 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"));
@@ -274,7 +389,8 @@ TEST(NinjaBinaryTargetWriter, EmptyProductExtension) {
"obj/foo/shlib.input2.o\n"
" ldflags =\n"
" libs =\n"
- " output_extension = \n";
+ " output_extension = \n"
+ " output_dir = \n";
std::string out_str = out.str();
EXPECT_EQ(expected, out_str);
@@ -357,7 +473,8 @@ TEST(NinjaBinaryTargetWriter, SourceSetDataDeps) {
"obj/foo/inter.stamp\n"
" ldflags =\n"
" libs =\n"
- " output_extension = \n";
+ " output_extension = \n"
+ " output_dir = \n";
EXPECT_EQ(final_expected, final_out.str());
}
@@ -392,7 +509,8 @@ TEST(NinjaBinaryTargetWriter, SharedLibraryModuleDefinitionFile) {
"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_extension = .so\n"
+ " output_dir = \n";
EXPECT_EQ(expected, out.str());
}
@@ -427,7 +545,8 @@ TEST(NinjaBinaryTargetWriter, LoadableModule) {
"build ./libbar.so: solink_module obj/foo/libbar.sources.o\n"
" ldflags =\n"
" libs =\n"
- " output_extension = .so\n";
+ " output_extension = .so\n"
+ " output_dir = \n";
EXPECT_EQ(loadable_expected, out.str());
// Final target.
@@ -458,7 +577,8 @@ TEST(NinjaBinaryTargetWriter, LoadableModule) {
"build ./exe: link obj/foo/exe.final.o || ./libbar.so\n"
" ldflags =\n"
" libs =\n"
- " output_extension = \n";
+ " output_extension = \n"
+ " output_dir = \n";
EXPECT_EQ(final_expected, final_out.str());
}
diff --git a/chromium/tools/gn/ninja_build_writer.cc b/chromium/tools/gn/ninja_build_writer.cc
index d28969084ee..2cbb245c0dd 100644
--- a/chromium/tools/gn/ninja_build_writer.cc
+++ b/chromium/tools/gn/ninja_build_writer.cc
@@ -8,6 +8,7 @@
#include <fstream>
#include <map>
+#include <sstream>
#include "base/command_line.h"
#include "base/files/file_util.h"
@@ -33,6 +34,16 @@
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) {
base::FilePath executable;
PathService::Get(base::FILE_EXE, &executable);
@@ -79,35 +90,6 @@ std::string GetSelfInvocationCommand(const BuildSettings* build_settings) {
#endif
}
-OutputFile GetTargetOutputFile(const Target* target) {
- OutputFile result(target->dependency_output_file());
-
- // The output files may have leading "./" so normalize those away.
- NormalizePath(&result.value());
- return result;
-}
-
-bool HasOutputIdenticalToLabel(const Target* target,
- const std::string& short_name) {
- if (target->output_type() != Target::ACTION &&
- target->output_type() != Target::ACTION_FOREACH)
- return false;
-
- // Rather than convert all outputs to be relative to the build directory
- // and then compare to the short name, convert the short name to look like a
- // file in the output directory since this is only one conversion.
- SourceFile short_name_as_source_file(
- target->settings()->build_settings()->build_dir().value() + short_name);
-
- std::vector<SourceFile> outputs_as_source;
- target->action_values().GetOutputsAsSourceFiles(target, &outputs_as_source);
- for (const SourceFile& output_as_source : outputs_as_source) {
- if (output_as_source == short_name_as_source_file)
- return true;
- }
- return false;
-}
-
// 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,
@@ -178,29 +160,36 @@ bool NinjaBuildWriter::RunAndWriteFile(
Err* err) {
ScopedTrace trace(TraceItem::TRACE_FILE_WRITE, "build.ninja");
- base::FilePath ninja_file(build_settings->GetFullPath(
- SourceFile(build_settings->build_dir().value() + "build.ninja")));
- base::CreateDirectory(ninja_file.DirName());
+ std::stringstream file;
+ std::stringstream depfile;
+ NinjaBuildWriter gen(build_settings, all_settings, default_toolchain,
+ default_toolchain_targets, file, depfile);
+ if (!gen.Run(err))
+ return false;
- std::ofstream file;
- file.open(FilePathToUTF8(ninja_file).c_str(),
- std::ios_base::out | std::ios_base::binary);
- if (file.fail()) {
- *err = Err(Location(), "Couldn't open build.ninja for writing");
+ // 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;
- }
- std::ofstream depfile;
- depfile.open((FilePathToUTF8(ninja_file) + ".d").c_str(),
- std::ios_base::out | std::ios_base::binary);
- if (depfile.fail()) {
- *err = Err(Location(), "Couldn't open depfile for writing");
+ // 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;
- }
- NinjaBuildWriter gen(build_settings, all_settings, default_toolchain,
- default_toolchain_targets, file, depfile);
- return gen.Run(err);
+ return true;
}
void NinjaBuildWriter::WriteNinjaRules() {
@@ -251,149 +240,166 @@ void NinjaBuildWriter::WriteSubninjas() {
}
bool NinjaBuildWriter::WritePhonyAndAllRules(Err* err) {
- std::string all_rules;
-
// 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.
- std::set<std::string> written_rules;
+ base::hash_set<std::string> written_rules;
written_rules.insert("all");
- // Write phony rules for all uniquely-named targets in the default toolchain.
- // Don't do other toolchains or we'll get naming conflicts, and if the name
- // isn't unique, also skip it. The exception is for the toplevel targets
- // which we also find.
- std::map<std::string, int> small_name_count;
- std::map<std::string, int> exe_count;
+ // Set if we encounter a target named "//:default".
+ bool default_target_exists = false;
+
+ // Targets in the root build file.
std::vector<const Target*> toplevel_targets;
- base::hash_set<std::string> target_files;
- for (const auto& target : default_toolchain_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;
+
+ for (const Target* target : default_toolchain_targets_) {
const Label& label = target->label();
- small_name_count[label.name()]++;
+ const std::string& short_name = label.name();
+
+ if (label.dir().value() == "//" && label.name() == "default")
+ default_target_exists = true;
+
+ // 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;
+ }
- // Look for targets with a name of the form
- // dir = "//foo/", name = "foo"
- // i.e. where the target name matches the top level directory. We will
- // always write phony rules for these even if there is another target with
- // the same short name.
+ // Find targets in "important" directories.
const std::string& dir_string = label.dir().value();
- if (dir_string.size() == label.name().size() + 3 && // Size matches.
+ 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_targets.push_back(target);
-
- // Look for executables; later we will generate phony rules for them
- // even if there are non-executable targets with the same name.
- if (target->output_type() == Target::EXECUTABLE)
- exe_count[label.name()]++;
-
- // Add the files to the list of generated targets so we don't write phony
- // rules that collide.
- std::string target_file(target->dependency_output_file().value());
- NormalizePath(&target_file);
- written_rules.insert(target_file);
- }
+ dir_string.compare(2, label.name().size(), label.name()) == 0) {
+ toplevel_dir_targets.push_back(target);
+ }
- for (const auto& target : default_toolchain_targets_) {
- const Label& label = target->label();
+ // 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()) {
- if (!target_files.insert(output.value()).second) {
+ // 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();
- OutputFile target_file = GetTargetOutputFile(target);
// 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);
- WritePhonyRule(target, target_file, long_name, &written_rules);
+ 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());
+ 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())
- WritePhonyRule(target, target_file, medium_name, &written_rules);
- }
-
- // Write short names for ones which are either completely unique or there
- // at least only one of them in the default toolchain that is an exe.
- if (small_name_count[label.name()] == 1 ||
- (target->output_type() == Target::EXECUTABLE &&
- exe_count[label.name()] == 1)) {
- // It's reasonable to generate output files in the root build directory
- // with the same name as the target. Don't generate phony rules for
- // these cases.
- //
- // All of this does not do the general checking of all target's outputs
- // which may theoretically collide. But it's not very reasonable for
- // a script target named "foo" to generate a file named "bar" with no
- // extension in the root build directory while another target is named
- // "bar". If this does occur, the user is likely to be confused when
- // building "bar" that is builds foo anyway, so you probably just
- // shouldn't do that.
- //
- // We should fix this however, and build up all generated script outputs
- // and check everything against that. There are other edge cases that the
- // current phony rule generator doesn't check. We may need to make a big
- // set of every possible generated file in the build for this purpose.
- if (!HasOutputIdenticalToLabel(target, label.name()))
- WritePhonyRule(target, target_file, label.name(), &written_rules);
+ if (medium_name != label.name() &&
+ written_rules.insert(medium_name).second)
+ WritePhonyRule(target, medium_name);
}
- if (!all_rules.empty())
- all_rules.append(" $\n ");
- all_rules.append(target_file.value());
- }
-
- // Pick up phony rules for the toplevel targets with non-unique names (which
- // would have been skipped in the above loop).
- for (const auto& toplevel_target : toplevel_targets) {
- if (small_name_count[toplevel_target->label().name()] > 1) {
- WritePhonyRule(toplevel_target, toplevel_target->dependency_output_file(),
- toplevel_target->label().name(), &written_rules);
- }
+ // Write the short name if no other target shares that short name and
+ // non of the higher-priority rules above claimed it.
+ if (short_names[label.name()].count == 1 &&
+ written_rules.insert(label.name()).second)
+ WritePhonyRule(target, label.name());
}
- // Figure out if the BUILD file wants to declare a custom "default"
- // target (rather than building 'all' by default). By convention
- // we use group("default") but it doesn't have to be a group.
- bool default_target_exists = false;
- for (const auto& target : default_toolchain_targets_) {
- const Label& label = target->label();
- if (label.dir().value() == "//" && label.name() == "default")
- default_target_exists = true;
- }
+ // Write the autogenerated "all" rule.
+ if (!default_toolchain_targets_.empty()) {
+ out_ << "\nbuild all: phony";
- if (!all_rules.empty()) {
- out_ << "\nbuild all: phony " << all_rules << std::endl;
+ 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_exists) {
- out_ << "default default" << std::endl;
- } else if (!all_rules.empty()) {
- out_ << "default all" << std::endl;
- }
+ if (default_target_exists)
+ out_ << "\ndefault default" << std::endl;
+ else if (!default_toolchain_targets_.empty())
+ out_ << "\ndefault all" << std::endl;
return true;
}
void NinjaBuildWriter::WritePhonyRule(const Target* target,
- const OutputFile& target_file,
- const std::string& phony_name,
- std::set<std::string>* written_rules) {
- if (target_file.value() == phony_name)
- return; // No need for a phony rule.
-
- if (written_rules->find(phony_name) != written_rules->end())
- return; // Already exists.
- written_rules->insert(phony_name);
-
+ const std::string& phony_name) {
EscapeOptions ninja_escape;
ninja_escape.mode = ESCAPE_NINJA;
@@ -401,6 +407,6 @@ void NinjaBuildWriter::WritePhonyRule(const Target* target,
std::string escaped = EscapeString(phony_name, ninja_escape, nullptr);
out_ << "build " << escaped << ": phony ";
- path_output_.WriteFile(out_, target_file);
+ 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
index 0d5b40eef70..e94f93de24e 100644
--- a/chromium/tools/gn/ninja_build_writer.h
+++ b/chromium/tools/gn/ninja_build_writer.h
@@ -46,12 +46,7 @@ class NinjaBuildWriter {
void WriteSubninjas();
bool WritePhonyAndAllRules(Err* err);
- // Writes a phony rule for the given target with the given name. Adds the new
- // name to the given set. If the name is already in the set, does nothing.
- void WritePhonyRule(const Target* target,
- const OutputFile& target_file,
- const std::string& phony_name,
- std::set<std::string>* written_rules);
+ void WritePhonyRule(const Target* target, const std::string& phony_name);
const BuildSettings* build_settings_;
std::vector<const Settings*> all_settings_;
diff --git a/chromium/tools/gn/ninja_build_writer_unittest.cc b/chromium/tools/gn/ninja_build_writer_unittest.cc
index f82dc835521..48d73028e17 100644
--- a/chromium/tools/gn/ninja_build_writer_unittest.cc
+++ b/chromium/tools/gn/ninja_build_writer_unittest.cc
@@ -53,13 +53,15 @@ TEST(NinjaBuildWriter, TwoTargets) {
"subninja toolchain.ninja\n"
"\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"
- "build bar: phony obj/bar/bar.stamp\n"
"\n";
const char expected_root_target[] =
- "build all: phony obj/foo/bar.stamp $\n"
+ "build all: phony $\n"
+ " obj/foo/bar.stamp $\n"
" obj/bar/bar.stamp\n"
+ "\n"
"default all\n";
std::string out_str = ninja_out.str();
#define EXPECT_SNIPPET(expected) \
diff --git a/chromium/tools/gn/ninja_create_bundle_target_writer.cc b/chromium/tools/gn/ninja_create_bundle_target_writer.cc
index d85f2401ae5..84da2ff2d4b 100644
--- a/chromium/tools/gn/ninja_create_bundle_target_writer.cc
+++ b/chromium/tools/gn/ninja_create_bundle_target_writer.cc
@@ -116,4 +116,15 @@ void NinjaCreateBundleTargetWriter::Run() {
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;
}
diff --git a/chromium/tools/gn/ninja_create_bundle_target_writer_unittest.cc b/chromium/tools/gn/ninja_create_bundle_target_writer_unittest.cc
index 88e6fbab34d..d35b519adc2 100644
--- a/chromium/tools/gn/ninja_create_bundle_target_writer_unittest.cc
+++ b/chromium/tools/gn/ninja_create_bundle_target_writer_unittest.cc
@@ -14,10 +14,11 @@
namespace {
void SetupBundleDataDir(BundleData* bundle_data, const std::string& root_dir) {
- bundle_data->root_dir().assign(root_dir + "/bar.bundle");
- bundle_data->resources_dir().assign(bundle_data->root_dir() + "/Resources");
- bundle_data->executable_dir().assign(bundle_data->root_dir() + "/Executable");
- bundle_data->plugins_dir().assign(bundle_data->root_dir() + "/PlugIns");
+ std::string bundle_root_dir = root_dir + "/bar.bundle";
+ bundle_data->root_dir() = SourceDir(bundle_root_dir);
+ bundle_data->resources_dir() = SourceDir(bundle_root_dir + "/Resources");
+ bundle_data->executable_dir() = SourceDir(bundle_root_dir + "/Executable");
+ bundle_data->plugins_dir() = SourceDir(bundle_root_dir + "/PlugIns");
}
} // namespace
@@ -55,7 +56,8 @@ TEST(NinjaCreateBundleTargetWriter, Run) {
"\n"
"build obj/baz/bar.stamp: stamp "
"bar.bundle/Resources/input1.txt "
- "bar.bundle/Resources/input2.txt\n";
+ "bar.bundle/Resources/input2.txt\n"
+ "build bar.bundle: phony obj/baz/bar.stamp\n";
std::string out_str = out.str();
EXPECT_EQ(expected, out_str);
}
@@ -97,7 +99,53 @@ TEST(NinjaCreateBundleTargetWriter, AssetCatalog) {
"../../foo/Foo.xcassets/foo.imageset/FooIcon-29@2x.png "
"../../foo/Foo.xcassets/foo.imageset/FooIcon-29@3x.png\n"
"\n"
- "build obj/baz/bar.stamp: stamp bar.bundle/Resources/Assets.car\n";
+ "build obj/baz/bar.stamp: stamp bar.bundle/Resources/Assets.car\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, BundleRootDirOutput) {
+ TestWithScope setup;
+ Err err;
+
+ setup.build_settings()->SetBuildDir(SourceDir("//out/Debug/"));
+ Target target(setup.settings(), Label(SourceDir("//baz/"), "bar"));
+ target.set_output_type(Target::CREATE_BUNDLE);
+
+ const std::string bundle_root_dir("//out/Debug/bar.bundle/Contents");
+ target.bundle_data().root_dir() = SourceDir(bundle_root_dir);
+ target.bundle_data().resources_dir() =
+ SourceDir(bundle_root_dir + "/Resources");
+ target.bundle_data().executable_dir() = SourceDir(bundle_root_dir + "/MacOS");
+ target.bundle_data().plugins_dir() = SourceDir(bundle_root_dir + "/Plug Ins");
+
+ std::vector<SourceFile> sources;
+ sources.push_back(SourceFile("//foo/input1.txt"));
+ sources.push_back(SourceFile("//foo/input2.txt"));
+ target.bundle_data().file_rules().push_back(BundleFileRule(
+ sources, SubstitutionPattern::MakeForTest(
+ "{{bundle_resources_dir}}/{{source_file_part}}")));
+
+ target.SetToolchain(setup.toolchain());
+ ASSERT_TRUE(target.OnResolved(&err));
+
+ std::ostringstream out;
+ NinjaCreateBundleTargetWriter writer(&target, out);
+ writer.Run();
+
+ const char expected[] =
+ "build bar.bundle/Contents/Resources/input1.txt: copy_bundle_data "
+ "../../foo/input1.txt\n"
+ "build bar.bundle/Contents/Resources/input2.txt: copy_bundle_data "
+ "../../foo/input2.txt\n"
+ "\n"
+ "build obj/baz/bar.stamp: stamp "
+ "bar.bundle/Contents/Resources/input1.txt "
+ "bar.bundle/Contents/Resources/input2.txt\n"
+ "build bar.bundle: phony obj/baz/bar.stamp\n";
std::string out_str = out.str();
EXPECT_EQ(expected, out_str);
}
@@ -167,7 +215,8 @@ TEST(NinjaCreateBundleTargetWriter, OrderOnlyDeps) {
"bar.bundle/Resources/input1.txt "
"bar.bundle/Resources/input2.txt "
"bar.bundle/Info.plist "
- "bar.bundle/Resources/Assets.car\n";
+ "bar.bundle/Resources/Assets.car\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/parse_tree.cc b/chromium/tools/gn/parse_tree.cc
index 167531c93fe..dc80514639a 100644
--- a/chromium/tools/gn/parse_tree.cc
+++ b/chromium/tools/gn/parse_tree.cc
@@ -297,7 +297,6 @@ BlockNode::BlockNode() {
}
BlockNode::~BlockNode() {
- STLDeleteContainerPointers(statements_.begin(), statements_.end());
}
const BlockNode* BlockNode::AsBlock() const {
@@ -307,7 +306,7 @@ const BlockNode* BlockNode::AsBlock() const {
Value BlockNode::Execute(Scope* scope, Err* err) const {
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.
- const ParseNode* cur = statements_[i];
+ const ParseNode* cur = statements_[i].get();
if (cur->AsList() || cur->AsLiteral() || cur->AsUnaryOp() ||
cur->AsIdentifier()) {
*err = cur->MakeErrorDescribing(
@@ -492,7 +491,6 @@ ListNode::ListNode() : prefer_multiline_(false) {
}
ListNode::~ListNode() {
- STLDeleteContainerPointers(contents_.begin(), contents_.end());
}
const ListNode* ListNode::AsList() const {
@@ -547,7 +545,7 @@ void ListNode::SortList(Comparator comparator) {
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];
+ const ParseNode* node = contents_[i].get();
if (!node->AsLiteral() && !node->AsIdentifier() && !node->AsAccessor()) {
skip = true;
continue;
@@ -561,15 +559,19 @@ void ListNode::SortList(Comparator comparator) {
// 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];
+ const ParseNode* original_first = contents_[sr.begin].get();
std::sort(contents_.begin() + sr.begin, contents_.begin() + sr.end,
- comparator);
+ [&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] != original_first) {
+ if (original_first->comments() &&
+ contents_[sr.begin].get() != original_first) {
for (const auto& hc : original_first->comments()->before()) {
- const_cast<ParseNode*>(contents_[sr.begin])
+ const_cast<ParseNode*>(contents_[sr.begin].get())
->comments_mutable()
->append_before(hc);
}
@@ -579,7 +581,7 @@ void ListNode::SortList(Comparator comparator) {
}
const ParseNode* prev = nullptr;
for (size_t i = sr.begin; i != sr.end; ++i) {
- const ParseNode* node = contents_[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;
@@ -627,8 +629,8 @@ 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++]) {
- if (IsSortRangeSeparator(contents_[i], prev)) {
+ 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
diff --git a/chromium/tools/gn/parse_tree.h b/chromium/tools/gn/parse_tree.h
index 28537992068..48313bea7f2 100644
--- a/chromium/tools/gn/parse_tree.h
+++ b/chromium/tools/gn/parse_tree.h
@@ -227,9 +227,11 @@ class BlockNode : public ParseNode {
void set_end(std::unique_ptr<EndNode> e) { end_ = std::move(e); }
const EndNode* End() const { return end_.get(); }
- const std::vector<ParseNode*>& statements() const { return statements_; }
+ const std::vector<std::unique_ptr<ParseNode>>& statements() const {
+ return statements_;
+ }
void append_statement(std::unique_ptr<ParseNode> s) {
- statements_.push_back(s.release());
+ statements_.push_back(std::move(s));
}
private:
@@ -238,8 +240,7 @@ class BlockNode : public ParseNode {
Token begin_token_;
std::unique_ptr<EndNode> end_;
- // Owning pointers, use unique_ptr when we can use C++11.
- std::vector<ParseNode*> statements_;
+ std::vector<std::unique_ptr<ParseNode>> statements_;
DISALLOW_COPY_AND_ASSIGN(BlockNode);
};
@@ -364,9 +365,11 @@ class ListNode : public ParseNode {
const EndNode* End() const { return end_.get(); }
void append_item(std::unique_ptr<ParseNode> s) {
- contents_.push_back(s.release());
+ contents_.push_back(std::move(s));
+ }
+ const std::vector<std::unique_ptr<const ParseNode>>& contents() const {
+ return contents_;
}
- const std::vector<const ParseNode*>& contents() const { return contents_; }
void SortAsStringsList();
void SortAsDepsList();
@@ -397,8 +400,7 @@ class ListNode : public ParseNode {
std::unique_ptr<EndNode> end_;
bool prefer_multiline_;
- // Owning pointers, use unique_ptr when we can use C++11.
- std::vector<const ParseNode*> contents_;
+ std::vector<std::unique_ptr<const ParseNode>> contents_;
DISALLOW_COPY_AND_ASSIGN(ListNode);
};
diff --git a/chromium/tools/gn/parser.cc b/chromium/tools/gn/parser.cc
index 33abfd0b2f0..977ddad6e7b 100644
--- a/chromium/tools/gn/parser.cc
+++ b/chromium/tools/gn/parser.cc
@@ -671,7 +671,7 @@ void Parser::TraverseOrder(const ParseNode* root,
TraverseOrder(binop->right(), pre, post);
} else if (const BlockNode* block = root->AsBlock()) {
for (const auto& statement : block->statements())
- TraverseOrder(statement, pre, post);
+ TraverseOrder(statement.get(), pre, post);
TraverseOrder(block->End(), pre, post);
} else if (const ConditionNode* condition = root->AsConditionNode()) {
TraverseOrder(condition->condition(), pre, post);
@@ -684,7 +684,7 @@ void Parser::TraverseOrder(const ParseNode* root,
// Nothing.
} else if (const ListNode* list = root->AsList()) {
for (const auto& node : list->contents())
- TraverseOrder(node, pre, post);
+ TraverseOrder(node.get(), pre, post);
TraverseOrder(list->End(), pre, post);
} else if (root->AsLiteral()) {
// Nothing.
diff --git a/chromium/tools/gn/qt_creator_writer.cc b/chromium/tools/gn/qt_creator_writer.cc
new file mode 100644
index 00000000000..96f247f5719
--- /dev/null
+++ b/chromium/tools/gn/qt_creator_writer.cc
@@ -0,0 +1,174 @@
+// 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() {}
+
+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());
+ AddToSources(target->inputs());
+
+ for (ConfigValuesIterator it(target); !it.done(); it.Next()) {
+ 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
new file mode 100644
index 00000000000..cea75fd1814
--- /dev/null
+++ b/chromium/tools/gn/qt_creator_writer.h
@@ -0,0 +1,56 @@
+// 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
index 17b9c075227..5352de3aadd 100644
--- a/chromium/tools/gn/runtime_deps.cc
+++ b/chromium/tools/gn/runtime_deps.cc
@@ -104,6 +104,15 @@ void RecursiveCollectRuntimeDeps(const Target* target,
AddIfNew(output_file.value(), target, deps, 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)
diff --git a/chromium/tools/gn/runtime_deps_unittest.cc b/chromium/tools/gn/runtime_deps_unittest.cc
index 915fbc28302..8b68bd85c4d 100644
--- a/chromium/tools/gn/runtime_deps_unittest.cc
+++ b/chromium/tools/gn/runtime_deps_unittest.cc
@@ -8,6 +8,7 @@
#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_scope.h"
@@ -257,6 +258,83 @@ TEST(RuntimeDeps, ActionOutputs) {
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(RuntimeDeps, CreateBundle) {
+ TestWithScope setup;
+ Err err;
+
+ // Dependency hierarchy:
+ // main(exe) -> dep(bundle) -> dep(shared_library) -> dep(source set)
+ // -> dep(bundle_data) -> dep(loadable_module)
+
+ 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);
+ 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(
+ 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(
+ std::vector<SourceFile>{SourceFile(build_dir + "dylib")},
+ SubstitutionPattern::MakeForTest("{{bundle_executable_dir}}")));
+ ASSERT_TRUE(dylib_data.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/Versions/A/");
+ bundle.bundle_data().root_dir() = SourceDir(root_dir);
+ bundle.bundle_data().resources_dir() = SourceDir(root_dir + "Resources");
+ bundle.bundle_data().executable_dir() = SourceDir(root_dir + "MacOS");
+ bundle.private_deps().push_back(LabelTargetPair(&dylib_data));
+ bundle.private_deps().push_back(LabelTargetPair(&module_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(2u, result.size()) << GetVectorDescription(result);
+
+ // The first one should always be the main exe.
+ EXPECT_EQ(MakePair("./main", &main), result[0]);
+
+ // The second one should be the framework bundle, not its included
+ // loadable_module or its intermediate shared_library.
+ EXPECT_EQ(MakePair("Bundle.framework/", &bundle), result[1]);
+}
+
// Tests that a dependency duplicated in regular and data deps is processed
// as a data dep.
TEST(RuntimeDeps, Dupe) {
@@ -282,3 +360,31 @@ TEST(RuntimeDeps, Dupe) {
MakePair("../../action.output", &action)) !=
result.end()) << GetVectorDescription(result);
}
+
+// Tests that actions can't have output substitutions.
+TEST(RuntimeDeps, WriteRuntimeDepsVariable) {
+ Scheduler scheduler;
+ 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
index a711df1cf02..b2e2a006b96 100644
--- a/chromium/tools/gn/scheduler.cc
+++ b/chromium/tools/gn/scheduler.cc
@@ -54,10 +54,13 @@ int GetThreadCount() {
//
// 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 three workers to prevent us from being too sensitive to I/O latency
+ // 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.
int num_cores = GetCPUCount() / 2; // Almost all CPUs now are hyperthreaded.
- return std::max(num_cores - 1, 3);
+ return std::max(num_cores - 1, 8);
}
} // namespace
diff --git a/chromium/tools/gn/scope.cc b/chromium/tools/gn/scope.cc
index d3d29d44927..93ce966e4f3 100644
--- a/chromium/tools/gn/scope.cc
+++ b/chromium/tools/gn/scope.cc
@@ -5,7 +5,7 @@
#include "tools/gn/scope.h"
#include "base/logging.h"
-#include "base/stl_util.h"
+#include "base/memory/ptr_util.h"
#include "tools/gn/parse_tree.h"
#include "tools/gn/template.h"
@@ -64,8 +64,6 @@ Scope::Scope(const Scope* parent)
}
Scope::~Scope() {
- STLDeleteContainerPairSecondPointers(target_defaults_.begin(),
- target_defaults_.end());
}
const Value* Scope::GetValue(const base::StringPiece& ident,
@@ -315,12 +313,9 @@ bool Scope::NonRecursiveMergeTo(Scope* dest,
}
}
- // Be careful to delete any pointer we're about to clobber.
- Scope** dest_scope = &dest->target_defaults_[current_name];
- if (*dest_scope)
- delete *dest_scope;
- *dest_scope = new Scope(settings_);
- pair.second->NonRecursiveMergeTo(*dest_scope, options, node_for_err,
+ std::unique_ptr<Scope>& dest_scope = dest->target_defaults_[current_name];
+ dest_scope = base::WrapUnique(new Scope(settings_));
+ pair.second->NonRecursiveMergeTo(dest_scope.get(), options, node_for_err,
"<SHOULDN'T HAPPEN>", err);
}
@@ -412,19 +407,19 @@ Scope* Scope::MakeTargetDefaults(const std::string& target_type) {
if (GetTargetDefaults(target_type))
return nullptr;
- Scope** dest = &target_defaults_[target_type];
- if (*dest) {
+ std::unique_ptr<Scope>& dest = target_defaults_[target_type];
+ if (dest) {
NOTREACHED(); // Already set.
- return *dest;
+ return dest.get();
}
- *dest = new Scope(settings_);
- return *dest;
+ dest = base::WrapUnique(new 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;
+ return found->second.get();
if (containing())
return containing()->GetTargetDefaults(target_type);
return nullptr;
diff --git a/chromium/tools/gn/scope.h b/chromium/tools/gn/scope.h
index 72aa0c3e2fb..e9bd1397cc9 100644
--- a/chromium/tools/gn/scope.h
+++ b/chromium/tools/gn/scope.h
@@ -333,10 +333,9 @@ class Scope {
RecordMap;
RecordMap values_;
- // Owning pointers. 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, Scope*> NamedScopeMap;
+ // 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
diff --git a/chromium/tools/gn/setup.cc b/chromium/tools/gn/setup.cc
index 384a2af17ea..ea7cb240908 100644
--- a/chromium/tools/gn/setup.cc
+++ b/chromium/tools/gn/setup.cc
@@ -299,7 +299,7 @@ bool Setup::DoSetup(const std::string& build_dir, bool force_create) {
if (!FillArguments(*cmdline))
return false;
}
- FillPythonPath();
+ FillPythonPath(*cmdline);
return true;
}
@@ -332,9 +332,13 @@ bool Setup::RunPostMessageLoop() {
}
if (!build_settings_.build_args().VerifyAllOverridesUsed(&err)) {
- // TODO(brettw) implement a system of warnings. Until we have a better
- // system, print the error but don't return failure.
+ // TODO(brettw) implement a system to have a different marker for
+ // warnings. Until we have a better system, print the error but don't
+ // return failure unless requested on the command line.
err.PrintToStdout();
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kFailOnUnusedArgs))
+ return false;
return true;
}
}
@@ -590,20 +594,25 @@ bool Setup::FillBuildDir(const std::string& build_dir, bool require_exists) {
return true;
}
-void Setup::FillPythonPath() {
+void 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");
+ if (cmdline.HasSwitch(switches::kScriptExecutable)) {
+ build_settings_.set_python_path(
+ cmdline.GetSwitchValuePath(switches::kScriptExecutable));
+ } 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('/'));
+ 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"));
+ build_settings_.set_python_path(base::FilePath("python"));
#endif
+ }
}
bool Setup::RunConfigFile() {
diff --git a/chromium/tools/gn/setup.h b/chromium/tools/gn/setup.h
index 4f2d8859951..22e655745b1 100644
--- a/chromium/tools/gn/setup.h
+++ b/chromium/tools/gn/setup.h
@@ -119,7 +119,7 @@ class Setup {
// Fills the python path portion of the command line. On failure, sets
// it to just "python".
- void FillPythonPath();
+ void FillPythonPath(const base::CommandLine& cmdline);
// Run config file.
bool RunConfigFile();
diff --git a/chromium/tools/gn/source_file_type.cc b/chromium/tools/gn/source_file_type.cc
index 72b872c5cae..328b2abbac3 100644
--- a/chromium/tools/gn/source_file_type.cc
+++ b/chromium/tools/gn/source_file_type.cc
@@ -11,7 +11,8 @@ SourceFileType GetSourceFileType(const SourceFile& file) {
base::StringPiece extension = FindExtension(&file.value());
if (extension == "cc" || extension == "cpp" || extension == "cxx")
return SOURCE_CPP;
- if (extension == "h")
+ if (extension == "h" || extension == "hpp" || extension == "hxx" ||
+ extension == "hh")
return SOURCE_H;
if (extension == "c")
return SOURCE_C;
diff --git a/chromium/tools/gn/substitution_type.cc b/chromium/tools/gn/substitution_type.cc
index e1ea14de947..fcca19dac06 100644
--- a/chromium/tools/gn/substitution_type.cc
+++ b/chromium/tools/gn/substitution_type.cc
@@ -43,9 +43,12 @@ const char* kSubstitutionNames[SUBSTITUTION_NUM_TYPES] = {
"{{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_resources_dir}}", // SUBSTITUTION_BUNDLE_RESOURCES_DIR
"{{bundle_executable_dir}}", // SUBSTITUTION_BUNDLE_EXECUTABLE_DIR
@@ -91,9 +94,12 @@ const char* kSubstitutionNinjaNames[SUBSTITUTION_NUM_TYPES] = {
"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_resources_dir", // SUBSTITUTION_BUNDLE_RESOURCES_DIR
"bundle_executable_dir", // SUBSTITUTION_BUNDLE_EXECUTABLE_DIR
@@ -193,6 +199,7 @@ bool IsValidLinkerSubstitution(SubstitutionType type) {
type == SUBSTITUTION_LINKER_INPUTS_NEWLINE ||
type == SUBSTITUTION_LDFLAGS ||
type == SUBSTITUTION_LIBS ||
+ type == SUBSTITUTION_OUTPUT_DIR ||
type == SUBSTITUTION_OUTPUT_EXTENSION ||
type == SUBSTITUTION_SOLIBS;
}
@@ -200,6 +207,16 @@ bool IsValidLinkerSubstitution(SubstitutionType type) {
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;
}
diff --git a/chromium/tools/gn/substitution_type.h b/chromium/tools/gn/substitution_type.h
index 3f7ec971abd..e82ecd61073 100644
--- a/chromium/tools/gn/substitution_type.h
+++ b/chromium/tools/gn/substitution_type.h
@@ -56,9 +56,13 @@ enum SubstitutionType {
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_RESOURCES_DIR, // {{bundle_resources_dir}}
@@ -116,6 +120,7 @@ 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);
diff --git a/chromium/tools/gn/substitution_writer.cc b/chromium/tools/gn/substitution_writer.cc
index 23d6914ac4e..a82e7ee2e75 100644
--- a/chromium/tools/gn/substitution_writer.cc
+++ b/chromium/tools/gn/substitution_writer.cc
@@ -56,6 +56,10 @@ const char kSourceExpansion_Help[] =
"\n"
"Placeholders\n"
"\n"
+ " This section discusses only placeholders for actions. There are other\n"
+ " placeholders used in the definition of tools. See \"gn help tool\" for\n"
+ " those.\n"
+ "\n"
" {{source}}\n"
" The name of the source file including directory (*). This will\n"
" generally be used for specifying inputs to a script in the\n"
@@ -546,6 +550,23 @@ std::string SubstitutionWriter::GetLinkerSubstitution(
// 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();
+ } else {
+ SetDirOrDotWithNoSlash(RebasePath(
+ target->output_dir().value(),
+ target->settings()->build_settings()->build_dir()),
+ &result);
+ return result;
+ }
+ break;
+
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
diff --git a/chromium/tools/gn/substitution_writer_unittest.cc b/chromium/tools/gn/substitution_writer_unittest.cc
index 77374f1a313..d252c79f54c 100644
--- a/chromium/tools/gn/substitution_writer_unittest.cc
+++ b/chromium/tools/gn/substitution_writer_unittest.cc
@@ -278,4 +278,46 @@ TEST(SubstitutionWriter, LinkerSubstitutions) {
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
index df167b30aa5..8884634f906 100644
--- a/chromium/tools/gn/switches.cc
+++ b/chromium/tools/gn/switches.cc
@@ -69,17 +69,51 @@ const char kDotfile_Help[] =
" Note that this interacts with \"--root\" in a possibly incorrect way.\n"
" It would be nice to test the edge cases and document or fix.\n";
+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[] =
+ "--fail-on-unused-args: Treat unused build args as fatal errors.\n"
+ "\n"
+ " If you set a value in a build's \"gn args\" and never use it in the\n"
+ " build (in a declare_args() block), GN will normally print an error\n"
+ " but not fail the build.\n"
+ "\n"
+ " In many cases engineers would use build args to enable or disable\n"
+ " features that would sometimes get removed. It would by annoying to\n"
+ " block work for typically benign problems. In Chrome in particular,\n"
+ " flags might be configured for build bots in a separate infrastructure\n"
+ " repository, or a declare_args block might be changed in a third party\n"
+ " repository. Treating these errors as blocking forced complex multi-\n"
+ " way patches to land what would otherwise be simple changes.\n"
+ "\n"
+ " In some cases, such concerns are not as important, and a mismatch\n"
+ " in build flags between the invoker of the build and the build files\n"
+ " represents a critical mismatch that should be immediately fixed. Such\n"
+ " users can set this flag to force GN to fail in that case.\n";
+
const char kMarkdown[] = "markdown";
const char kMarkdown_HelpShort[] =
- "--markdown: write the output in the Markdown format.";
+ "--markdown: Write help output in the Markdown format.";
const char kMarkdown_Help[] =
- "--markdown: write the output in the Markdown format.\n";
+ "--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[] =
+ "--script-executable: Set the executable used to execute scripts.\n"
+ "\n"
+ " By default GN searches the PATH for Python to execute scripts in\n"
+ " action targets and exec_script calls. This flag allows the\n"
+ " specification of a specific Python executable or potentially\n"
+ " a different language interpreter.\n";
+
const char kQuiet[] = "q";
const char kQuiet_HelpShort[] =
"-q: Quiet mode. Don't print output on success.";
@@ -202,6 +236,8 @@ const char kVersion_HelpShort[] =
// immediately if this switch is used.
const char kVersion_Help[] = "";
+const char kAllToolchains[] = "all-toolchains";
+
// -----------------------------------------------------------------------------
SwitchInfo::SwitchInfo()
@@ -223,11 +259,13 @@ const SwitchInfoMap& GetSwitches() {
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)
diff --git a/chromium/tools/gn/switches.h b/chromium/tools/gn/switches.h
index 3dc5b9f0f25..effaa25ed3c 100644
--- a/chromium/tools/gn/switches.h
+++ b/chromium/tools/gn/switches.h
@@ -40,6 +40,10 @@ 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[];
@@ -48,6 +52,10 @@ 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[];
@@ -80,6 +88,20 @@ 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
index 18c353eac05..ddc8ad5074d 100644
--- a/chromium/tools/gn/target.cc
+++ b/chromium/tools/gn/target.cc
@@ -55,19 +55,6 @@ Err MakeTestOnlyError(const Target* from, const Target* to) {
"Either mark it test-only or don't do this dependency.");
}
-Err MakeStaticLibDepsError(const Target* from, const Target* to) {
- return Err(from->defined_from(),
- "Complete static libraries can't depend on static libraries.",
- from->label().GetUserVisibleName(false) +
- "\n"
- "which is a complete static library can't depend on\n" +
- to->label().GetUserVisibleName(false) +
- "\n"
- "which is a static library.\n"
- "\n"
- "Use source sets for intermediate targets instead.");
-}
-
// 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.
@@ -317,13 +304,14 @@ bool Target::OnResolved(Err* err) {
return false;
if (!CheckTestonly(err))
return false;
- if (!CheckNoNestedStaticLibs(err))
- return false;
if (!CheckAssertNoDeps(err))
return false;
CheckSourcesGenerated();
}
+ if (!write_runtime_deps_output_.value().empty())
+ g_scheduler->AddWriteRuntimeDepsTarget(this);
+
return true;
}
@@ -479,8 +467,24 @@ void Target::PullDependentTargetLibsFrom(const Target* dep, bool is_public) {
// 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);
+ }
+ }
+ }
- // Inherited library settings.
+ // 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());
}
@@ -699,30 +703,6 @@ bool Target::CheckTestonly(Err* err) const {
return true;
}
-bool Target::CheckNoNestedStaticLibs(Err* err) const {
- // If the current target is not a complete static library, it can depend on
- // static library targets with no problem.
- if (!(output_type() == Target::STATIC_LIBRARY && complete_static_lib()))
- return true;
-
- // Verify no deps are static libraries.
- for (const auto& pair : GetDeps(DEPS_ALL)) {
- if (pair.ptr->output_type() == Target::STATIC_LIBRARY) {
- *err = MakeStaticLibDepsError(this, pair.ptr);
- return false;
- }
- }
-
- // Verify no inherited libraries are static libraries.
- for (const auto& lib : inherited_libraries().GetOrdered()) {
- if (lib->output_type() == Target::STATIC_LIBRARY) {
- *err = MakeStaticLibDepsError(this, lib);
- return false;
- }
- }
- return true;
-}
-
bool Target::CheckAssertNoDeps(Err* err) const {
if (assert_no_deps_.empty())
return true;
diff --git a/chromium/tools/gn/target.h b/chromium/tools/gn/target.h
index fdd6f1a6821..495a9c15ec9 100644
--- a/chromium/tools/gn/target.h
+++ b/chromium/tools/gn/target.h
@@ -100,6 +100,12 @@ class Target : public Item {
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
@@ -324,7 +330,6 @@ class Target : public Item {
// Validates the given thing when a target is resolved.
bool CheckVisibility(Err* err) const;
bool CheckTestonly(Err* err) const;
- bool CheckNoNestedStaticLibs(Err* err) const;
bool CheckAssertNoDeps(Err* err) const;
void CheckSourcesGenerated() const;
void CheckSourceGenerated(const SourceFile& source) const;
@@ -332,6 +337,7 @@ class Target : public Item {
OutputType output_type_;
std::string output_name_;
bool output_prefix_override_;
+ SourceDir output_dir_;
std::string output_extension_;
bool output_extension_set_;
diff --git a/chromium/tools/gn/target_generator.cc b/chromium/tools/gn/target_generator.cc
index 2132a5b06bd..90642d47d20 100644
--- a/chromium/tools/gn/target_generator.cc
+++ b/chromium/tools/gn/target_generator.cc
@@ -403,6 +403,5 @@ bool TargetGenerator::FillWriteRuntimeDeps() {
OutputFile output_file(GetBuildSettings(), source_file);
target_->set_write_runtime_deps_output(output_file);
- g_scheduler->AddWriteRuntimeDepsTarget(target_);
return true;
}
diff --git a/chromium/tools/gn/target_unittest.cc b/chromium/tools/gn/target_unittest.cc
index e2e41a8708c..622dd54aef7 100644
--- a/chromium/tools/gn/target_unittest.cc
+++ b/chromium/tools/gn/target_unittest.cc
@@ -183,7 +183,13 @@ TEST(Target, InheritCompleteStaticLib) {
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));
@@ -199,42 +205,74 @@ TEST(Target, InheritCompleteStaticLib) {
// 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();
- EXPECT_EQ(1u, a_inherited.size());
+ 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(Target, InheritCompleteStaticLibNoDirectStaticLibDeps) {
+TEST(Target, InheritCompleteStaticLibStaticLibDeps) {
TestWithScope setup;
Err err;
// Create a dependency chain:
- // A (complete static lib) -> B (static lib)
- TestTarget a(setup, "//foo:a", Target::STATIC_LIBRARY);
- a.set_complete_static_lib(true);
+ // 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_FALSE(a.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(Target, InheritCompleteStaticLibNoIheritedStaticLibDeps) {
+TEST(Target, InheritCompleteStaticLibInheritedCompleteStaticLibDeps) {
TestWithScope setup;
Err err;
// Create a dependency chain:
- // A (complete static lib) -> B (source set) -> C (static lib)
- TestTarget a(setup, "//foo:a", Target::STATIC_LIBRARY);
- a.set_complete_static_lib(true);
- TestTarget b(setup, "//foo:b", Target::SOURCE_SET);
+ // 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.public_deps().push_back(LabelTargetPair(&b));
- b.public_deps().push_back(LabelTargetPair(&c));
+ 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_FALSE(a.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(Target, NoActionDepPropgation) {
diff --git a/chromium/tools/gn/test_with_scope.cc b/chromium/tools/gn/test_with_scope.cc
index 32d5dd67585..0ddd4636be4 100644
--- a/chromium/tools/gn/test_with_scope.cc
+++ b/chromium/tools/gn/test_with_scope.cc
@@ -24,6 +24,7 @@ TestWithScope::TestWithScope()
settings_.set_default_toolchain_label(toolchain_.label());
SetupToolchain(&toolchain_);
+ scope_.set_item_collector(&items_);
}
TestWithScope::~TestWithScope() {
@@ -37,6 +38,28 @@ Label TestWithScope::ParseLabel(const std::string& str) const {
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;
diff --git a/chromium/tools/gn/test_with_scope.h b/chromium/tools/gn/test_with_scope.h
index fa6fb4b324b..88532438213 100644
--- a/chromium/tools/gn/test_with_scope.h
+++ b/chromium/tools/gn/test_with_scope.h
@@ -34,6 +34,7 @@ class TestWithScope {
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
@@ -44,6 +45,11 @@ class TestWithScope {
// 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
@@ -62,6 +68,7 @@ class TestWithScope {
Settings settings_;
Toolchain toolchain_;
Scope scope_;
+ Scope::ItemVector items_;
// Supplies the scope with built-in variables like root_out_dir.
ScopePerFileProvider scope_progammatic_provider_;
diff --git a/chromium/tools/gn/tool.h b/chromium/tools/gn/tool.h
index 9360ce66ef6..f6727ed6d16 100644
--- a/chromium/tools/gn/tool.h
+++ b/chromium/tools/gn/tool.h
@@ -52,6 +52,14 @@ class Tool {
default_output_extension_ = ext;
}
+ const SubstitutionPattern& default_output_dir() const {
+ return default_output_dir_;
+ }
+ void set_default_output_dir(const SubstitutionPattern& dir) {
+ DCHECK(!complete_);
+ default_output_dir_ = dir;
+ }
+
// Dependency file (if supported).
const SubstitutionPattern& depfile() const {
return depfile_;
@@ -186,6 +194,7 @@ class Tool {
private:
SubstitutionPattern command_;
std::string default_output_extension_;
+ SubstitutionPattern default_output_dir_;
SubstitutionPattern depfile_;
DepsFormat depsformat_;
PrecompiledHeaderType precompiled_header_type_;
diff --git a/chromium/tools/gn/variables.cc b/chromium/tools/gn/variables.cc
index 4c5fae1adf6..a65d9403e31 100644
--- a/chromium/tools/gn/variables.cc
+++ b/chromium/tools/gn/variables.cc
@@ -418,6 +418,25 @@ const char kAllowCircularIncludesFrom_Help[] =
" public_deps = [ \":c\" ]\n"
" }\n";
+const char kArflags[] = "arflags";
+const char kArflags_HelpShort[] =
+ "arflags: [string list] Arguments passed to static_library archiver.";
+const char kArflags_Help[] =
+ "arflags: Arguments passed to static_library archiver.\n"
+ "\n"
+ " A list of flags passed to the archive/lib command that creates static\n"
+ " libraries.\n"
+ "\n"
+ " arflags are NOT pushed to dependents, so applying arflags to source\n"
+ " sets or any other target type will be a no-op. As with ldflags,\n"
+ " you could put the arflags in a config and set that as a public or\n"
+ " \"all dependent\" config, but that will likely not be what you want.\n"
+ " If you have a chain of static libraries dependent on each other,\n"
+ " this can cause the flags to propagate up to other static libraries.\n"
+ " Due to the nature of how arflags are typically used, you will normally\n"
+ " want to apply them directly on static_library targets themselves.\n"
+ COMMON_ORDERING_HELP;
+
const char kArgs[] = "args";
const char kArgs_HelpShort[] =
"args: [string list] Arguments passed to an action.";
@@ -645,9 +664,16 @@ const char kCompleteStaticLib_Help[] =
" In some cases the static library might be the final desired output.\n"
" For example, you may be producing a static library for distribution to\n"
" third parties. In this case, the static library should include code\n"
- " for all dependencies in one complete package. Since GN does not unpack\n"
- " static libraries to forward their contents up the dependency chain,\n"
- " it is an error for complete static libraries to depend on other static\n"
+ " for all dependencies in one complete package. However, complete static\n"
+ " libraries themselves are never linked into other complete static\n"
+ " libraries. All complete static libraries are for distribution and\n"
+ " linking them in would cause code duplication in this case. If the\n"
+ " static library is not for distribution, it should not be complete.\n"
+ "\n"
+ " GN treats non-complete static libraries as source sets when they are\n"
+ " linked into complete static libraries. This is done because some tools\n"
+ " like AR do not handle dependent static libraries properly. This makes\n"
+ " it easier to write \"alink\" rules.\n"
"\n"
" In rare cases it makes sense to list a header in more than one\n"
" target if it could be considered conceptually a member of both.\n"
@@ -737,7 +763,7 @@ const char kConfigs_Help[] =
const char kConsole[] = "console";
const char kConsole_HelpShort[] =
- "console [boolean]: Run this action in the console pool.";
+ "console: [boolean] Run this action in the console pool.";
const char kConsole_Help[] =
"console: Run this action in the console pool.\n"
"\n"
@@ -781,7 +807,7 @@ const char kData_Help[] =
" generated files both in the \"outputs\" list as well as the \"data\"\n"
" list.\n"
"\n"
- " By convention, directories are be listed with a trailing slash:\n"
+ " By convention, directories are listed with a trailing slash:\n"
" data = [ \"test/data/\" ]\n"
" However, no verification is done on these so GN doesn't enforce this.\n"
" The paths are just rebased and passed along when requested.\n"
@@ -1119,6 +1145,34 @@ const char kOutputExtension_Help[] =
" }\n"
" }\n";
+const char kOutputDir[] = "output_dir";
+const char kOutputDir_HelpShort[] =
+ "output_dir: [directory] Directory to put output file in.";
+const char kOutputDir_Help[] =
+ "output_dir: [directory] Directory to put output file in.\n"
+ "\n"
+ " For library and executable targets, overrides the directory for the\n"
+ " final output. This must be in the root_build_dir or a child thereof.\n"
+ "\n"
+ " This should generally be in the root_out_dir or a subdirectory thereof\n"
+ " (the root_out_dir will be the same as the root_build_dir for the\n"
+ " default toolchain, and will be a subdirectory for other toolchains).\n"
+ " Not putting the output in a subdirectory of root_out_dir can result\n"
+ " in collisions between different toolchains, so you will need to take\n"
+ " steps to ensure that your target is only present in one toolchain.\n"
+ "\n"
+ " Normally the toolchain specifies the output directory for libraries\n"
+ " and executables (see \"gn help tool\"). You will have to consult that\n"
+ " for the default location. The default location will be used if\n"
+ " output_dir is undefined or empty.\n"
+ "\n"
+ "Example\n"
+ "\n"
+ " shared_library(\"doom_melon\") {\n"
+ " output_dir = \"$root_out_dir/plugin_libs\"\n"
+ " ...\n"
+ " }\n";
+
const char kOutputName[] = "output_name";
const char kOutputName_HelpShort[] =
"output_name: [string] Name for the output file other than the default.";
@@ -1272,6 +1326,19 @@ const char kPrecompiledSource_Help[] =
" using \"msvc\"-style precompiled headers. It will be implicitly added\n"
" to the sources of the target. See \"gn help precompiled_header\".\n";
+const char kProductType[] = "product_type";
+const char kProductType_HelpShort[] =
+ "product_type: [string] Product type for Xcode projects.";
+const char kProductType_Help[] =
+ "product_type: Product type for Xcode projects.\n"
+ "\n"
+ " Correspond to the type of the product of a create_bundle target. Only\n"
+ " meaningful to Xcode (used as part of the Xcode project generation).\n"
+ "\n"
+ " When generating Xcode project files, only create_bundle target with\n"
+ " a non-empty product_type will have a corresponding target in Xcode\n"
+ " project.\n";
+
const char kPublic[] = "public";
const char kPublic_HelpShort[] =
"public: [file list] Declare public header files for a target.";
@@ -1610,6 +1677,7 @@ const VariableInfoMap& GetTargetVariables() {
if (info_map.empty()) {
INSERT_VARIABLE(AllDependentConfigs)
INSERT_VARIABLE(AllowCircularIncludesFrom)
+ INSERT_VARIABLE(Arflags)
INSERT_VARIABLE(Args)
INSERT_VARIABLE(Asmflags)
INSERT_VARIABLE(AssertNoDeps)
@@ -1636,12 +1704,14 @@ const VariableInfoMap& GetTargetVariables() {
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(PrecompiledHeader)
INSERT_VARIABLE(PrecompiledSource)
+ INSERT_VARIABLE(ProductType)
INSERT_VARIABLE(Public)
INSERT_VARIABLE(PublicConfigs)
INSERT_VARIABLE(PublicDeps)
diff --git a/chromium/tools/gn/variables.h b/chromium/tools/gn/variables.h
index 08fea1ab82b..0aaa8e09a8d 100644
--- a/chromium/tools/gn/variables.h
+++ b/chromium/tools/gn/variables.h
@@ -79,6 +79,10 @@ 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[];
@@ -183,6 +187,10 @@ 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[];
@@ -207,6 +215,10 @@ 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[];
diff --git a/chromium/tools/gn/visual_studio_writer.cc b/chromium/tools/gn/visual_studio_writer.cc
index e0483465f2f..50d6878a5f1 100644
--- a/chromium/tools/gn/visual_studio_writer.cc
+++ b/chromium/tools/gn/visual_studio_writer.cc
@@ -5,13 +5,13 @@
#include "tools/gn/visual_studio_writer.h"
#include <algorithm>
+#include <iterator>
#include <map>
#include <memory>
#include <set>
#include <string>
#include "base/logging.h"
-#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "tools/gn/builder.h"
@@ -180,10 +180,22 @@ VisualStudioWriter::SolutionProject::SolutionProject(
const std::string& _config_platform)
: SolutionEntry(_name, _path, _guid),
label_dir_path(_label_dir_path),
- config_platform(_config_platform) {}
+ 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)
@@ -211,8 +223,6 @@ VisualStudioWriter::VisualStudioWriter(const BuildSettings* build_settings,
}
VisualStudioWriter::~VisualStudioWriter() {
- STLDeleteContainerPointers(projects_.begin(), projects_.end());
- STLDeleteContainerPointers(folders_.begin(), folders_.end());
}
// static
@@ -226,18 +236,10 @@ bool VisualStudioWriter::RunAndWriteFiles(const BuildSettings* build_settings,
if (dir_filters.empty()) {
targets = builder->GetAllResolvedTargets();
} else {
- std::vector<std::string> tokens = base::SplitString(
- dir_filters, ";", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
- SourceDir root_dir =
- SourceDirForCurrentDirectory(build_settings->root_path());
-
std::vector<LabelPattern> filters;
- for (const std::string& token : tokens) {
- LabelPattern pattern =
- LabelPattern::GetPattern(root_dir, Value(nullptr, token), err);
- if (err->has_error())
- return false;
- filters.push_back(pattern);
+ if (!commands::FilterPatternsFromString(build_settings, dir_filters,
+ &filters, err)) {
+ return false;
}
commands::FilterTargetsByPatterns(builder->GetAllResolvedTargets(), filters,
@@ -281,7 +283,8 @@ bool VisualStudioWriter::RunAndWriteFiles(const BuildSettings* build_settings,
// 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 SolutionEntry* a, const SolutionEntry* b) {
+ [](const std::unique_ptr<SolutionProject>& a,
+ const std::unique_ptr<SolutionProject>& b) {
return a->path < b->path;
});
@@ -310,15 +313,16 @@ bool VisualStudioWriter::WriteProjectFiles(const Target* target, Err* err) {
base::FilePath vcxproj_path = build_settings_->GetFullPath(target_file);
std::string vcxproj_path_str = FilePathToUTF8(vcxproj_path);
- projects_.push_back(new SolutionProject(
+ projects_.emplace_back(new 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,
- err)) {
+ &source_types, err)) {
projects_.pop_back();
return false;
}
@@ -331,7 +335,7 @@ bool VisualStudioWriter::WriteProjectFiles(const Target* target, Err* err) {
base::FilePath filters_path = UTF8ToFilePath(vcxproj_path_str + ".filters");
std::stringstream filters_string_out;
- WriteFiltersFileContents(filters_string_out, target);
+ WriteFiltersFileContents(filters_string_out, target, source_types);
return WriteFileIfChanged(filters_path, filters_string_out.str(), err);
}
@@ -339,6 +343,7 @@ bool VisualStudioWriter::WriteProjectFileContents(
std::ostream& out,
const SolutionProject& solution_project,
const Target* target,
+ SourceFileCompileTypePairs* source_types,
Err* err) {
PathOutput path_output(GetTargetOutputDir(target),
build_settings_->root_path_utf8(),
@@ -477,13 +482,7 @@ bool VisualStudioWriter::WriteProjectFileContents(
cl_compile->SubElement("MinimalRebuild")->Text("false");
if (!options.optimization.empty())
cl_compile->SubElement("Optimization")->Text(options.optimization);
- if (target->config_values().has_precompiled_headers()) {
- cl_compile->SubElement("PrecompiledHeader")->Text("Use");
- cl_compile->SubElement("PrecompiledHeaderFile")
- ->Text(target->config_values().precompiled_header());
- } else {
- cl_compile->SubElement("PrecompiledHeader")->Text("NotUsing");
- }
+ cl_compile->SubElement("PrecompiledHeader")->Text("NotUsing");
{
std::unique_ptr<XmlElementWriter> preprocessor_definitions =
cl_compile->SubElement("PreprocessorDefinitions");
@@ -508,22 +507,25 @@ bool VisualStudioWriter::WriteProjectFileContents(
{
std::unique_ptr<XmlElementWriter> group = project.SubElement("ItemGroup");
- if (!target->config_values().precompiled_source().is_null()) {
- group
- ->SubElement(
- "ClCompile", "Include",
- SourceFileWriter(path_output,
- target->config_values().precompiled_source()))
- ->SubElement("PrecompiledHeader")
- ->Text("Create");
- }
+ std::vector<OutputFile> tool_outputs; // Prevent reallocation in loop.
for (const SourceFile& file : target->sources()) {
- SourceFileType type = GetSourceFileType(file);
- if (type == SOURCE_H || type == SOURCE_CPP || type == SOURCE_C) {
- group->SubElement(type == SOURCE_H ? "ClInclude" : "ClCompile",
- "Include", SourceFileWriter(path_output, file));
+ 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) " +
+ 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));
}
}
@@ -558,8 +560,10 @@ bool VisualStudioWriter::WriteProjectFileContents(
return true;
}
-void VisualStudioWriter::WriteFiltersFileContents(std::ostream& out,
- const Target* target) {
+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",
@@ -585,35 +589,31 @@ void VisualStudioWriter::WriteFiltersFileContents(std::ostream& out,
std::set<std::string> processed_filters;
- for (const SourceFile& file : target->sources()) {
- SourceFileType type = GetSourceFileType(file);
- if (type == SOURCE_H || type == SOURCE_CPP || type == SOURCE_C) {
- std::unique_ptr<XmlElementWriter> cl_item = files_group.SubElement(
- type == SOURCE_H ? "ClInclude" : "ClCompile", "Include",
- SourceFileWriter(file_path_output, file));
-
- std::ostringstream target_relative_out;
- filter_path_output.WriteFile(target_relative_out, 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);
+ 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);
}
}
}
@@ -648,14 +648,14 @@ void VisualStudioWriter::WriteSolutionFileContents(
out << "# " << version_string_ << std::endl;
SourceDir solution_dir(FilePathToUTF8(solution_dir_path));
- for (const SolutionEntry* folder : folders_) {
+ 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 SolutionEntry* project : projects_) {
+ for (const std::unique_ptr<SolutionProject>& project : projects_) {
out << "Project(\"" << kGuidTypeProject << "\") = \"" << project->name
<< "\", \"" << RebasePath(project->path, solution_dir) << "\", \""
<< project->guid << "\"" << std::endl;
@@ -673,7 +673,7 @@ void VisualStudioWriter::WriteSolutionFileContents(
out << "\tGlobalSection(ProjectConfigurationPlatforms) = postSolution"
<< std::endl;
- for (const SolutionProject* project : projects_) {
+ 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
@@ -688,13 +688,13 @@ void VisualStudioWriter::WriteSolutionFileContents(
out << "\tEndGlobalSection" << std::endl;
out << "\tGlobalSection(NestedProjects) = preSolution" << std::endl;
- for (const SolutionEntry* folder : folders_) {
+ 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 SolutionEntry* project : projects_) {
+ for (const std::unique_ptr<SolutionProject>& project : projects_) {
out << "\t\t" << project->guid << " = " << project->parent_folder->guid
<< std::endl;
}
@@ -708,7 +708,7 @@ void VisualStudioWriter::ResolveSolutionFolders() {
// Get all project directories. Create solution folder for each directory.
std::map<base::StringPiece, SolutionEntry*> processed_paths;
- for (SolutionProject* project : projects_) {
+ 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);
@@ -717,12 +717,12 @@ void VisualStudioWriter::ResolveSolutionFolders() {
project->parent_folder = it->second;
} else {
std::string folder_path_str = folder_path.as_string();
- SolutionEntry* folder = new SolutionEntry(
+ std::unique_ptr<SolutionEntry> folder(new SolutionEntry(
FindLastDirComponent(SourceDir(folder_path)).as_string(),
- folder_path_str, MakeGuid(folder_path_str, kGuidSeedFolder));
- folders_.push_back(folder);
- project->parent_folder = folder;
- processed_paths[folder_path] = folder;
+ 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;
@@ -751,38 +751,42 @@ void VisualStudioWriter::ResolveSolutionFolders() {
// Create also all parent folders up to |root_folder_path_|.
SolutionFolders additional_folders;
- for (SolutionEntry* folder : folders_) {
- if (folder->path == root_folder_path_)
+ 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 {
- folder = new SolutionEntry(
+ std::unique_ptr<SolutionEntry> new_folder(new SolutionEntry(
FindLastDirComponent(SourceDir(parent_path)).as_string(),
parent_path.as_string(),
- MakeGuid(parent_path.as_string(), kGuidSeedFolder));
- additional_folders.push_back(folder);
- processed_paths[parent_path] = folder;
+ 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(), additional_folders.begin(),
- additional_folders.end());
+ 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 SolutionEntry* a, const SolutionEntry* b) {
+ [](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.
- SolutionFolders parents;
- for (SolutionEntry* folder : folders_) {
+ 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)) {
@@ -792,7 +796,7 @@ void VisualStudioWriter::ResolveSolutionFolders() {
parents.pop_back();
}
}
- parents.push_back(folder);
+ parents.push_back(folder.get());
}
}
diff --git a/chromium/tools/gn/visual_studio_writer.h b/chromium/tools/gn/visual_studio_writer.h
index 5b578ed3cba..99c537075ff 100644
--- a/chromium/tools/gn/visual_studio_writer.h
+++ b/chromium/tools/gn/visual_studio_writer.h
@@ -6,6 +6,7 @@
#define TOOLS_GN_VISUAL_STUDIO_WRITER_H_
#include <iosfwd>
+#include <memory>
#include <string>
#include <vector>
@@ -20,6 +21,7 @@ class FilePath;
class Builder;
class BuildSettings;
class Err;
+class SourceFile;
class Target;
class VisualStudioWriter {
@@ -77,8 +79,19 @@ class VisualStudioWriter {
std::string config_platform;
};
- using SolutionProjects = std::vector<SolutionProject*>;
- using SolutionFolders = std::vector<SolutionEntry*>;
+ 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,
@@ -89,8 +102,11 @@ class VisualStudioWriter {
bool WriteProjectFileContents(std::ostream& out,
const SolutionProject& solution_project,
const Target* target,
+ SourceFileCompileTypePairs* source_types,
Err* err);
- void WriteFiltersFileContents(std::ostream& out, const Target* target);
+ 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);
diff --git a/chromium/tools/gn/visual_studio_writer_unittest.cc b/chromium/tools/gn/visual_studio_writer_unittest.cc
index d70117fd0c2..f89c1c193f3 100644
--- a/chromium/tools/gn/visual_studio_writer_unittest.cc
+++ b/chromium/tools/gn/visual_studio_writer_unittest.cc
@@ -4,6 +4,7 @@
#include "tools/gn/visual_studio_writer.h"
+#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"
@@ -31,22 +32,22 @@ TEST_F(VisualStudioWriterTest, ResolveSolutionFolders) {
std::string path =
MakeTestPath("/foo/chromium/src/out/Debug/obj/base/base.vcxproj");
- writer.projects_.push_back(new VisualStudioWriter::SolutionProject(
+ writer.projects_.emplace_back(new 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(new VisualStudioWriter::SolutionProject(
+ writer.projects_.emplace_back(new 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(new VisualStudioWriter::SolutionProject(
+ writer.projects_.emplace_back(new 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(new VisualStudioWriter::SolutionProject(
+ writer.projects_.emplace_back(new VisualStudioWriter::SolutionProject(
"bar", path, MakeGuid(path, "project"),
MakeTestPath("/foo/chromium/src/base"), "Win32"));
@@ -71,12 +72,12 @@ TEST_F(VisualStudioWriterTest, ResolveSolutionFolders) {
ASSERT_EQ("gn", writer.folders_[3]->name);
ASSERT_EQ(MakeTestPath("/foo/chromium/src/tools/gn"),
writer.folders_[3]->path);
- ASSERT_EQ(writer.folders_[2], writer.folders_[3]->parent_folder);
+ ASSERT_EQ(writer.folders_[2].get(), writer.folders_[3]->parent_folder);
- ASSERT_EQ(writer.folders_[0], writer.projects_[0]->parent_folder);
- ASSERT_EQ(writer.folders_[3], writer.projects_[1]->parent_folder);
- ASSERT_EQ(writer.folders_[1], writer.projects_[2]->parent_folder);
- ASSERT_EQ(writer.folders_[0], writer.projects_[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) {
@@ -85,26 +86,30 @@ TEST_F(VisualStudioWriterTest, ResolveSolutionFolders_AbsPath) {
std::string path =
MakeTestPath("/foo/chromium/src/out/Debug/obj/base/base.vcxproj");
- writer.projects_.push_back(new VisualStudioWriter::SolutionProject(
+ writer.projects_.emplace_back(new 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(new VisualStudioWriter::SolutionProject(
+ writer.projects_.emplace_back(new 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(new VisualStudioWriter::SolutionProject(
+ writer.projects_.emplace_back(new 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(new VisualStudioWriter::SolutionProject(
- "baz", path, MakeGuid(path, "project"), MakeTestPath("/foo/bar/baz"),
- "Win32"));
+ writer.projects_.emplace_back(new VisualStudioWriter::SolutionProject(
+ "baz", path, MakeGuid(path, "project"), baz_label_dir_path, "Win32"));
writer.ResolveSolutionFolders();
@@ -118,7 +123,7 @@ TEST_F(VisualStudioWriterTest, ResolveSolutionFolders_AbsPath) {
ASSERT_EQ("baz", writer.folders_[1]->name);
ASSERT_EQ(MakeTestPath("/foo/bar/baz"), writer.folders_[1]->path);
- ASSERT_EQ(writer.folders_[0], writer.folders_[1]->parent_folder);
+ 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);
@@ -126,23 +131,23 @@ TEST_F(VisualStudioWriterTest, ResolveSolutionFolders_AbsPath) {
ASSERT_EQ("src", writer.folders_[3]->name);
ASSERT_EQ(MakeTestPath("/foo/chromium/src"), writer.folders_[3]->path);
- ASSERT_EQ(writer.folders_[2], writer.folders_[3]->parent_folder);
+ 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], writer.folders_[4]->parent_folder);
+ 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], writer.folders_[5]->parent_folder);
+ 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], writer.folders_[6]->parent_folder);
+ ASSERT_EQ(writer.folders_[5].get(), writer.folders_[6]->parent_folder);
- ASSERT_EQ(writer.folders_[4], writer.projects_[0]->parent_folder);
- ASSERT_EQ(writer.folders_[6], writer.projects_[1]->parent_folder);
- ASSERT_EQ(writer.folders_[0], writer.projects_[2]->parent_folder);
- ASSERT_EQ(writer.folders_[1], writer.projects_[3]->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
new file mode 100644
index 00000000000..bc8994409fe
--- /dev/null
+++ b/chromium/tools/gn/xcode_object.cc
@@ -0,0 +1,858 @@
+// 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 <sstream>
+#include <utility>
+
+#include "base/files/file_path.h"
+#include "base/logging.h"
+#include "base/memory/ptr_util.h"
+#include "base/strings/string_util.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();
+}
+
+const char* GetSourceType(const base::FilePath::StringType& ext) {
+ std::map<base::FilePath::StringType, const char*> extension_map = {
+ {FILE_PATH_LITERAL(".a"), "archive.ar"},
+ {FILE_PATH_LITERAL(".app"), "wrapper.application"},
+ {FILE_PATH_LITERAL(".bdic"), "file"},
+ {FILE_PATH_LITERAL(".bundle"), "wrapper.cfbundle"},
+ {FILE_PATH_LITERAL(".c"), "sourcecode.c.c"},
+ {FILE_PATH_LITERAL(".cc"), "sourcecode.cpp.cpp"},
+ {FILE_PATH_LITERAL(".cpp"), "sourcecode.cpp.cpp"},
+ {FILE_PATH_LITERAL(".css"), "text.css"},
+ {FILE_PATH_LITERAL(".cxx"), "sourcecode.cpp.cpp"},
+ {FILE_PATH_LITERAL(".dart"), "sourcecode"},
+ {FILE_PATH_LITERAL(".dylib"), "compiled.mach-o.dylib"},
+ {FILE_PATH_LITERAL(".framework"), "wrapper.framework"},
+ {FILE_PATH_LITERAL(".h"), "sourcecode.c.h"},
+ {FILE_PATH_LITERAL(".hxx"), "sourcecode.cpp.h"},
+ {FILE_PATH_LITERAL(".icns"), "image.icns"},
+ {FILE_PATH_LITERAL(".java"), "sourcecode.java"},
+ {FILE_PATH_LITERAL(".js"), "sourcecode.javascript"},
+ {FILE_PATH_LITERAL(".kext"), "wrapper.kext"},
+ {FILE_PATH_LITERAL(".m"), "sourcecode.c.objc"},
+ {FILE_PATH_LITERAL(".mm"), "sourcecode.cpp.objcpp"},
+ {FILE_PATH_LITERAL(".nib"), "wrapper.nib"},
+ {FILE_PATH_LITERAL(".o"), "compiled.mach-o.objfile"},
+ {FILE_PATH_LITERAL(".pdf"), "image.pdf"},
+ {FILE_PATH_LITERAL(".pl"), "text.script.perl"},
+ {FILE_PATH_LITERAL(".plist"), "text.plist.xml"},
+ {FILE_PATH_LITERAL(".pm"), "text.script.perl"},
+ {FILE_PATH_LITERAL(".png"), "image.png"},
+ {FILE_PATH_LITERAL(".py"), "text.script.python"},
+ {FILE_PATH_LITERAL(".r"), "sourcecode.rez"},
+ {FILE_PATH_LITERAL(".rez"), "sourcecode.rez"},
+ {FILE_PATH_LITERAL(".s"), "sourcecode.asm"},
+ {FILE_PATH_LITERAL(".storyboard"), "file.storyboard"},
+ {FILE_PATH_LITERAL(".strings"), "text.plist.strings"},
+ {FILE_PATH_LITERAL(".swift"), "sourcecode.swift"},
+ {FILE_PATH_LITERAL(".ttf"), "file"},
+ {FILE_PATH_LITERAL(".xcassets"), "folder.assetcatalog"},
+ {FILE_PATH_LITERAL(".xcconfig"), "text.xcconfig"},
+ {FILE_PATH_LITERAL(".xcdatamodel"), "wrapper.xcdatamodel"},
+ {FILE_PATH_LITERAL(".xcdatamodeld"), "wrapper.xcdatamodeld"},
+ {FILE_PATH_LITERAL(".xib"), "file.xib"},
+ {FILE_PATH_LITERAL(".y"), "sourcecode.yacc"},
+ };
+
+ const auto& iter = extension_map.find(ext);
+ if (iter != extension_map.end()) {
+ return iter->second;
+ }
+
+ return "text";
+}
+
+bool HasExplicitFileType(const base::FilePath::StringType& ext) {
+ return ext == FILE_PATH_LITERAL(".dart");
+}
+
+bool IsSourceFileForIndexing(const base::FilePath::StringType& ext) {
+ return ext == FILE_PATH_LITERAL(".c") || ext == FILE_PATH_LITERAL(".cc") ||
+ ext == FILE_PATH_LITERAL(".cpp") || ext == FILE_PATH_LITERAL(".cxx") ||
+ ext == FILE_PATH_LITERAL(".m") || ext == FILE_PATH_LITERAL(".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 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 XCBuildConfigurationClass:
+ return "XCBuildConfiguration";
+ case XCConfigurationListClass:
+ return "XCConfigurationList";
+ }
+ NOTREACHED();
+ return nullptr;
+}
+
+// PBXObjectVisitor -----------------------------------------------------------
+
+PBXObjectVisitor::PBXObjectVisitor() {}
+
+PBXObjectVisitor::~PBXObjectVisitor() {}
+
+// PBXObject ------------------------------------------------------------------
+
+PBXObject::PBXObject() {}
+
+PBXObject::~PBXObject() {}
+
+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() {}
+
+PBXBuildPhase::~PBXBuildPhase() {}
+
+// 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(
+ base::WrapUnique(new PBXShellScriptBuildPhase(name, shell_script)));
+ }
+}
+
+PBXTarget::~PBXTarget() {}
+
+std::string PBXTarget::Name() const {
+ return name_;
+}
+
+void PBXTarget::Visit(PBXObjectVisitor& visitor) {
+ PBXObject::Visit(visitor);
+ configurations_->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() {}
+
+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)
+ : file_reference_(file_reference), build_phase_(build_phase) {
+ DCHECK(file_reference_);
+ DCHECK(build_phase_);
+}
+
+PBXBuildFile::~PBXBuildFile() {}
+
+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_);
+ out << "};\n";
+}
+
+// PBXFileReference -----------------------------------------------------------
+
+PBXFileReference::PBXFileReference(const std::string& name,
+ const std::string& path,
+ const std::string& type)
+ : name_(name), path_(path), type_(type) {}
+
+PBXFileReference::~PBXFileReference() {}
+
+PBXObjectClass PBXFileReference::Class() const {
+ return PBXFileReferenceClass;
+}
+
+std::string PBXFileReference::Name() const {
+ return path_;
+}
+
+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 {
+ const base::FilePath::StringType ext =
+ base::FilePath::FromUTF8Unsafe(path_).Extension();
+
+ if (HasExplicitFileType(ext))
+ PrintProperty(out, rules, "explicitFileType", GetSourceType(ext));
+ else
+ PrintProperty(out, rules, "lastKnownFileType", GetSourceType(ext));
+ }
+
+ if (name_ != path_ && !name_.empty())
+ PrintProperty(out, rules, "name", name_);
+
+ PrintProperty(out, rules, "path", path_);
+ PrintProperty(out, rules, "sourceTree",
+ type_.empty() ? "<group>" : "BUILT_PRODUCTS_DIR");
+ out << "};\n";
+}
+
+// PBXFrameworksBuildPhase ----------------------------------------------------
+
+PBXFrameworksBuildPhase::PBXFrameworksBuildPhase() {}
+
+PBXFrameworksBuildPhase::~PBXFrameworksBuildPhase() {}
+
+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() {}
+
+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& source_path) {
+ DCHECK(!source_path.empty());
+ std::string::size_type sep = source_path.find("/");
+ if (sep == std::string::npos) {
+ children_.push_back(base::WrapUnique(
+ new PBXFileReference(std::string(), source_path, std::string())));
+ return static_cast<PBXFileReference*>(children_.back().get());
+ }
+
+ PBXGroup* group = nullptr;
+ base::StringPiece component(source_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->path_ == component) {
+ group = child_as_group;
+ break;
+ }
+ }
+
+ if (!group) {
+ children_.push_back(base::WrapUnique(new PBXGroup(component.as_string())));
+ group = static_cast<PBXGroup*>(children_.back().get());
+ }
+
+ DCHECK(group);
+ DCHECK(group->path_ == component);
+ return group->AddSourceFile(source_path.substr(sep + 1));
+}
+
+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 (!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 PBXFileReference* product_reference)
+ : PBXTarget(name, shell_script, config_name, attributes),
+ product_reference_(product_reference),
+ product_type_(product_type) {
+ DCHECK(product_reference_);
+ build_phases_.push_back(base::WrapUnique(new PBXSourcesBuildPhase));
+ source_build_phase_ =
+ static_cast<PBXSourcesBuildPhase*>(build_phases_.back().get());
+
+ build_phases_.push_back(base::WrapUnique(new PBXFrameworksBuildPhase));
+}
+
+PBXNativeTarget::~PBXNativeTarget() {}
+
+void PBXNativeTarget::AddFileForIndexing(
+ const PBXFileReference* file_reference) {
+ DCHECK(file_reference);
+ source_build_phase_->AddBuildFile(
+ base::WrapUnique(new PBXBuildFile(file_reference, source_build_phase_)));
+}
+
+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", EmptyPBXObjectVector());
+ PrintProperty(out, rules, "name", name_);
+ PrintProperty(out, rules, "productName", 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(
+ base::WrapUnique(new PBXGroup(source_path, "Source"))));
+ products_ = static_cast<PBXGroup*>(main_group_->AddChild(
+ base::WrapUnique(new PBXGroup(std::string(), "Product"))));
+ main_group_->AddChild(base::WrapUnique(new PBXGroup(std::string(), "Build")));
+
+ configurations_.reset(new XCConfigurationList(config_name, attributes, this));
+}
+
+PBXProject::~PBXProject() {}
+
+void PBXProject::AddSourceFile(const std::string& source_path) {
+ PBXFileReference* file_reference = sources_->AddSourceFile(source_path);
+ const base::FilePath::StringType ext =
+ base::FilePath::FromUTF8Unsafe(source_path).Extension();
+ if (!IsSourceFileForIndexing(ext))
+ return;
+
+ if (!target_for_indexing_) {
+ PBXAttributes attributes;
+ attributes["EXECUTABLE_PREFIX"] = "";
+ attributes["HEADER_SEARCH_PATHS"] = sources_->path();
+ attributes["PRODUCT_NAME"] = name_;
+
+ PBXFileReference* product_reference = static_cast<PBXFileReference*>(
+ products_->AddChild(base::WrapUnique(new PBXFileReference(
+ std::string(), name_, "compiled.mach-o.executable"))));
+
+ const char product_type[] = "com.apple.product-type.tool";
+ targets_.push_back(base::WrapUnique(
+ new PBXNativeTarget(name_, std::string(), config_name_, attributes,
+ product_type, product_reference)));
+ target_for_indexing_ = static_cast<PBXNativeTarget*>(targets_.back().get());
+ }
+
+ DCHECK(target_for_indexing_);
+ target_for_indexing_->AddFileForIndexing(file_reference);
+}
+
+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(base::WrapUnique(
+ new PBXAggregateTarget(name, shell_script, config_name_, attributes)));
+}
+
+void 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 base::FilePath::StringType ext =
+ base::FilePath::FromUTF8Unsafe(output_name).Extension();
+
+ PBXFileReference* product = static_cast<PBXFileReference*>(
+ products_->AddChild(base::WrapUnique(new PBXFileReference(
+ name, output_name, type.empty() ? GetSourceType(ext) : type))));
+
+ PBXAttributes attributes;
+ attributes["CODE_SIGNING_REQUIRED"] = "NO";
+ attributes["CONFIGURATION_BUILD_DIR"] = ".";
+ attributes["PRODUCT_NAME"] = name;
+
+ targets_.push_back(base::WrapUnique(new PBXNativeTarget(
+ name, shell_script, config_name_, attributes, output_type, product)));
+}
+
+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() {}
+
+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() {}
+
+PBXSourcesBuildPhase::~PBXSourcesBuildPhase() {}
+
+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";
+}
+
+// XCBuildConfiguration -------------------------------------------------------
+
+XCBuildConfiguration::XCBuildConfiguration(const std::string& name,
+ const PBXAttributes& attributes)
+ : attributes_(attributes), name_(name) {}
+
+XCBuildConfiguration::~XCBuildConfiguration() {}
+
+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(
+ base::WrapUnique(new XCBuildConfiguration(name, attributes)));
+}
+
+XCConfigurationList::~XCConfigurationList() {}
+
+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
new file mode 100644
index 00000000000..25f2415f516
--- /dev/null
+++ b/chromium/tools/gn/xcode_object.h
@@ -0,0 +1,392 @@
+// 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.
+
+// PBXObjectClass -------------------------------------------------------------
+
+enum PBXObjectClass {
+ // Those values needs to stay sorted in alphabetic order.
+ PBXAggregateTargetClass,
+ PBXBuildFileClass,
+ PBXFileReferenceClass,
+ PBXFrameworksBuildPhaseClass,
+ PBXGroupClass,
+ PBXNativeTargetClass,
+ PBXProjectClass,
+ PBXShellScriptBuildPhaseClass,
+ PBXSourcesBuildPhaseClass,
+ XCBuildConfigurationClass,
+ XCConfigurationListClass,
+};
+
+const char* ToString(PBXObjectClass cls);
+
+// Forward-declarations -------------------------------------------------------
+
+class PBXAggregateTarget;
+class PBXBuildFile;
+class PBXFileReference;
+class PBXBuildPhase;
+class PBXFrameworksBuildPhase;
+class PBXGroup;
+class PBXNativeTarget;
+class PBXObject;
+class PBXProject;
+class PBXShellScriptBuildPhase;
+class PBXSourcesBuildPhase;
+class PBXTarget;
+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;
+
+ // PXBObject 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_;
+ 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;
+
+ // PXBObject 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);
+ ~PBXBuildFile() override;
+
+ // PXBObject 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_;
+
+ DISALLOW_COPY_AND_ASSIGN(PBXBuildFile);
+};
+
+// 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;
+
+ 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& source_path);
+
+ // 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_;
+
+ 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 PBXFileReference* product_reference);
+ ~PBXNativeTarget() override;
+
+ void AddFileForIndexing(const PBXFileReference* file_reference);
+
+ // PBXObject implementation.
+ PBXObjectClass Class() const override;
+ void Print(std::ostream& out, unsigned indent) const override;
+
+ private:
+ const PBXFileReference* product_reference_;
+ std::string product_type_;
+
+ 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 AddSourceFile(const std::string& source_path);
+ void AddAggregateTarget(const std::string& name,
+ const std::string& shell_script);
+ void AddNativeTarget(const std::string& name,
+ const std::string& type,
+ const std::string& output_name,
+ const std::string& output_type,
+ const std::string& shell_script);
+
+ 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);
+};
+
+// 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_writer.cc b/chromium/tools/gn/xcode_writer.cc
new file mode 100644
index 00000000000..4168f7f068d
--- /dev/null
+++ b/chromium/tools/gn/xcode_writer.cc
@@ -0,0 +1,432 @@
+// 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 {
+
+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 GetArchs(const Args& args) {
+ const Value* target_cpu_value = args.GetArgOverride(variables::kTargetCpu);
+ if (target_cpu_value) {
+ if (target_cpu_value->type() == Value::STRING) {
+ if (target_cpu_value->string_value() == "x86")
+ return "i386";
+ if (target_cpu_value->string_value() == "x64")
+ return "x86_64";
+ if (target_cpu_value->string_value() == "arm")
+ return "armv7";
+ if (target_cpu_value->string_value() == "armv7")
+ return "armv7";
+ if (target_cpu_value->string_value() == "arm64")
+ return "armv64";
+ }
+ }
+ return "x86_64";
+}
+
+std::string GetBuildScript(const std::string& target_name,
+ const std::string& build_path,
+ const std::string& ninja_extra_args) {
+ std::stringstream script;
+ script << "echo note: \"Compile and copy " << target_name << " via ninja\"\n"
+ << "exec ";
+ if (!build_path.empty())
+ script << "env PATH=\"" << build_path << "\" ";
+ 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();
+}
+
+class CollectPBXObjectsPerClassHelper : public PBXObjectVisitor {
+ public:
+ CollectPBXObjectsPerClassHelper() {}
+
+ 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,
+ 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["ARCHS"] = GetArchs(build_settings->build_args());
+ attributes["SDKROOT"] = "macosx10.11";
+ 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, attributes, source_path, config_name,
+ root_target_name, ninja_extra_args,
+ target_os);
+
+ workspace.CreateSourcesProject(all_targets, build_settings->build_dir(),
+ attributes, source_path, config_name,
+ target_os);
+
+ return workspace.WriteFiles(build_settings, err);
+}
+
+XcodeWriter::XcodeWriter(const std::string& name) : name_(name) {
+ if (name_.empty())
+ name_.assign("all");
+}
+
+XcodeWriter::~XcodeWriter() {}
+
+// 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 PBXAttributes& attributes,
+ const std::string& source_path,
+ const std::string& config_name,
+ const std::string& root_target,
+ const std::string& ninja_extra_args,
+ TargetOsType target_os) {
+ std::unique_ptr<PBXProject> main_project(
+ new PBXProject("products", config_name, source_path, attributes));
+
+ std::string build_path;
+ std::unique_ptr<base::Environment> env(base::Environment::Create());
+ env->GetVar("PATH", &build_path);
+
+ main_project->AddAggregateTarget(
+ "All", GetBuildScript(root_target, build_path, ninja_extra_args));
+
+ 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(), build_path,
+ ninja_extra_args));
+ break;
+
+ case Target::CREATE_BUNDLE:
+ if (target->bundle_data().product_type().empty())
+ continue;
+
+ main_project->AddNativeTarget(
+ target->label().name(), std::string(),
+ target->bundle_data()
+ .GetBundleRootDirOutput(target->settings())
+ .Resolve(base::FilePath())
+ .AsUTF8Unsafe(),
+ target->bundle_data().product_type(),
+ GetBuildScript(target->label().name(), build_path,
+ ninja_extra_args));
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ projects_.push_back(std::move(main_project));
+}
+
+void XcodeWriter::CreateSourcesProject(
+ const std::vector<const Target*>& targets,
+ const SourceDir& root_build_dir,
+ const PBXAttributes& attributes,
+ const std::string& source_path,
+ const std::string& config_name,
+ TargetOsType target_os) {
+ std::vector<SourceFile> sources;
+ for (const Target* target : targets) {
+ if (!target->settings()->is_default())
+ continue;
+
+ for (const SourceFile& source : target->sources()) {
+ if (source.is_system_absolute())
+ continue;
+
+ if (IsStringInOutputDir(root_build_dir, source.value()))
+ continue;
+
+ sources.push_back(source);
+ }
+ }
+
+ std::unique_ptr<PBXProject> sources_for_indexing(
+ new PBXProject("sources", config_name, source_path, attributes));
+
+ // Sort sources to ensure determinisn 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) {
+ base::FilePath source_path = source.Resolve(base::FilePath());
+ sources_for_indexing->AddSourceFile(source_path.AsUTF8Unsafe());
+ }
+
+ projects_.push_back(std::move(sources_for_indexing));
+}
+
+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 (const 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
new file mode 100644
index 00000000000..dd162c65f89
--- /dev/null
+++ b/chromium/tools/gn/xcode_writer.h
@@ -0,0 +1,97 @@
+// 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 SourceDir;
+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,
+ 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 PBXAttributes& attributes,
+ const std::string& source_path,
+ const std::string& config_name,
+ const std::string& root_target,
+ const std::string& ninja_extra_args,
+ TargetOsType target_os);
+
+ // Generates the "sources.xcodeproj" project that reference all source
+ // files to allow Xcode to index them.
+ void CreateSourcesProject(const std::vector<const Target*>& targets,
+ const SourceDir& root_build_dir,
+ const PBXAttributes& attributes,
+ const std::string& source_path,
+ const std::string& config_name,
+ 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/grit/OWNERS b/chromium/tools/grit/OWNERS
index 5a9431a7735..40b5c310ad5 100644
--- a/chromium/tools/grit/OWNERS
+++ b/chromium/tools/grit/OWNERS
@@ -1,4 +1,3 @@
flackr@chromium.org
-newt@chromium.org
thakis@chromium.org
thestig@chromium.org
diff --git a/chromium/tools/grit/grit_rule.gni b/chromium/tools/grit/grit_rule.gni
index 90c0b00abbf..07d8f3aebf9 100644
--- a/chromium/tools/grit/grit_rule.gni
+++ b/chromium/tools/grit/grit_rule.gni
@@ -159,13 +159,6 @@ if (use_nss_certs) {
]
}
-if (use_nss_verifier) {
- grit_defines += [
- "-D",
- "use_nss_verifier",
- ]
-}
-
if (use_ozone) {
grit_defines += [
"-D",
diff --git a/chromium/tools/gritsettings/resource_ids b/chromium/tools/gritsettings/resource_ids
index b790c724ce5..5c46a2647f8 100644
--- a/chromium/tools/gritsettings/resource_ids
+++ b/chromium/tools/gritsettings/resource_ids
@@ -64,6 +64,9 @@
"includes": [6100],
"structures": [6150],
},
+ "ash/wm/common/resources/ash_wm_common_resources.grd": {
+ "structures": [6700],
+ },
"ui/keyboard/keyboard_resources.grd": {
"includes": [6850],
},
@@ -175,6 +178,11 @@
"content/content_resources.grd": {
"includes": [23950],
},
+ # ios_web strings and content strings must start at the same id.
+ # App only use one file depending on whether it is iOS or other platform.
+ "ios/web/ios_web_resources.grd": {
+ "includes": [23950],
+ },
"content/shell/shell_resources.grd": {
"includes": [24450],
},
diff --git a/chromium/tools/gyp/pylib/gyp/MSVSSettings.py b/chromium/tools/gyp/pylib/gyp/MSVSSettings.py
index 4985756bdde..8ae19180ea2 100644
--- a/chromium/tools/gyp/pylib/gyp/MSVSSettings.py
+++ b/chromium/tools/gyp/pylib/gyp/MSVSSettings.py
@@ -592,6 +592,7 @@ _Same(_compile, 'UndefinePreprocessorDefinitions', _string_list) # /U
_Same(_compile, 'UseFullPaths', _boolean) # /FC
_Same(_compile, 'WholeProgramOptimization', _boolean) # /GL
_Same(_compile, 'XMLDocumentationFileName', _file_name)
+_Same(_compile, 'CompileAsWinRT', _boolean) # /ZW
_Same(_compile, 'AssemblerOutput',
_Enumeration(['NoListing',
diff --git a/chromium/tools/gyp/pylib/gyp/generator/msvs.py b/chromium/tools/gyp/pylib/gyp/generator/msvs.py
index bc4dfc31247..e60c0256312 100644
--- a/chromium/tools/gyp/pylib/gyp/generator/msvs.py
+++ b/chromium/tools/gyp/pylib/gyp/generator/msvs.py
@@ -257,6 +257,8 @@ def _ToolSetOrAppend(tools, tool_name, setting, value, only_if_unset=False):
if not tools.get(tool_name):
tools[tool_name] = dict()
tool = tools[tool_name]
+ if 'CompileAsWinRT' == setting:
+ return
if tool.get(setting):
if only_if_unset: return
if type(tool[setting]) == list and type(value) == list:
@@ -286,6 +288,21 @@ def _ConfigFullName(config_name, config_data):
return '%s|%s' % (_ConfigBaseName(config_name, platform_name), platform_name)
+def _ConfigWindowsTargetPlatformVersion(config_data):
+ ver = config_data.get('msvs_windows_sdk_version')
+
+ for key in [r'HKLM\Software\Microsoft\Microsoft SDKs\Windows\%s',
+ r'HKLM\Software\Wow6432Node\Microsoft\Microsoft SDKs\Windows\%s']:
+ sdk_dir = MSVSVersion._RegistryGetValue(key % ver, 'InstallationFolder')
+ if not sdk_dir:
+ continue
+ version = MSVSVersion._RegistryGetValue(key % ver, 'ProductVersion') or ''
+ # Find a matching entry in sdk_dir\include.
+ names = sorted([x for x in os.listdir(r'%s\include' % sdk_dir)
+ if x.startswith(version)], reverse=True)
+ return names[0]
+
+
def _BuildCommandLineForRuleRaw(spec, cmd, cygwin_shell, has_input_path,
quote_cmd, do_setup_env):
@@ -2676,6 +2693,21 @@ def _GetMSBuildGlobalProperties(spec, guid, gyp_file_name):
else:
properties[0].append(['ApplicationType', 'Windows Store'])
+ platform_name = None
+ msvs_windows_sdk_version = None
+ for configuration in spec['configurations'].itervalues():
+ platform_name = platform_name or _ConfigPlatform(configuration)
+ msvs_windows_sdk_version = (msvs_windows_sdk_version or
+ _ConfigWindowsTargetPlatformVersion(configuration))
+ if platform_name and msvs_windows_sdk_version:
+ break
+
+ if platform_name == 'ARM':
+ properties[0].append(['WindowsSDKDesktopARMSupport', 'true'])
+ if msvs_windows_sdk_version:
+ properties[0].append(['WindowsTargetPlatformVersion',
+ str(msvs_windows_sdk_version)])
+
return properties
def _GetMSBuildConfigurationDetails(spec, build_file):
diff --git a/chromium/tools/gyp/pylib/gyp/generator/ninja.py b/chromium/tools/gyp/pylib/gyp/generator/ninja.py
index edac48dfca4..9cfc7060b5c 100644
--- a/chromium/tools/gyp/pylib/gyp/generator/ninja.py
+++ b/chromium/tools/gyp/pylib/gyp/generator/ninja.py
@@ -1369,7 +1369,8 @@ class NinjaWriter(object):
is_command_start=not package_framework)
if package_framework and not is_empty:
if spec['type'] == 'shared_library' and self.xcode_settings.isIOS:
- self.ninja.build(output, 'package_ios_framework', mac_bundle_depends)
+ self.ninja.build(output, 'package_ios_framework', mac_bundle_depends,
+ variables=variables)
else:
variables.append(('version', self.xcode_settings.GetFrameworkVersion()))
self.ninja.build(output, 'package_framework', mac_bundle_depends,
diff --git a/chromium/tools/gyp/pylib/gyp/generator/xcode.py b/chromium/tools/gyp/pylib/gyp/generator/xcode.py
index 0e3fb9301ec..db99d6ab81e 100644
--- a/chromium/tools/gyp/pylib/gyp/generator/xcode.py
+++ b/chromium/tools/gyp/pylib/gyp/generator/xcode.py
@@ -77,6 +77,7 @@ generator_additional_non_configuration_keys = [
'mac_framework_headers',
'mac_framework_private_headers',
'mac_xctest_bundle',
+ 'mac_xcuitest_bundle',
'xcode_create_dependents_test_runner',
]
@@ -691,6 +692,7 @@ def GenerateOutput(target_list, target_dicts, data, params):
'executable+bundle': 'com.apple.product-type.application',
'loadable_module+bundle': 'com.apple.product-type.bundle',
'loadable_module+xctest': 'com.apple.product-type.bundle.unit-test',
+ 'loadable_module+xcuitest': 'com.apple.product-type.bundle.ui-testing',
'shared_library+bundle': 'com.apple.product-type.framework',
'executable+extension+bundle': 'com.apple.product-type.app-extension',
'executable+watch+extension+bundle':
@@ -707,13 +709,19 @@ def GenerateOutput(target_list, target_dicts, data, params):
type = spec['type']
is_xctest = int(spec.get('mac_xctest_bundle', 0))
+ is_xcuitest = int(spec.get('mac_xcuitest_bundle', 0))
is_bundle = int(spec.get('mac_bundle', 0)) or is_xctest
is_app_extension = int(spec.get('ios_app_extension', 0))
is_watchkit_extension = int(spec.get('ios_watchkit_extension', 0))
is_watch_app = int(spec.get('ios_watch_app', 0))
if type != 'none':
type_bundle_key = type
- if is_xctest:
+ if is_xcuitest:
+ type_bundle_key += '+xcuitest'
+ assert type == 'loadable_module', (
+ 'mac_xcuitest_bundle targets must have type loadable_module '
+ '(target %s)' % target_name)
+ elif is_xctest:
type_bundle_key += '+xctest'
assert type == 'loadable_module', (
'mac_xctest_bundle targets must have type loadable_module '
@@ -745,6 +753,9 @@ def GenerateOutput(target_list, target_dicts, data, params):
assert not is_bundle, (
'mac_bundle targets cannot have type none (target "%s")' %
target_name)
+ assert not is_xcuitest, (
+ 'mac_xcuitest_bundle targets cannot have type none (target "%s")' %
+ target_name)
assert not is_xctest, (
'mac_xctest_bundle targets cannot have type none (target "%s")' %
target_name)
diff --git a/chromium/tools/gyp/pylib/gyp/mac_tool.py b/chromium/tools/gyp/pylib/gyp/mac_tool.py
index 32aba14fe76..e33c1d1273d 100755
--- a/chromium/tools/gyp/pylib/gyp/mac_tool.py
+++ b/chromium/tools/gyp/pylib/gyp/mac_tool.py
@@ -405,7 +405,7 @@ class MacTool(object):
self._MergePlist(merged_plist, plist)
plistlib.writePlist(merged_plist, output)
- def ExecCodeSignBundle(self, key, entitlements, provisioning):
+ def ExecCodeSignBundle(self, key, entitlements, provisioning, path, preserve):
"""Code sign a bundle.
This function tries to code sign an iOS bundle, following the same
@@ -419,11 +419,14 @@ class MacTool(object):
provisioning, self._GetCFBundleIdentifier())
entitlements_path = self._InstallEntitlements(
entitlements, substitutions, overrides)
- subprocess.check_call([
- 'codesign', '--force', '--sign', key, '--entitlements',
- entitlements_path, '--timestamp=none', os.path.join(
- os.environ['TARGET_BUILD_DIR'],
- os.environ['FULL_PRODUCT_NAME'])])
+
+ args = ['codesign', '--force', '--sign', key]
+ if preserve == 'True':
+ args.extend(['--deep', '--preserve-metadata=identifier,entitlements'])
+ else:
+ args.extend(['--entitlements', entitlements_path])
+ args.extend(['--timestamp=none', path])
+ subprocess.check_call(args)
def _InstallProvisioningProfile(self, profile, bundle_identifier):
"""Installs embedded.mobileprovision into the bundle.
@@ -639,7 +642,7 @@ class MacTool(object):
return data
def NextGreaterPowerOf2(x):
- return 2**(x-1).bit_length()
+ return 2**(x).bit_length()
def WriteHmap(output_name, filelist):
"""Generates a header map based on |filelist|.
diff --git a/chromium/tools/gyp/pylib/gyp/win_tool.py b/chromium/tools/gyp/pylib/gyp/win_tool.py
index bb6f1ea436f..1c843a0b6cf 100755
--- a/chromium/tools/gyp/pylib/gyp/win_tool.py
+++ b/chromium/tools/gyp/pylib/gyp/win_tool.py
@@ -116,11 +116,19 @@ class WinTool(object):
env = self._GetEnv(arch)
if use_separate_mspdbsrv == 'True':
self._UseSeparateMspdbsrv(env, args)
- link = subprocess.Popen([args[0].replace('/', '\\')] + list(args[1:]),
- shell=True,
- env=env,
- stdout=subprocess.PIPE,
- stderr=subprocess.STDOUT)
+ if sys.platform == 'win32':
+ args = list(args) # *args is a tuple by default, which is read-only.
+ args[0] = args[0].replace('/', '\\')
+ # https://docs.python.org/2/library/subprocess.html:
+ # "On Unix with shell=True [...] if args is a sequence, the first item
+ # specifies the command string, and any additional items will be treated as
+ # additional arguments to the shell itself. That is to say, Popen does the
+ # equivalent of:
+ # Popen(['/bin/sh', '-c', args[0], args[1], ...])"
+ # For that reason, since going through the shell doesn't seem necessary on
+ # non-Windows don't do that there.
+ link = subprocess.Popen(args, shell=sys.platform == 'win32', env=env,
+ stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
out, _ = link.communicate()
for line in out.splitlines():
if (not line.startswith(' Creating library ') and
diff --git a/chromium/tools/gyp/pylib/gyp/xcode_emulation.py b/chromium/tools/gyp/pylib/gyp/xcode_emulation.py
index 2dec19e5d6f..048511a2690 100644
--- a/chromium/tools/gyp/pylib/gyp/xcode_emulation.py
+++ b/chromium/tools/gyp/pylib/gyp/xcode_emulation.py
@@ -229,11 +229,15 @@ class XcodeSettings(object):
self.isIOS
def _IsBundle(self):
- return int(self.spec.get('mac_bundle', 0)) != 0 or self._IsXCTest()
+ return int(self.spec.get('mac_bundle', 0)) != 0 or self._IsXCTest() or \
+ self._IsXCUiTest()
def _IsXCTest(self):
return int(self.spec.get('mac_xctest_bundle', 0)) != 0
+ def _IsXCUiTest(self):
+ return int(self.spec.get('mac_xcuitest_bundle', 0)) != 0
+
def _IsIosAppExtension(self):
return int(self.spec.get('ios_app_extension', 0)) != 0
@@ -312,7 +316,8 @@ class XcodeSettings(object):
"""Returns the qualified path to the bundle's plist file. E.g.
Chromium.app/Contents/Info.plist. Only valid for bundles."""
assert self._IsBundle()
- if self.spec['type'] in ('executable', 'loadable_module'):
+ if self.spec['type'] in ('executable', 'loadable_module') or \
+ self.IsIosFramework():
return os.path.join(self.GetBundleContentsFolderPath(), 'Info.plist')
else:
return os.path.join(self.GetBundleContentsFolderPath(),
@@ -332,6 +337,10 @@ class XcodeSettings(object):
assert self._IsBundle(), ('ios_watch_app flag requires mac_bundle '
'(target %s)' % self.spec['target_name'])
return 'com.apple.product-type.application.watchapp'
+ if self._IsXCUiTest():
+ assert self._IsBundle(), ('mac_xcuitest_bundle flag requires mac_bundle '
+ '(target %s)' % self.spec['target_name'])
+ return 'com.apple.product-type.bundle.ui-testing'
if self._IsBundle():
return {
'executable': 'com.apple.product-type.application',
@@ -839,7 +848,8 @@ class XcodeSettings(object):
ldflags.append('-arch ' + archs[0])
# Xcode adds the product directory by default.
- ldflags.append('-L' + product_dir)
+ # Rewrite -L. to -L./ to work around http://www.openradar.me/25313838
+ ldflags.append('-L' + (product_dir if product_dir != '.' else './'))
install_name = self.GetInstallName()
if install_name and self.spec['type'] != 'loadable_module':
@@ -1008,10 +1018,20 @@ class XcodeSettings(object):
self.IsIosFramework()):
return []
+ postbuilds = []
+ product_name = self.GetFullProductName()
settings = self.xcode_settings[configname]
+
+ # Xcode expects XCTests to be copied into the TEST_HOST dir.
+ if self._IsXCTest():
+ source = os.path.join("${BUILT_PRODUCTS_DIR}", product_name)
+ test_host = os.path.dirname(settings.get('TEST_HOST'));
+ xctest_destination = os.path.join(test_host, 'PlugIns', product_name)
+ postbuilds.extend(['ditto %s %s' % (source, xctest_destination)])
+
key = self._GetIOSCodeSignIdentityKey(settings)
if not key:
- return []
+ return postbuilds
# Warn for any unimplemented signing xcode keys.
unimpl = ['OTHER_CODE_SIGN_FLAGS']
@@ -1020,11 +1040,41 @@ class XcodeSettings(object):
print 'Warning: Some codesign keys not implemented, ignoring: %s' % (
', '.join(sorted(unimpl)))
- return ['%s code-sign-bundle "%s" "%s" "%s"' % (
+ if self._IsXCTest():
+ # For device xctests, Xcode copies two extra frameworks into $TEST_HOST.
+ test_host = os.path.dirname(settings.get('TEST_HOST'));
+ frameworks_dir = os.path.join(test_host, 'Frameworks')
+ platform_root = self._XcodePlatformPath(configname)
+ frameworks = \
+ ['Developer/Library/PrivateFrameworks/IDEBundleInjection.framework',
+ 'Developer/Library/Frameworks/XCTest.framework']
+ for framework in frameworks:
+ source = os.path.join(platform_root, framework)
+ destination = os.path.join(frameworks_dir, os.path.basename(framework))
+ postbuilds.extend(['ditto %s %s' % (source, destination)])
+
+ # Then re-sign everything with 'preserve=True'
+ postbuilds.extend(['%s code-sign-bundle "%s" "%s" "%s" "%s" %s' % (
+ os.path.join('${TARGET_BUILD_DIR}', 'gyp-mac-tool'), key,
+ settings.get('CODE_SIGN_ENTITLEMENTS', ''),
+ settings.get('PROVISIONING_PROFILE', ''), destination, True)
+ ])
+ plugin_dir = os.path.join(test_host, 'PlugIns')
+ targets = [os.path.join(plugin_dir, product_name), test_host]
+ for target in targets:
+ postbuilds.extend(['%s code-sign-bundle "%s" "%s" "%s" "%s" %s' % (
+ os.path.join('${TARGET_BUILD_DIR}', 'gyp-mac-tool'), key,
+ settings.get('CODE_SIGN_ENTITLEMENTS', ''),
+ settings.get('PROVISIONING_PROFILE', ''), target, True)
+ ])
+
+ postbuilds.extend(['%s code-sign-bundle "%s" "%s" "%s" "%s" %s' % (
os.path.join('${TARGET_BUILD_DIR}', 'gyp-mac-tool'), key,
settings.get('CODE_SIGN_ENTITLEMENTS', ''),
- settings.get('PROVISIONING_PROFILE', ''))
- ]
+ settings.get('PROVISIONING_PROFILE', ''),
+ os.path.join("${BUILT_PRODUCTS_DIR}", product_name), False)
+ ])
+ return postbuilds
def _GetIOSCodeSignIdentityKey(self, settings):
identity = settings.get('CODE_SIGN_IDENTITY')
@@ -1379,6 +1429,7 @@ def IsMacBundle(flavor, spec):
just a single file. Bundle rules do not produce a binary but also package
resources into that directory."""
is_mac_bundle = int(spec.get('mac_xctest_bundle', 0)) != 0 or \
+ int(spec.get('mac_xcuitest_bundle', 0)) != 0 or \
(int(spec.get('mac_bundle', 0)) != 0 and flavor == 'mac')
if is_mac_bundle:
diff --git a/chromium/tools/gyp/pylib/gyp/xcodeproj_file.py b/chromium/tools/gyp/pylib/gyp/xcodeproj_file.py
index d08b7f77700..1bc90c7d6d8 100644
--- a/chromium/tools/gyp/pylib/gyp/xcodeproj_file.py
+++ b/chromium/tools/gyp/pylib/gyp/xcodeproj_file.py
@@ -2261,6 +2261,8 @@ class PBXNativeTarget(XCTarget):
'', ''],
'com.apple.product-type.bundle.unit-test': ['wrapper.cfbundle',
'', '.xctest'],
+ 'com.apple.product-type.bundle.ui-testing': ['wrapper.cfbundle',
+ '', '.xctest'],
'com.googlecode.gyp.xcode.bundle': ['compiled.mach-o.dylib',
'', '.so'],
'com.apple.product-type.kernel-extension': ['wrapper.kext',
@@ -2317,7 +2319,9 @@ class PBXNativeTarget(XCTarget):
force_extension = suffix[1:]
if self._properties['productType'] == \
- 'com.apple.product-type-bundle.unit.test':
+ 'com.apple.product-type-bundle.unit.test' or \
+ self._properties['productType'] == \
+ 'com.apple.product-type-bundle.ui-testing':
if force_extension is None:
force_extension = suffix[1:]
diff --git a/chromium/tools/gyp/test/ios/framework/framework.gyp b/chromium/tools/gyp/test/ios/framework/framework.gyp
index a99079226d4..2c6fdd5b272 100644
--- a/chromium/tools/gyp/test/ios/framework/framework.gyp
+++ b/chromium/tools/gyp/test/ios/framework/framework.gyp
@@ -10,6 +10,8 @@
'mac_bundle': 1,
'sources': [
'iOSFramework/iOSFramework.h',
+ 'iOSFramework/Thing.h',
+ 'iOSFramework/Thing.m',
],
'link_settings': {
'libraries': [
@@ -18,7 +20,9 @@
],
},
'mac_framework_headers': [
+ # Using two headers here tests mac_tool.py NextGreaterPowerOf2.
'iOSFramework/iOSFramework.h',
+ 'iOSFramework/Thing.h',
],
'mac_framework_dirs': [
'$(SDKROOT)/../../Library/Frameworks',
diff --git a/chromium/tools/gyp/test/mac/xcuitest/test.gyp b/chromium/tools/gyp/test/mac/xcuitest/test.gyp
new file mode 100644
index 00000000000..80cdf9032d0
--- /dev/null
+++ b/chromium/tools/gyp/test/mac/xcuitest/test.gyp
@@ -0,0 +1,69 @@
+# Copyright (c) 2013 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'target_defaults': {
+ 'xcode_settings': {
+ 'SDKROOT': 'iphoneos',
+ 'FRAMEWORK_SEARCH_PATHS': [
+ '$(inherited)',
+ '$(DEVELOPER_FRAMEWORKS_DIR)',
+ ],
+ 'OTHER_LDFLAGS': [
+ '$(inherited)',
+ '-ObjC',
+ ],
+ 'GCC_PREFIX_HEADER': '',
+ 'CLANG_ENABLE_OBJC_ARC': 'YES',
+ 'INFOPLIST_FILE': 'Info.plist',
+ },
+ },
+ 'targets': [
+ {
+ 'target_name': 'testApp',
+ 'type': 'executable',
+ 'mac_bundle': 1,
+ 'sources': [
+ 'MyAppDelegate.h',
+ 'MyAppDelegate.m',
+ 'main.m',
+ ],
+ 'link_settings': {
+ 'libraries': [
+ '$(SDKROOT)/System/Library/Frameworks/Foundation.framework',
+ '$(SDKROOT)/System/Library/Frameworks/UIKit.framework',
+ ],
+ },
+ },
+ {
+ 'target_name': 'tests',
+ 'type': 'loadable_module',
+ 'mac_bundle': 1,
+ 'mac_xcuitest_bundle': 1,
+ 'sources': [
+ 'TestCase.m',
+ ],
+ 'dependencies': [
+ 'testApp',
+ ],
+ 'mac_bundle_resources': [
+ 'resource.txt',
+ ],
+ 'variables': {
+ # This must *not* be set for xctest ui tests.
+ 'xctest_host': '',
+ },
+ 'link_settings': {
+ 'libraries': [
+ '$(SDKROOT)/System/Library/Frameworks/XCTest.framework',
+ ]
+ },
+ 'xcode_settings': {
+ 'WRAPPER_EXTENSION': 'xctest',
+ 'TEST_TARGET_NAME': 'testApp',
+ },
+ },
+ ],
+}
+
diff --git a/chromium/tools/gyp/test/win/compiler-flags/compile-as-winrt.gyp b/chromium/tools/gyp/test/win/compiler-flags/compile-as-winrt.gyp
new file mode 100644
index 00000000000..8978e5059de
--- /dev/null
+++ b/chromium/tools/gyp/test/win/compiler-flags/compile-as-winrt.gyp
@@ -0,0 +1,20 @@
+# Copyright (c) 2016 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'targets': [
+ {
+ 'target_name': 'test-compile-as-winrt',
+ 'type': 'executable',
+ 'msvs_windows_sdk_version': 'v10.0',
+ 'msvs_settings': {
+ 'VCCLCompilerTool': {
+ 'AdditionalUsingDirectories': ['$(VCInstallDir)vcpackages;$(WindowsSdkDir)UnionMetadata;%(AdditionalUsingDirectories)'],
+ 'CompileAsWinRT': 'true'
+ }
+ },
+ 'sources': ['compile-as-winrt.cc']
+ }
+ ]
+}
diff --git a/chromium/tools/idl_parser/OWNERS b/chromium/tools/idl_parser/OWNERS
new file mode 100644
index 00000000000..c5e87c09a35
--- /dev/null
+++ b/chromium/tools/idl_parser/OWNERS
@@ -0,0 +1,3 @@
+bashi@chromium.org
+haraken@chromium.org
+yukishiino@chromium.org
diff --git a/chromium/tools/idl_parser/idl_parser.py b/chromium/tools/idl_parser/idl_parser.py
index 45f8d7c5827..ff787a46346 100755
--- a/chromium/tools/idl_parser/idl_parser.py
+++ b/chromium/tools/idl_parser/idl_parser.py
@@ -554,14 +554,12 @@ class IDLParser(object):
# [36]
def p_StringifierRest(self, p):
- """StringifierRest : AttributeRest
+ """StringifierRest : ReadOnly AttributeRest
| ReturnType OperationRest
| ';'"""
if len(p) == 3:
p[2].AddChildren(p[1])
p[0] = p[2]
- elif p[1] != ';':
- p[0] = p[1]
# [37]
def p_StaticMember(self, p):
diff --git a/chromium/tools/imagediff/BUILD.gn b/chromium/tools/imagediff/BUILD.gn
index 7688cfea54b..9273106f288 100644
--- a/chromium/tools/imagediff/BUILD.gn
+++ b/chromium/tools/imagediff/BUILD.gn
@@ -2,20 +2,31 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-executable("imagediff") {
- output_name = "image_diff" # Different than dir nam for historical reasons.
- sources = [
- "image_diff.cc",
- "image_diff_png.cc",
- "image_diff_png.h",
- ]
+import("//build/symlink.gni")
- configs += [ "//build/config/compiler:wexit_time_destructors" ]
+if (current_toolchain == host_toolchain) {
+ executable("imagediff") {
+ output_name = "image_diff" # Different than dir nam for historical reasons.
+ sources = [
+ "image_diff.cc",
+ "image_diff_png.cc",
+ "image_diff_png.h",
+ ]
- deps = [
- "//base",
- "//build/config/sanitizers:deps",
- "//third_party/libpng",
- "//third_party/zlib",
- ]
+ configs += [ "//build/config/compiler:wexit_time_destructors" ]
+
+ deps = [
+ "//base",
+ "//build/config/sanitizers:deps",
+ "//build/win:default_exe_manifest",
+ "//third_party/libpng",
+ "//third_party/zlib",
+ ]
+ }
+} else {
+ # Aliases for compatibility with GYP.
+ binary_symlink("imagediff") {
+ binary_label = ":$target_name($host_toolchain)"
+ binary_output_name = "image_diff"
+ }
}
diff --git a/chromium/tools/include_tracer.py b/chromium/tools/include_tracer.py
index 567a79765f8..30061d79a6b 100755
--- a/chromium/tools/include_tracer.py
+++ b/chromium/tools/include_tracer.py
@@ -112,7 +112,6 @@ INCLUDE_PATHS = [
'third_party/WebKit/Source/public',
'third_party/WebKit/Source/web',
'third_party/WebKit/Source/wtf',
- 'third_party/cld',
'third_party/google_toolbox_for_mac/src',
'third_party/icu/public/common',
'third_party/icu/public/i18n',
diff --git a/chromium/tools/ipc_fuzzer/BUILD.gn b/chromium/tools/ipc_fuzzer/BUILD.gn
new file mode 100644
index 00000000000..ce31589d31e
--- /dev/null
+++ b/chromium/tools/ipc_fuzzer/BUILD.gn
@@ -0,0 +1,37 @@
+# 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.
+
+import("//tools/ipc_fuzzer/ipc_fuzzer.gni")
+
+config("ipc_fuzzer_config") {
+ defines = [ "ENABLE_IPC_FUZZER" ]
+}
+
+config("ipc_fuzzer_tool_config") {
+ if (is_win) {
+ cflags = [ "/wd4366" ]
+ }
+ defines = [
+ "ENABLE_IPC_FUZZER",
+ "USE_CUPS",
+ ]
+ include_dirs = [ "." ]
+}
+
+if (enable_ipc_fuzzer) {
+ assert(!is_component_build, "IPC fuzzer does not support component builds.")
+
+ group("ipc_fuzzer_all") {
+ deps = [
+ "//tools/ipc_fuzzer/fuzzer:ipc_fuzzer",
+ "//tools/ipc_fuzzer/message_dump:ipc_message_dump",
+ "//tools/ipc_fuzzer/message_replay:ipc_fuzzer_replay",
+ "//tools/ipc_fuzzer/message_tools:ipc_message_list",
+ "//tools/ipc_fuzzer/message_tools:ipc_message_util",
+ ]
+ }
+} else {
+ group("ipc_fuzzer_all") {
+ }
+}
diff --git a/chromium/tools/ipc_fuzzer/fuzzer/BUILD.gn b/chromium/tools/ipc_fuzzer/fuzzer/BUILD.gn
new file mode 100644
index 00000000000..6a1dc836fee
--- /dev/null
+++ b/chromium/tools/ipc_fuzzer/fuzzer/BUILD.gn
@@ -0,0 +1,28 @@
+# 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.
+
+import("//build/config/sanitizers/sanitizers.gni")
+
+executable("ipc_fuzzer") {
+ configs += [ "//tools/ipc_fuzzer:ipc_fuzzer_tool_config" ]
+ sources = [
+ "fuzzer.cc",
+ "fuzzer.h",
+ "fuzzer_main.cc",
+ "generator.cc",
+ "generator.h",
+ "mutator.cc",
+ "mutator.h",
+ "rand_util.cc",
+ "rand_util.h",
+ ]
+ deps = [
+ "//tools/ipc_fuzzer/message_lib:ipc_message_lib",
+ ]
+ if (is_asan && is_chromeos) {
+ # Compiling fuzzer.cc with ASan takes too long, see
+ # http://crbug.com/360158.
+ config -= [ "//build/config/sanitizers:default_sanitizer_flags" ]
+ }
+}
diff --git a/chromium/tools/ipc_fuzzer/fuzzer/fuzzer.cc b/chromium/tools/ipc_fuzzer/fuzzer/fuzzer.cc
index c1fb9d2e446..8f970dfe5be 100644
--- a/chromium/tools/ipc_fuzzer/fuzzer/fuzzer.cc
+++ b/chromium/tools/ipc_fuzzer/fuzzer/fuzzer.cc
@@ -1253,17 +1253,6 @@ struct FuzzTraits<gpu::MailboxHolder> {
};
template <>
-struct FuzzTraits<gpu::ValueState> {
- static bool Fuzz(gpu::ValueState* p, Fuzzer* fuzzer) {
- if (!FuzzParamArray(&p->float_value[0], 4, fuzzer))
- return false;
- if (!FuzzParamArray(&p->int_value[0], 4, fuzzer))
- return false;
- return true;
- }
-};
-
-template <>
struct FuzzTraits<GURL> {
static bool Fuzz(GURL* p, Fuzzer* fuzzer) {
if (!fuzzer->ShouldGenerate()) {
@@ -1481,15 +1470,27 @@ struct FuzzTraits<net::HostPortPair> {
};
template <>
+struct FuzzTraits<net::IPAddress> {
+ static bool Fuzz(net::IPAddress* p, Fuzzer* fuzzer) {
+ std::vector<uint8_t> bytes = p->bytes();
+ if (!FuzzParam(&bytes, fuzzer))
+ return false;
+ net::IPAddress ip_address(bytes);
+ *p = ip_address;
+ return true;
+ }
+};
+
+template <>
struct FuzzTraits<net::IPEndPoint> {
static bool Fuzz(net::IPEndPoint* p, Fuzzer* fuzzer) {
- net::IPAddressNumber address_number = p->address().bytes();
+ net::IPAddress ip_address = p->address();
int port = p->port();
- if (!FuzzParam(&address_number, fuzzer))
+ if (!FuzzParam(&ip_address, fuzzer))
return false;
if (!FuzzParam(&port, fuzzer))
return false;
- net::IPEndPoint ip_endpoint(address_number, port);
+ net::IPEndPoint ip_endpoint(ip_address, port);
*p = ip_endpoint;
return true;
}
diff --git a/chromium/tools/ipc_fuzzer/ipc_fuzzer.gni b/chromium/tools/ipc_fuzzer/ipc_fuzzer.gni
new file mode 100644
index 00000000000..f4f41ac523e
--- /dev/null
+++ b/chromium/tools/ipc_fuzzer/ipc_fuzzer.gni
@@ -0,0 +1,16 @@
+# 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.
+
+import("//build/config/chrome_build.gni")
+import("//build/config/chromecast_build.gni")
+import("//build/config/sanitizers/sanitizers.gni")
+
+declare_args() {
+ # Build IPC fuzzer by default if it's a supported configuration. For
+ # sanitizer builds, this needs to be enabled explicitly as they can be slow
+ # (especially MSan).
+ enable_ipc_fuzzer =
+ is_clang && !is_component_build && !is_official_build && !is_chromecast &&
+ !using_sanitizer && (is_linux || is_mac || is_win)
+}
diff --git a/chromium/tools/ipc_fuzzer/message_dump/BUILD.gn b/chromium/tools/ipc_fuzzer/message_dump/BUILD.gn
new file mode 100644
index 00000000000..756652cbf9b
--- /dev/null
+++ b/chromium/tools/ipc_fuzzer/message_dump/BUILD.gn
@@ -0,0 +1,13 @@
+# 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.
+
+loadable_module("ipc_message_dump") {
+ configs += [ "//tools/ipc_fuzzer:ipc_fuzzer_tool_config" ]
+ deps = [
+ "//tools/ipc_fuzzer/message_lib:ipc_message_lib",
+ ]
+ sources = [
+ "message_dump.cc",
+ ]
+}
diff --git a/chromium/tools/ipc_fuzzer/message_lib/BUILD.gn b/chromium/tools/ipc_fuzzer/message_lib/BUILD.gn
new file mode 100644
index 00000000000..f6a20169cc2
--- /dev/null
+++ b/chromium/tools/ipc_fuzzer/message_lib/BUILD.gn
@@ -0,0 +1,44 @@
+# 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.
+
+import("//build/config/features.gni")
+
+static_library("ipc_message_lib") {
+ configs += [ "//tools/ipc_fuzzer:ipc_fuzzer_tool_config" ]
+ public_deps = [
+ "//base",
+ "//chrome/common",
+ "//chrome/common/safe_browsing:proto",
+ "//components/content_settings/content/common",
+ "//components/network_hints/common",
+ "//components/page_load_metrics/common",
+ "//components/pdf/common",
+ "//components/tracing",
+ "//content/child",
+ "//content/public/child",
+ "//ipc",
+ "//media/cast:net",
+ "//ppapi/proxy:ipc",
+ "//skia",
+ "//third_party/WebKit/public:blink",
+ "//third_party/WebKit/public:blink_headers",
+ "//third_party/libjingle",
+ "//third_party/mt19937ar",
+ "//ui/accessibility:ax_gen",
+ ]
+ sources = [
+ "all_messages.h",
+ "message_cracker.h",
+ "message_file.h",
+ "message_file_format.h",
+ "message_file_reader.cc",
+ "message_file_writer.cc",
+ "message_names.cc",
+ "message_names.h",
+ ]
+
+ if (enable_nacl) {
+ public_deps += [ "//components/nacl/common" ]
+ }
+}
diff --git a/chromium/tools/ipc_fuzzer/message_lib/DEPS b/chromium/tools/ipc_fuzzer/message_lib/DEPS
index b2aa99957dd..46cdff245d7 100644
--- a/chromium/tools/ipc_fuzzer/message_lib/DEPS
+++ b/chromium/tools/ipc_fuzzer/message_lib/DEPS
@@ -5,6 +5,7 @@ include_rules = [
"+components/dns_prefetch/common",
"+components/nacl/common",
"+components/network_hints/common",
+ "+components/page_load_metrics/common",
"+components/password_manager/content/common",
"+components/pdf/common",
"+components/tracing",
diff --git a/chromium/tools/ipc_fuzzer/message_lib/all_messages.h b/chromium/tools/ipc_fuzzer/message_lib/all_messages.h
index cc601787f88..6cead53f176 100644
--- a/chromium/tools/ipc_fuzzer/message_lib/all_messages.h
+++ b/chromium/tools/ipc_fuzzer/message_lib/all_messages.h
@@ -19,7 +19,7 @@
#include "components/content_settings/content/common/content_settings_message_generator.h"
#include "components/nacl/common/nacl_host_messages.h"
#include "components/network_hints/common/network_hints_message_generator.h"
-#include "components/password_manager/content/common/credential_manager_message_generator.h"
+#include "components/page_load_metrics/common/page_load_metrics_messages.h"
#include "components/pdf/common/pdf_message_generator.h"
#include "components/tracing/tracing_messages.h"
#include "components/translate/content/common/translate_messages.h"
diff --git a/chromium/tools/ipc_fuzzer/message_lib/message_lib.gyp b/chromium/tools/ipc_fuzzer/message_lib/message_lib.gyp
index 56ccce07f3b..cf9d18beb33 100644
--- a/chromium/tools/ipc_fuzzer/message_lib/message_lib.gyp
+++ b/chromium/tools/ipc_fuzzer/message_lib/message_lib.gyp
@@ -11,13 +11,13 @@
'../../../chrome/chrome.gyp:safe_browsing_proto',
'../../../components/components.gyp:content_settings_content_common',
'../../../components/components.gyp:network_hints_common',
+ '../../../components/components.gyp:page_load_metrics_common',
'../../../components/components.gyp:pdf_common',
'../../../components/nacl.gyp:nacl_common',
'../../../content/content.gyp:content_child',
'../../../ipc/ipc.gyp:ipc',
'../../../media/cast/cast.gyp:cast_net',
'../../../ppapi/ppapi_internal.gyp:ppapi_ipc',
- '../../../remoting/remoting.gyp:remoting_host',
'../../../skia/skia.gyp:skia',
'../../../third_party/libjingle/libjingle.gyp:libjingle',
'../../../third_party/mt19937ar/mt19937ar.gyp:mt19937ar',
diff --git a/chromium/tools/ipc_fuzzer/message_replay/BUILD.gn b/chromium/tools/ipc_fuzzer/message_replay/BUILD.gn
new file mode 100644
index 00000000000..b1ec352669a
--- /dev/null
+++ b/chromium/tools/ipc_fuzzer/message_replay/BUILD.gn
@@ -0,0 +1,16 @@
+# 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.
+
+executable("ipc_fuzzer_replay") {
+ configs += [ "//tools/ipc_fuzzer:ipc_fuzzer_tool_config" ]
+ deps = [
+ "//ipc/mojo",
+ "//tools/ipc_fuzzer/message_lib:ipc_message_lib",
+ ]
+ sources = [
+ "replay.cc",
+ "replay_process.cc",
+ "replay_process.h",
+ ]
+}
diff --git a/chromium/tools/ipc_fuzzer/message_replay/replay_process.cc b/chromium/tools/ipc_fuzzer/message_replay/replay_process.cc
index 54b56de8f10..dcee5c77d59 100644
--- a/chromium/tools/ipc_fuzzer/message_replay/replay_process.cc
+++ b/chromium/tools/ipc_fuzzer/message_replay/replay_process.cc
@@ -105,8 +105,7 @@ void ReplayProcess::OpenChannel() {
std::string process_type =
base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
switches::kProcessType);
- bool should_use_mojo = process_type == switches::kRendererProcess &&
- content::ShouldUseMojoChannel();
+ bool should_use_mojo = process_type == switches::kRendererProcess;
if (should_use_mojo) {
std::string token =
base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
diff --git a/chromium/tools/ipc_fuzzer/message_tools/BUILD.gn b/chromium/tools/ipc_fuzzer/message_tools/BUILD.gn
new file mode 100644
index 00000000000..dad44ffd65a
--- /dev/null
+++ b/chromium/tools/ipc_fuzzer/message_tools/BUILD.gn
@@ -0,0 +1,25 @@
+# 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.
+
+executable("ipc_message_util") {
+ configs += [ "//tools/ipc_fuzzer:ipc_fuzzer_tool_config" ]
+ deps = [
+ "//third_party/re2",
+ "//tools/ipc_fuzzer/message_lib:ipc_message_lib",
+ ]
+ sources = [
+ "message_util.cc",
+ ]
+}
+
+executable("ipc_message_list") {
+ configs += [ "//tools/ipc_fuzzer:ipc_fuzzer_tool_config" ]
+ deps = [
+ "//chrome/common/safe_browsing:proto",
+ "//tools/ipc_fuzzer/message_lib:ipc_message_lib",
+ ]
+ sources = [
+ "message_list.cc",
+ ]
+}
diff --git a/chromium/tools/json_schema_compiler/cc_generator.py b/chromium/tools/json_schema_compiler/cc_generator.py
index 0904e39b366..267d9fe8f10 100644
--- a/chromium/tools/json_schema_compiler/cc_generator.py
+++ b/chromium/tools/json_schema_compiler/cc_generator.py
@@ -43,6 +43,7 @@ class _Generator(object):
.Append()
.Append(self._util_cc_helper.GetIncludePath())
.Append('#include "base/logging.h"')
+ .Append('#include "base/memory/ptr_util.h"')
.Append('#include "base/strings/string_number_conversions.h"')
.Append('#include "base/strings/utf_string_conversions.h"')
.Append('#include "%s/%s.h"' %
@@ -317,7 +318,7 @@ class _Generator(object):
c.Append('const base::DictionaryValue* dict = '
'static_cast<const base::DictionaryValue*>(&value);')
if self._generate_error_messages:
- c.Append('std::set<std::string> keys;')
+ c.Append('std::set<std::string> keys;')
for prop in type_.properties.itervalues():
c.Concat(self._InitializePropertyToDefault(prop, 'out'))
for prop in type_.properties.itervalues():
@@ -508,20 +509,12 @@ class _Generator(object):
# Enums cannot be wrapped with scoped_ptr, but the XXX_NONE enum value
# is equal to 0.
(c.Sblock('if (%s) {' % choice_var)
- .Append('DCHECK(!result) << "Cannot set multiple choices for %s";' %
- type_.unix_name)
- .Cblock(self._CreateValueFromType('result.reset(%s);',
- choice.name,
- choice,
- choice_var,
- True))
- .Eblock('}')
- )
+ .Append('DCHECK(!result) << "Cannot set multiple choices for %s";' %
+ type_.unix_name).Cblock(self._CreateValueFromType(
+ 'result = %s;', choice.name, choice, choice_var, True))
+ .Eblock('}'))
(c.Append('DCHECK(result) << "Must set at least one choice for %s";' %
- type_.unix_name)
- .Append('return result;')
- .Eblock('}')
- )
+ type_.unix_name).Append('return result;').Eblock('}'))
return c
def _GenerateFunction(self, function):
@@ -570,7 +563,7 @@ class _Generator(object):
def _CreateValueFromType(self, code, prop_name, type_, var, is_ptr=False):
"""Creates a base::Value given a type. Generated code passes ownership
- to caller.
+ to caller via std::unique_ptr.
var: variable or variable*
@@ -624,21 +617,22 @@ class _Generator(object):
if (underlying_type.property_type == PropertyType.CHOICES or
underlying_type.property_type == PropertyType.OBJECT):
if is_ptr:
- return '(%s)->ToValue().release()' % var
+ return '(%s)->ToValue()' % var
else:
- return '(%s).ToValue().release()' % var
+ return '(%s).ToValue()' % var
elif (underlying_type.property_type == PropertyType.ANY or
underlying_type.property_type == PropertyType.FUNCTION):
if is_ptr:
vardot = '(%s)->' % var
else:
vardot = '(%s).' % var
- return '%sDeepCopy()' % vardot
+ return '%sCreateDeepCopy()' % vardot
elif underlying_type.property_type == PropertyType.ENUM:
maybe_namespace = ''
if type_.property_type == PropertyType.REF:
maybe_namespace = '%s::' % underlying_type.namespace.unix_name
- return 'new base::StringValue(%sToString(%s))' % (maybe_namespace, var)
+ return 'base::WrapUnique(new base::StringValue(%sToString(%s)))' % (
+ maybe_namespace, var)
elif underlying_type.property_type == PropertyType.BINARY:
if is_ptr:
vardot = var + '->'
@@ -647,16 +641,16 @@ class _Generator(object):
return ('base::BinaryValue::CreateWithCopiedBuffer(%sdata(),'
' %ssize())' % (vardot, vardot))
elif underlying_type.property_type == PropertyType.ARRAY:
- return '%s.release()' % self._util_cc_helper.CreateValueFromArray(
+ return '%s' % self._util_cc_helper.CreateValueFromArray(
var,
is_ptr)
elif underlying_type.property_type.is_fundamental:
if is_ptr:
var = '*%s' % var
if underlying_type.property_type == PropertyType.STRING:
- return 'new base::StringValue(%s)' % var
+ return 'base::WrapUnique(new base::StringValue(%s))' % var
else:
- return 'new base::FundamentalValue(%s)' % var
+ return 'base::WrapUnique(new base::FundamentalValue(%s))' % var
else:
raise NotImplementedError('Conversion of %s to base::Value not '
'implemented' % repr(type_.type_))
@@ -840,7 +834,7 @@ class _Generator(object):
if is_ptr:
c.Append('%(dst_var)s.reset(new base::DictionaryValue());')
elif underlying_type.property_type == PropertyType.ANY:
- c.Append('%(dst_var)s.reset(%(src_var)s->DeepCopy());')
+ c.Append('%(dst_var)s = %(src_var)s->CreateDeepCopy();')
elif underlying_type.property_type == PropertyType.ARRAY:
# util_cc_helper deals with optional and required arrays
(c.Append('const base::ListValue* list = NULL;')
diff --git a/chromium/tools/json_schema_compiler/util.cc b/chromium/tools/json_schema_compiler/util.cc
index dcb44ecb132..d1a16261d2a 100644
--- a/chromium/tools/json_schema_compiler/util.cc
+++ b/chromium/tools/json_schema_compiler/util.cc
@@ -160,12 +160,12 @@ void AddItemToList(const std::vector<char>& from, base::ListValue* out) {
void AddItemToList(const std::unique_ptr<base::Value>& from,
base::ListValue* out) {
- out->Append(from->DeepCopy());
+ out->Append(from->CreateDeepCopy());
}
void AddItemToList(const std::unique_ptr<base::DictionaryValue>& from,
base::ListValue* out) {
- out->Append(static_cast<base::Value*>(from->DeepCopy()));
+ out->Append(from->CreateDeepCopy());
}
std::string ValueTypeToString(base::Value::Type type) {
diff --git a/chromium/tools/licenses.py b/chromium/tools/licenses.py
index 9a6602b855a..7a77710c0c5 100755
--- a/chromium/tools/licenses.py
+++ b/chromium/tools/licenses.py
@@ -29,6 +29,9 @@ PRUNE_PATHS = set([
# Placeholder directory only, not third-party code.
os.path.join('third_party','adobe'),
+ # Already covered by //third_party/android_tools.
+ os.path.join('third_party','android_tools_internal'),
+
# Apache 2.0 license. See crbug.com/140478
os.path.join('third_party','bidichecker'),
@@ -42,11 +45,13 @@ PRUNE_PATHS = set([
os.path.join('build','secondary'),
os.path.join('third_party','bison'),
os.path.join('third_party','blanketjs'),
+ os.path.join('third_party','chromite'),
os.path.join('third_party','cygwin'),
os.path.join('third_party','gles2_conform'),
os.path.join('third_party','gnu_binutils'),
os.path.join('third_party','gold'),
os.path.join('third_party','gperf'),
+ os.path.join('third_party','jarjar'),
os.path.join('third_party','kasko'),
os.path.join('third_party','lighttpd'),
os.path.join('third_party','llvm'),
@@ -56,6 +61,7 @@ PRUNE_PATHS = set([
os.path.join('third_party','pefile'),
os.path.join('third_party','perl'),
os.path.join('third_party','psyco_win32'),
+ os.path.join('third_party','pyelftools'),
os.path.join('third_party','pylib'),
os.path.join('third_party','pywebsocket'),
os.path.join('third_party','qunit'),
@@ -166,12 +172,6 @@ SPECIAL_CASES = {
"URL": "http://code.google.com/p/pdfium/",
"License": "BSD",
},
- os.path.join('third_party', 'pdfsqueeze'): {
- "Name": "pdfsqueeze",
- "URL": "http://code.google.com/p/pdfsqueeze/",
- "License": "Apache 2.0",
- "License File": "COPYING",
- },
os.path.join('third_party', 'ppapi'): {
"Name": "ppapi",
"URL": "http://code.google.com/p/ppapi/",
@@ -298,7 +298,6 @@ KNOWN_NON_IOS_LIBRARIES = set([
os.path.join('third_party', 'mozilla'),
os.path.join('third_party', 'npapi'),
os.path.join('third_party', 'ots'),
- os.path.join('third_party', 'pdfsqueeze'),
os.path.join('third_party', 'ppapi'),
os.path.join('third_party', 'qcms'),
os.path.join('third_party', 're2'),
diff --git a/chromium/tools/mb/mb.py b/chromium/tools/mb/mb.py
index 39e810c1a67..2c16266c641 100755
--- a/chromium/tools/mb/mb.py
+++ b/chromium/tools/mb/mb.py
@@ -23,10 +23,18 @@ import shutil
import sys
import subprocess
import tempfile
+import traceback
import urllib2
from collections import OrderedDict
+CHROMIUM_SRC_DIR = os.path.dirname(os.path.dirname(os.path.dirname(
+ os.path.abspath(__file__))))
+sys.path = [os.path.join(CHROMIUM_SRC_DIR, 'build')] + sys.path
+
+import gn_helpers
+
+
def main(args):
mbw = MetaBuildWrapper()
return mbw.Main(args)
@@ -34,11 +42,9 @@ def main(args):
class MetaBuildWrapper(object):
def __init__(self):
- p = os.path
- d = os.path.dirname
- self.chromium_src_dir = p.normpath(d(d(d(p.abspath(__file__)))))
- self.default_config = p.join(self.chromium_src_dir, 'tools', 'mb',
- 'mb_config.pyl')
+ self.chromium_src_dir = CHROMIUM_SRC_DIR
+ self.default_config = os.path.join(self.chromium_src_dir, 'tools', 'mb',
+ 'mb_config.pyl')
self.executable = sys.executable
self.platform = sys.platform
self.sep = os.sep
@@ -57,9 +63,11 @@ class MetaBuildWrapper(object):
except KeyboardInterrupt:
self.Print('interrupted, exiting', stream=sys.stderr)
return 130
- except Exception as e:
+ except Exception:
self.DumpInputFiles()
- self.Print(str(e))
+ s = traceback.format_exc()
+ for l in s.splitlines():
+ self.Print(l)
return 1
def ParseArgs(self, argv):
@@ -74,8 +82,14 @@ class MetaBuildWrapper(object):
default=self.default_config,
help='path to config file '
'(default is //tools/mb/mb_config.pyl)')
- subp.add_argument('-g', '--goma-dir', default=self.ExpandUser('~/goma'),
- help='path to goma directory (default is %(default)s).')
+ subp.add_argument('-g', '--goma-dir',
+ help='path to goma directory')
+ subp.add_argument('--android-version-code',
+ help='Sets GN arg android_default_version_code and '
+ 'GYP_DEFINE app_manifest_version_code')
+ subp.add_argument('--android-version-name',
+ help='Sets GN arg android_default_version_name and '
+ 'GYP_DEFINE app_manifest_version_name')
subp.add_argument('-n', '--dryrun', action='store_true',
help='Do a dry run (i.e., do nothing, just print '
'the commands that will run)')
@@ -222,6 +236,7 @@ class MetaBuildWrapper(object):
def CmdAnalyze(self):
vals = self.Lookup()
+ self.ClobberIfNeeded(vals)
if vals['type'] == 'gn':
return self.RunGNAnalyze(vals)
else:
@@ -230,7 +245,6 @@ class MetaBuildWrapper(object):
def CmdGen(self):
vals = self.Lookup()
self.ClobberIfNeeded(vals)
-
if vals['type'] == 'gn':
return self.RunGNGen(vals)
else:
@@ -255,7 +269,9 @@ class MetaBuildWrapper(object):
def CmdLookup(self):
vals = self.Lookup()
if vals['type'] == 'gn':
- cmd = self.GNCmd('gen', '_path_', vals['gn_args'])
+ cmd = self.GNCmd('gen', '_path_')
+ gn_args = self.GNArgs(vals)
+ self.Print('\nWriting """\\\n%s""" to _path_/args.gn.\n' % gn_args)
env = None
else:
cmd, env = self.GYPCmd('_path_', vals)
@@ -310,9 +326,13 @@ class MetaBuildWrapper(object):
for config in self.masters[master].values():
all_configs[config] = master
- # Check that every referenced config actually exists.
+ # Check that every referenced args file or config actually exists.
for config, loc in all_configs.items():
- if not config in self.configs:
+ if config.startswith('//'):
+ if not self.Exists(self.ToAbsPath(config)):
+ errs.append('Unknown args file "%s" referenced from "%s".' %
+ (config, loc))
+ elif not config in self.configs:
errs.append('Unknown config "%s" referenced from "%s".' %
(config, loc))
@@ -451,6 +471,8 @@ class MetaBuildWrapper(object):
config = self.masters[master][builder]
if config == 'tbd':
tbd.add(builder)
+ elif config.startswith('//'):
+ done.add(builder)
else:
# TODO(dpranke): Check if MB is actually running?
vals = self.FlattenConfig(config)
@@ -470,7 +492,7 @@ class MetaBuildWrapper(object):
PrintBuilders(STAT_TBD, tbd, notes)
PrintBuilders(STAT_GYP, gyp, notes)
else:
- self.Print(' ... done')
+ self.Print(' All GN!')
stats[STAT_DONE] += len(done)
@@ -543,11 +565,22 @@ class MetaBuildWrapper(object):
if not vals:
self.ReadConfigFile()
config = self.ConfigFromArgs()
- if not config in self.configs:
- raise MBErr('Config "%s" not found in %s' %
- (config, self.args.config_file))
-
- vals = self.FlattenConfig(config)
+ if config.startswith('//'):
+ if not self.Exists(self.ToAbsPath(config)):
+ raise MBErr('args file "%s" not found' % config)
+ vals = {
+ 'args_file': config,
+ 'cros_passthrough': False,
+ 'gn_args': '',
+ 'gyp_crosscompile': False,
+ 'gyp_defines': '',
+ 'type': 'gn',
+ }
+ else:
+ if not config in self.configs:
+ raise MBErr('Config "%s" not found in %s' %
+ (config, self.args.config_file))
+ vals = self.FlattenConfig(config)
# Do some basic sanity checking on the config so that we
# don't have to do this in every caller.
@@ -574,10 +607,12 @@ class MetaBuildWrapper(object):
gn_args = ' '.join(contents.get('gn_args', []))
return {
- 'type': contents.get('mb_type', ''),
+ 'args_file': '',
+ 'cros_passthrough': False,
'gn_args': gn_args,
- 'gyp_defines': gyp_defines,
'gyp_crosscompile': False,
+ 'gyp_defines': gyp_defines,
+ 'type': contents.get('mb_type', ''),
}
def ReadConfigFile(self):
@@ -618,11 +653,15 @@ class MetaBuildWrapper(object):
def FlattenConfig(self, config):
mixins = self.configs[config]
+ # TODO(dpranke): We really should provide a constructor for the
+ # default set of values.
vals = {
- 'type': None,
+ 'args_file': '',
+ 'cros_passthrough': False,
'gn_args': [],
'gyp_defines': '',
'gyp_crosscompile': False,
+ 'type': None,
}
visited = []
@@ -639,8 +678,9 @@ class MetaBuildWrapper(object):
visited.append(m)
mixin_vals = self.mixins[m]
- if 'type' in mixin_vals:
- vals['type'] = mixin_vals['type']
+
+ if 'cros_passthrough' in mixin_vals:
+ vals['cros_passthrough'] = mixin_vals['cros_passthrough']
if 'gn_args' in mixin_vals:
if vals['gn_args']:
vals['gn_args'] += ' ' + mixin_vals['gn_args']
@@ -653,6 +693,9 @@ class MetaBuildWrapper(object):
vals['gyp_defines'] += ' ' + mixin_vals['gyp_defines']
else:
vals['gyp_defines'] = mixin_vals['gyp_defines']
+ if 'type' in mixin_vals:
+ vals['type'] = mixin_vals['type']
+
if 'mixins' in mixin_vals:
self.FlattenMixins(mixin_vals['mixins'], vals, visited)
return vals
@@ -690,7 +733,14 @@ class MetaBuildWrapper(object):
def RunGNGen(self, vals):
build_dir = self.args.path[0]
- cmd = self.GNCmd('gen', build_dir, vals['gn_args'], extra_args=['--check'])
+ cmd = self.GNCmd('gen', build_dir, '--check')
+ gn_args = self.GNArgs(vals)
+
+ # Since GN hasn't run yet, the build directory may not even exist.
+ self.MaybeMakeDirectory(self.ToAbsPath(build_dir))
+
+ gn_args_path = self.ToAbsPath(build_dir, 'args.gn')
+ self.WriteFile(gn_args_path, gn_args, force_verbose=True)
swarming_targets = []
if getattr(self.args, 'swarming_targets_file', None):
@@ -722,10 +772,6 @@ class MetaBuildWrapper(object):
('//testing/buildbot/gn_isolate_map.pyl', err))
gn_runtime_deps_path = self.ToAbsPath(build_dir, 'runtime_deps')
-
- # Since GN hasn't run yet, the build directory may not even exist.
- self.MaybeMakeDirectory(self.ToAbsPath(build_dir))
-
self.WriteFile(gn_runtime_deps_path, '\n'.join(gn_labels) + '\n')
cmd.append('--runtime-deps-list-file=%s' % gn_runtime_deps_path)
@@ -736,9 +782,10 @@ class MetaBuildWrapper(object):
self.Print('GN gen failed: %d' % ret)
return ret
+ android = 'target_os="android"' in vals['gn_args']
for target in swarming_targets:
- if target.endswith('_apk'):
- # "_apk" targets may be either android_apk or executable. The former
+ if android:
+ # Android targets may be either android_apk or executable. The former
# will result in runtime_deps associated with the stamp file, while the
# latter will result in runtime_deps associated with the executable.
target_name = self.GNTargetName(target)
@@ -792,7 +839,7 @@ class MetaBuildWrapper(object):
command, extra_files = self.GetIsolateCommand(target, vals, gn_isolate_map)
label = gn_isolate_map[target_name]['label']
- cmd = self.GNCmd('desc', build_dir, extra_args=[label, 'runtime_deps'])
+ cmd = self.GNCmd('desc', build_dir, label, 'runtime_deps')
ret, out, _ = self.Call(cmd)
if ret:
if out:
@@ -841,22 +888,49 @@ class MetaBuildWrapper(object):
isolate_path + 'd.gen.json',
)
- def GNCmd(self, subcommand, path, gn_args='', extra_args=None):
+ def GNCmd(self, subcommand, path, *args):
if self.platform == 'linux2':
subdir, exe = 'linux64', 'gn'
elif self.platform == 'darwin':
subdir, exe = 'mac', 'gn'
else:
subdir, exe = 'win', 'gn.exe'
+
gn_path = self.PathJoin(self.chromium_src_dir, 'buildtools', subdir, exe)
- cmd = [gn_path, subcommand, path]
- gn_args = gn_args.replace("$(goma_dir)", self.args.goma_dir)
- if gn_args:
- cmd.append('--args=%s' % gn_args)
- if extra_args:
- cmd.extend(extra_args)
- return cmd
+ return [gn_path, subcommand, path] + list(args)
+
+ def GNArgs(self, vals):
+ if vals['cros_passthrough']:
+ if not 'GN_ARGS' in os.environ:
+ raise MBErr('MB is expecting GN_ARGS to be in the environment')
+ gn_args = os.environ['GN_ARGS']
+ if not re.search('target_os.*=.*"chromeos"', gn_args):
+ raise MBErr('GN_ARGS is missing target_os = "chromeos": (GN_ARGS=%s)' %
+ gn_args)
+ else:
+ gn_args = vals['gn_args']
+
+ if self.args.goma_dir:
+ gn_args += ' goma_dir="%s"' % self.args.goma_dir
+
+ android_version_code = self.args.android_version_code
+ if android_version_code:
+ gn_args += ' android_default_version_code="%s"' % android_version_code
+
+ android_version_name = self.args.android_version_name
+ if android_version_name:
+ gn_args += ' android_default_version_name="%s"' % android_version_name
+
+ # Canonicalize the arg string into a sorted, newline-separated list
+ # of key-value pairs, and de-dup the keys if need be so that only
+ # the last instance of each arg is listed.
+ gn_args = gn_helpers.ToGNString(gn_helpers.FromGNArgs(gn_args))
+
+ args_file = vals.get('args_file', None)
+ if args_file:
+ gn_args = ('import("%s")\n' % vals['args_file']) + gn_args
+ return gn_args
def RunGYPGen(self, vals):
path = self.args.path[0]
@@ -913,10 +987,12 @@ class MetaBuildWrapper(object):
cmdline = []
extra_files = []
- if android:
- # TODO(jbudorick): This won't work with instrumentation test targets.
- # Revisit this logic when those are added to gn_isolate_map.pyl.
- cmdline = [self.PathJoin('bin', 'run_%s' % target_name)]
+ if android and test_type != "script":
+ cmdline = [
+ self.PathJoin('bin', 'run_%s' % target_name),
+ '--logcat-output-dir', '${ISOLATED_OUTDIR}/logcats',
+ '-v',
+ ]
elif use_x11 and test_type == 'windowed_test_launcher':
extra_files = [
'xdisplaycheck',
@@ -998,15 +1074,34 @@ class MetaBuildWrapper(object):
return output_dir
def GYPCmd(self, output_dir, vals):
- gyp_defines = vals['gyp_defines']
+ if vals['cros_passthrough']:
+ if not 'GYP_DEFINES' in os.environ:
+ raise MBErr('MB is expecting GYP_DEFINES to be in the environment')
+ gyp_defines = os.environ['GYP_DEFINES']
+ if not 'chromeos=1' in gyp_defines:
+ raise MBErr('GYP_DEFINES is missing chromeos=1: (GYP_DEFINES=%s)' %
+ gyp_defines)
+ else:
+ gyp_defines = vals['gyp_defines']
+
goma_dir = self.args.goma_dir
# GYP uses shlex.split() to split the gyp defines into separate arguments,
# so we can support backslashes and and spaces in arguments by quoting
# them, even on Windows, where this normally wouldn't work.
- if '\\' in goma_dir or ' ' in goma_dir:
+ if goma_dir and ('\\' in goma_dir or ' ' in goma_dir):
goma_dir = "'%s'" % goma_dir
- gyp_defines = gyp_defines.replace("$(goma_dir)", goma_dir)
+
+ if goma_dir:
+ gyp_defines += ' gomadir=%s' % goma_dir
+
+ android_version_code = self.args.android_version_code
+ if android_version_code:
+ gyp_defines += ' app_manifest_version_code=%s' % android_version_code
+
+ android_version_name = self.args.android_version_name
+ if android_version_name:
+ gyp_defines += ' app_manifest_version_name=%s' % android_version_name
cmd = [
self.executable,
@@ -1018,6 +1113,21 @@ class MetaBuildWrapper(object):
# Ensure that we have an environment that only contains
# the exact values of the GYP variables we need.
env = os.environ.copy()
+
+ # This is a terrible hack to work around the fact that
+ # //tools/clang/scripts/update.py is invoked by GYP and GN but
+ # currently relies on an environment variable to figure out
+ # what revision to embed in the command line #defines.
+ # For GN, we've made this work via a gn arg that will cause update.py
+ # to get an additional command line arg, but getting that to work
+ # via GYP_DEFINES has proven difficult, so we rewrite the GYP_DEFINES
+ # to get rid of the arg and add the old var in, instead.
+ # See crbug.com/582737 for more on this. This can hopefully all
+ # go away with GYP.
+ if 'llvm_force_head_revision=1' in gyp_defines:
+ env['LLVM_FORCE_HEAD_REVISION'] = '1'
+ gyp_defines = gyp_defines.replace('llvm_force_head_revision=1', '')
+
env['GYP_GENERATORS'] = 'ninja'
if 'GYP_CHROMIUM_NO_ACTION' in env:
del env['GYP_CHROMIUM_NO_ACTION']
@@ -1083,8 +1193,11 @@ class MetaBuildWrapper(object):
matching_targets = set()
try:
- cmd = self.GNCmd('refs', self.args.path[0]) + [
- '@%s' % response_file.name, '--all', '--as=output']
+ cmd = self.GNCmd('refs',
+ self.args.path[0],
+ '@%s' % response_file.name,
+ '--all',
+ '--as=output')
ret, out, _ = self.Run(cmd, force_verbose=False)
if ret and not 'The input matches no targets' in out:
self.WriteFailureAndRaise('gn refs returned %d: %s' % (ret, out),
@@ -1095,8 +1208,10 @@ class MetaBuildWrapper(object):
if build_output in targets:
matching_targets.add(build_output)
- cmd = self.GNCmd('refs', self.args.path[0]) + [
- '@%s' % response_file.name, '--all']
+ cmd = self.GNCmd('refs',
+ self.args.path[0],
+ '@%s' % response_file.name,
+ '--all')
ret, out, _ = self.Run(cmd, force_verbose=False)
if ret and not 'The input matches no targets' in out:
self.WriteFailureAndRaise('gn refs returned %d: %s' % (ret, out),
@@ -1214,7 +1329,7 @@ class MetaBuildWrapper(object):
self.Print(json.dumps(obj, indent=2, sort_keys=True))
def GNTargetName(self, target):
- return target[:-len('_apk')] if target.endswith('_apk') else target
+ return target
def Build(self, target):
build_dir = self.ToSrcRelPath(self.args.path[0])
diff --git a/chromium/tools/mb/mb_config.pyl b/chromium/tools/mb/mb_config.pyl
index e2cfe335e1f..38fb6782222 100644
--- a/chromium/tools/mb/mb_config.pyl
+++ b/chromium/tools/mb/mb_config.pyl
@@ -12,10 +12,11 @@
# generated publicly advertised non-Official builds which are not allowed
# to have proprietary codecs enabled.
'chromium': {
- 'Android': 'android_without_codecs_gyp_release_bot_minimal_symbols',
+ 'Android': 'android_without_codecs_gn_release_bot_minimal_symbols',
'Linux x64': 'noswarming_gn_release_bot',
'Mac': 'noswarming_gyp_release_bot_mac_strip',
'Win': 'noswarming_gyp_release_bot_minimal_symbols_x86',
+ 'Win x64': 'noswarming_gn_release_bot_minimal_symbols_x64',
},
'chromium.android': {
@@ -36,9 +37,11 @@
'android_cronet_gn_release_bot_minimal_symbols_x86',
'Android Cronet x86 Builder (dbg)':
'android_cronet_gn_debug_static_bot_x86',
-
'Android GN Builder (dbg)': 'android_gn_debug_bot_minimal_symbols',
- 'Android MIPS Builder (dbg)': 'android_gn_debug_static_bot_mipsel',
+ 'Android MIPS Builder (dbg)':
+ 'android_gn_debug_static_minimal_symbols_mipsel',
+ 'Android N5X Swarm Builder':
+ 'swarming_android_gn_release_bot_minimal_symbols_arm64',
'Android Swarm Builder':
'swarming_android_gn_release_bot_minimal_symbols',
'Android WebView CTS L-MR1 (dbg)': 'none',
@@ -66,200 +69,207 @@
},
'chromium.chromiumos': {
- 'ChromiumOS amd64-generic Compile': 'tbd',
- 'ChromiumOS daisy Compile': 'tbd',
- 'ChromiumOS x86-generic Compile': 'tbd',
- 'Linux ChromiumOS Builder (dbg)': 'tbd',
- 'Linux ChromiumOS Full': 'tbd',
- 'Linux ChromiumOS Ozone Builder': 'tbd',
-
+ 'ChromiumOS amd64-generic Compile': 'cros_chrome_sdk_gn',
+ 'ChromiumOS daisy Compile': 'cros_chrome_sdk_gn',
+ 'ChromiumOS x86-generic Compile': 'cros_chrome_sdk_gn',
'Linux ChromiumOS Builder': 'swarming_chromeos_gyp_release_bot',
+ 'Linux ChromiumOS Builder (dbg)': 'swarming_chromeos_gyp_debug_bot',
+ 'Linux ChromiumOS Full': 'swarming_chromeos_gyp_release_bot',
'Linux ChromiumOS GN (dbg)': 'chromeos_gn_debug_bot',
'Linux ChromiumOS GN': 'chromeos_ozone_gn_release_bot',
+ 'Linux ChromiumOS Ozone Builder':
+ 'swarming_chromeos_ozone_gyp_release_bot',
'Linux ChromiumOS Ozone Tests (1)': 'none',
'Linux ChromiumOS Tests (1)': 'none',
'Linux ChromiumOS Tests (dbg)(1)': 'none',
},
'chromium.fyi': {
- 'Blink Linux LSan ASan': 'tbd',
- 'Browser Side Navigation Linux': 'tbd',
- 'Chromium Builder': 'tbd',
- 'Chromium Builder (dbg)': 'tbd',
- 'Chromium Linux Goma Canary': 'tbd',
- 'Chromium Linux Goma Canary (clobber)': 'tbd',
- 'Chromium Linux Precise Goma LinkTest': 'tbd',
- 'Chromium Linux32 Goma Canary (clobber)': 'tbd',
- 'Chromium Mac 10.10 MacViews': 'tbd',
- 'Chromium Mac 10.11': 'tbd',
- 'Chromium Mac 10.11 Force Mac Toolchain': 'tbd',
- 'Chromium Mac 10.9 Goma Canary': 'tbd',
- 'Chromium Mac 10.9 Goma Canary (clobber)': 'tbd',
- 'Chromium Mac 10.9 Goma Canary (dbg)': 'tbd',
- 'Chromium Mac 10.9 Goma Canary (dbg)(clobber)': 'tbd',
- 'Chromium Win 10': 'tbd',
- 'Chromium Win x64 Clobber': 'tbd',
- 'ChromiumOS Linux Tests': 'tbd',
- 'ClangToTAndroidASan':
- 'android_clang_no_chrome_plugins_asan_gn_debug_bot_minimal_symbols',
- 'ClangToTLinux': 'tbd',
- 'ClangToTLinux (dbg)': 'tbd',
- 'ClangToTLinuxASan': 'tbd',
- 'ClangToTLinuxUBSanVptr': 'tbd',
- 'ClangToTMac': 'tbd',
- 'ClangToTMac (dbg)': 'tbd',
- 'ClangToTMacASan': 'tbd',
- 'ClangToTWin': 'tbd',
- 'ClangToTWin(dbg)': 'tbd',
- 'ClangToTWin(dll)': 'tbd',
- 'ClangToTWin64': 'tbd',
- 'ClangToTWin64(dbg)': 'tbd',
- 'ClangToTWin64(dll)': 'tbd',
- 'ClangToTiOS': 'tbd',
- 'Closure Compilation Linux': 'tbd',
- 'CrWin7Goma': 'tbd',
- 'CrWin7Goma(clbr)': 'tbd',
- 'CrWin7Goma(dbg)': 'tbd',
- 'CrWin7Goma(dll)': 'tbd',
- 'CrWinAsan': 'tbd',
- 'CrWinAsan(dll)': 'tbd',
- 'CrWinAsanCov': 'tbd',
- 'CrWinClang(shared)': 'tbd',
- 'CrWinClang64(dll)': 'tbd',
- 'CrWinClangGoma': 'tbd',
- 'CrWinClangLLD': 'tbd',
- 'CrWinClangLLD64': 'tbd',
- 'CrWinClngLLD64dbg': 'tbd',
- 'CrWinClngLLDdbg': 'tbd',
- 'CrWinGoma': 'tbd',
- 'CrWinGoma(dll)': 'tbd',
- 'Linux Trusty': 'tbd',
- 'Linux Trusty (dbg)': 'tbd',
- 'Linux V8 API Stability': 'tbd',
- 'MD Top Chrome ChromeOS material-hybrid': 'tbd',
- 'MD Top Chrome ChromeOS non-material': 'tbd',
- 'MD Top Chrome Linux material': 'tbd',
- 'MD Top Chrome Win material': 'tbd',
- 'Ozone ECS Linux': 'tbd',
- 'Windows 8 App Certification': 'tbd',
- 'Windows Builder (DrMemory)': 'tbd',
- 'Windows Tests (DrMemory)': 'tbd',
-
'Android ChromeDriver Tests (dbg)': 'none',
'Android Cloud Tests': 'android_gn_debug_static_bot_x86',
'Android Remoting Tests': 'none',
'Android Tests (trial)(dbg)': 'none',
'Android Tests (x86 emulator)': 'android_gn_debug_static_bot_x86',
'Android Asan Builder Tests (dbg)':
- 'android_asan_gn_debug_bot_minimal_symbols',
+ 'android_asan_gn_clang_shared_debug_minimal_symbols',
'Android Builder (dbg)': 'android_gn_debug_static_bot',
- 'CFI Linux CF': 'gn_cfi_diag_release_bot',
- 'CFI Linux ToT': 'gn_cfi_release_bot',
- 'CFI Linux': 'gn_cfi_release_bot',
- 'Chromium Win MiniInstaller Tests': 'none',
+ 'Blimp Linux (dbg)':
+ '//build/args/bots/chromium.fyi/blimp_linux_dbg.gn',
+ 'Browser Side Navigation Linux': 'gn_release_bot',
+ 'CFI Linux CF': 'gn_cfi_diag_release_static',
+ 'CFI Linux ToT': 'gn_cfi_release_static',
+ 'CFI Linux': 'gn_cfi_release_static',
+ 'Chromium Linux Goma Canary': 'gn_release_bot',
+ 'Chromium Linux Goma Canary (clobber)': 'gn_release_bot',
+ 'Chromium Linux Precise Goma LinkTest': 'gn_release_bot',
+ 'Chromium Linux32 Goma Canary (clobber)': 'gn_release_bot_x86',
+ 'Chromium Mac 10.10 MacViews': 'mac_views_browser_gyp_release_bot',
+ 'Chromium Mac 10.11': 'gyp_release_bot',
+ 'Chromium Mac 10.11 Force Mac Toolchain': 'gyp_release_bot',
+ 'Chromium Mac 10.9 Goma Canary': 'gyp_release_bot',
+ 'Chromium Mac 10.9 Goma Canary (clobber)': 'gyp_release_bot',
+ 'Chromium Mac 10.9 Goma Canary (dbg)': 'gyp_debug_bot',
+ 'Chromium Mac 10.9 Goma Canary (dbg)(clobber)': 'gyp_debug_bot',
'Chromium Win PGO Builder': 'gyp_official_winpgo',
'Chromium Win x64 PGO Builder': 'gyp_official_winpgo_x64',
'Chromium Windows Analyze': 'gn_windows_analyze',
- 'Chromium_iOS_Device': 'ios_gyp',
- 'Chromium_iOS_Device_(ninja)': 'ios_gyp',
- 'Chromium_iOS_Simulator_(dbg)': 'ios_gyp',
+ 'CrWin7Goma': 'gyp_release_bot_minimal_symbols_x86',
+ 'CrWin7Goma(clbr)': 'gyp_shared_release_bot_minimal_symbols_x86',
+ 'CrWin7Goma(dbg)': 'gyp_debug_bot_minimal_symbols_x86',
+ 'CrWin7Goma(dll)': 'gyp_shared_release_bot_minimal_symbols_x86',
'CrWinClang':
'swarming_gyp_clang_official_release_bot_minimal_symbols_x86',
'CrWinClang(dbg)':
'swarming_gyp_clang_debug_bot_minimal_symbols_x86',
+ 'CrWinClang(dbg) tester': 'none',
'CrWinClang64':
'swarming_gyp_clang_official_release_bot_minimal_symbols_x64',
+ 'CrWinClang tester': 'none',
+ 'CrWinClang64(dll)':
+ 'swarming_gyp_clang_minimal_symbols_shared_release_bot_x64',
+ 'CrWinClangGoma': 'gyp_clang_minimal_symbols_shared_release_bot_x86',
+ 'CrWinGoma': 'gyp_release_bot_minimal_symbols_x86',
+ 'CrWinGoma(dll)': 'gyp_shared_release_bot_minimal_symbols_x86',
+ 'ClangToTAndroidASan': 'android_clang_tot_asan',
'ClangToTAndroidASan tester': 'none',
+ 'ClangToTLinux':
+ 'swarming_gyp_clang_tot_linux_dump_symbols_shared_release',
'ClangToTLinux tester': 'none',
+ 'ClangToTLinux (dbg)': 'swarming_clang_tot_shared_debug',
+ 'ClangToTLinuxASan': 'swarming_gyp_clang_tot_asan_lsan_static_release',
'ClangToTLinuxASan tester': 'none',
+ 'ClangToTLinuxLLD': 'swarming_clang_tot_lld_release_shared',
+ 'ClangToTLinuxLLD tester': 'none',
+ 'ClangToTLinuxUBSanVptr':
+ 'swarming_gyp_clang_tot_edge_ubsan_no_recover_hack_static_release',
'ClangToTLinuxUBSanVptr tester': 'none',
+ 'ClangToTMac': 'swarming_gyp_clang_tot_minimal_symbols_shared_release',
'ClangToTMac tester': 'none',
+ 'ClangToTMac (dbg)':
+ 'swarming_gyp_clang_tot_minimal_symbols_shared_debug',
+ 'ClangToTMacASan':
+ 'swarming_gyp_asan_clang_tot_full_symbols_static_release',
'ClangToTMacASan tester': 'none',
+ 'ClangToTWin':
+ 'swarming_gyp_clang_tot_official_minimal_symbols_static_release_x86',
'ClangToTWin tester': 'none',
+ 'ClangToTWin(dbg)':
+ 'swarming_gyp_clang_tot_minimal_symbols_shared_debug_x86',
'ClangToTWin(dbg) tester': 'none',
+ 'ClangToTWin(dll)':
+ 'swarming_gyp_clang_tot_minimal_symbols_shared_release_x86',
'ClangToTWin(dll) tester': 'none',
+ 'ClangToTWin64':
+ 'swarming_gyp_clang_tot_official_minimal_symbols_static_release_x64',
'ClangToTWin64 tester': 'none',
+ 'ClangToTWin64(dbg)':
+ 'swarming_gyp_clang_tot_minimal_symbols_shared_debug_x64',
'ClangToTWin64(dbg) tester': 'none',
+ 'ClangToTWin64(dll)':
+ 'swarming_gyp_clang_tot_minimal_symbols_shared_release_x64',
'ClangToTWin64(dll) tester': 'none',
+ 'ClangToTiOS': 'ios_gyp',
+ 'Closure Compilation Linux': 'closure_compilation',
+ 'CrWinAsan':
+ 'swarming_gyp_asan_clang_fuzzer_static_v8_heap_x86_full_symbols_release',
'CrWinAsan tester': 'none',
+ 'CrWinAsan(dll)':
+ 'swarming_gyp_asan_clang_fuzzer_shared_v8_heap_x86_full_symbols_release',
'CrWinAsan(dll) tester': 'none',
+ 'CrWinAsanCov':
+ ('swarming_gyp_asan_clang_edge_fuzzer'
+ '_static_v8_heap_x86_full_symbols_release'),
'CrWinAsanCov tester': 'none',
- 'CrWinClang tester': 'none',
- 'CrWinClang(dbg) tester': 'none',
+ 'CrWinClang(shared)':
+ 'swarming_gyp_clang_shared_release_bot_minimal_symbols_x86',
'CrWinClang(shared) tester': 'none',
'CrWinClang64 tester': 'none',
- 'CrWinClang64(dbg) tester': 'none',
'CrWinClang64(dbg)': 'win_clang_debug_bot',
+ 'CrWinClang64(dbg) tester': 'none',
'CrWinClang64(dll) tester': 'none',
+ 'CrWinClangLLD':
+ 'swarming_gyp_clang_tot_minimal_symbols_shared_release_use_lld_x86',
'CrWinClangLLD tester': 'none',
+ 'CrWinClangLLD64':
+ 'swarming_gyp_clang_tot_minimal_symbols_shared_release_use_lld_x64',
'CrWinClangLLD64 tester': 'none',
+ 'CrWinClngLLD64dbg':
+ 'swarming_gyp_clang_tot_minimal_symbols_shared_debug_use_lld_x64',
'CrWinClngLLD64dbg tester': 'none',
+ 'CrWinClngLLDdbg':
+ 'swarming_gyp_clang_tot_minimal_symbols_shared_debug_use_lld_x86',
'CrWinClngLLDdbg tester': 'none',
+ 'Headless Linux (dbg)':
+ '//build/args/bots/chromium.fyi/headless_linux_dbg.gn',
+ 'MD Top Chrome ChromeOS material-hybrid':
+ 'gyp_chromeos_with_codecs_debug_bot',
+ 'MD Top Chrome ChromeOS non-material':
+ 'gyp_chromeos_with_codecs_debug_bot',
+ 'MD Top Chrome Win material':
+ 'gyp_debug_bot_minimal_symbols_x64',
+ 'MD Top Chrome Linux material': 'gn_debug_bot',
+ 'LTO Linux': 'gn_official_goma_lto',
'LTO Linux Perf': 'gn_official_goma_lto',
'Libfuzzer Upload Linux ASan': 'gn_release_libfuzzer_asan',
+ 'Libfuzzer Upload Linux ASan Debug': 'gn_debug_libfuzzer_asan',
'Libfuzzer Upload Linux MSan': 'gn_release_libfuzzer_msan',
'Libfuzzer Upload Linux UBSan': 'gn_release_libfuzzer_ubsan',
- 'Linux ARM': 'swarming_gyp_release_bot_arm',
+ 'Linux ARM': 'swarming_gn_release_bot_arm',
+ 'Linux Kitchen (kitchen_run)': 'swarming_gn_release_bot',
+ 'Linux Kitchen (annotated_run)': 'swarming_gn_release_bot',
+ 'Linux V8 API Stability': 'gn_release_bot',
'Site Isolation Linux': 'gn_release_trybot',
'Site Isolation Win': 'gyp_release_trybot_x64',
- 'Vista Tests (dbg)(1)': 'none',
- 'Vista Tests (dbg)(2)': 'none',
+ 'UBSanVptr Linux': 'gn_ubsan_vptr_release_bot',
+ 'WebKit Linux - TraceWrappables': 'swarming_gn_release_bot_x64',
'Win LKGR (DrM 64)': 'gn_release_drmemory_drfuzz',
'Win LKGR (DrM)': 'gn_release_drmemory_drfuzz_x86',
- 'Win8 Tests (1)': 'none',
- 'Win8 Tests (2)': 'none',
- 'WinClang': 'win_clang_debug_bot',
- 'Windows Browser (DrMemory light) (1)': 'none',
- 'Windows Browser (DrMemory light) (2)': 'none',
+ 'Win 10 Fast Ring': 'gn_release_trybot_x64',
},
'chromium.gpu': {
- 'Android Debug (Nexus 5)': 'android_gyp_debug_static_bot',
- 'Android Debug (Nexus 6)': 'android_gyp_debug_static_bot',
- 'Android Debug (Nexus 9)': 'android_gyp_debug_static_bot_arm64',
- 'GPU Mac Builder': 'tbd',
- 'GPU Mac Builder (dbg)': 'tbd',
-
- 'GPU Linux Builder (dbg)': 'swarming_gpu_tests_gn_debug_bot',
- 'GPU Linux Builder': 'swarming_gpu_tests_gn_release_bot',
- 'GPU Win Builder':
- 'swarming_gpu_tests_gyp_release_bot_minimal_symbols_x86',
- 'GPU Win Builder (dbg)':
- 'swarming_gpu_tests_gyp_debug_bot_minimal_symbols_x86',
+ # These all use the 'trybot' mixins to ensure that dcheck is on.
+ 'GPU Mac Builder': 'swarming_gpu_tests_gyp_release_trybot',
+ 'GPU Mac Builder (dbg)': 'swarming_gpu_tests_gyp_debug_trybot',
+ 'GPU Linux Builder (dbg)': 'swarming_gpu_tests_gn_debug_trybot',
+ 'GPU Linux Builder': 'swarming_gpu_tests_gn_release_trybot',
+ 'GPU Win Builder': 'swarming_gpu_tests_gyp_release_trybot_x86',
+ 'GPU Win Builder (dbg)': 'swarming_gpu_tests_gyp_debug_trybot_x86',
'Linux Debug (NVIDIA)': 'none',
'Linux Release (NVIDIA)': 'none',
'Mac 10.10 Debug (Intel)': 'none',
'Mac 10.10 Release (Intel)': 'none',
'Mac 10.10 Retina Debug (AMD)': 'none',
'Mac 10.10 Retina Release (AMD)': 'none',
- 'Mac Retina Debug': 'none',
- 'Mac Retina Release': 'none',
'Win7 Debug (NVIDIA)': 'none',
'Win7 Release (ATI)': 'none',
'Win7 Release (NVIDIA)': 'none',
},
'chromium.gpu.fyi': {
- 'GPU Mac Builder': 'tbd',
- 'GPU Mac Builder (dbg)': 'tbd',
- 'GPU Win Clang Builder (dbg)': 'tbd',
- 'Linux Audio': 'tbd',
- 'Win7 Audio': 'tbd',
-
- 'GPU Linux Builder (dbg)': 'swarming_gpu_fyi_tests_gn_debug_bot',
- 'GPU Linux Builder': 'swarming_gpu_fyi_tests_gn_release_bot',
- 'GPU Win Builder':
- 'swarming_gpu_tests_deqp_gles_gyp_release_bot_minimal_symbols_x86',
+ # These all use the 'trybot' mixins to ensure that dcheck is on.
+ 'Android Debug (Nexus 5)': 'android_gn_debug_static_trybot',
+ 'Android Debug (Nexus 5X)': 'android_gn_debug_static_trybot_arm64',
+ 'Android Debug (Nexus 6)': 'android_gn_debug_static_trybot',
+ 'Android Debug (Nexus 9)': 'android_gn_debug_static_trybot_arm64',
+ 'GPU Linux Builder (dbg)': 'swarming_gpu_fyi_tests_gn_debug_trybot',
+ 'GPU Linux Builder': 'swarming_gpu_fyi_tests_gn_release_trybot',
+ 'GPU Mac Builder': 'swarming_gpu_fyi_tests_gyp_release_trybot',
+ 'GPU Mac Builder (dbg)': 'swarming_gpu_fyi_tests_gyp_debug_trybot',
+ 'GPU Win Builder': 'swarming_gpu_tests_deqp_gles_gyp_release_trybot_x86',
'GPU Win Builder (dbg)':
- 'swarming_gpu_tests_deqp_gles_gyp_debug_bot_minimal_symbols_x86',
+ 'swarming_gpu_tests_deqp_gles_gyp_debug_trybot_x86',
+ 'GPU Win Clang Builder (dbg)':
+ 'swarming_gpu_fyi_tests_gyp_clang_debug_trybot_x86',
'GPU Win x64 Builder':
- 'swarming_gpu_tests_deqp_gles_gyp_release_bot_minimal_symbols_x64',
+ 'swarming_gpu_tests_deqp_gles_gyp_release_trybot_x64',
'GPU Win x64 Builder (dbg)':
- 'swarming_gpu_tests_deqp_gles_gyp_debug_bot_minimal_symbols_x64',
+ 'swarming_gpu_tests_deqp_gles_gyp_debug_trybot_x64',
+ 'Linux ChromiumOS Builder':
+ 'swarming_gpu_fyi_tests_chromeos_gyp_release_trybot',
'Linux Debug (NVIDIA)': 'none',
'Linux Debug (New Intel)': 'none',
'Linux Release (ATI)': 'none',
- 'Linux Release (Intel Graphics Stack)': 'none',
'Linux Release (NVIDIA GeForce 730)': 'none',
'Linux Release (NVIDIA)': 'none',
'Linux Release (New Intel)': 'none',
@@ -275,7 +285,6 @@
'Win7 Debug (NVIDIA)': 'none',
'Win7 Debug (New Intel)': 'none',
'Win7 Release (ATI)': 'none',
- 'Win7 Release (Intel)': 'none',
'Win7 Release (NVIDIA GeForce 730)': 'none',
'Win7 Release (NVIDIA)': 'none',
'Win7 Release (New Intel)': 'none',
@@ -287,66 +296,89 @@
'chromium.linux': {
'Android Arm64 Builder (dbg)':
- 'swarming_android_gyp_debug_static_bot_arm64',
- 'Android Builder (dbg)': 'swarming_android_gyp_debug_static_bot',
- 'Android Builder': 'swarming_android_gyp_release_bot_minimal_symbols',
+ 'swarming_android_gn_debug_static_bot_arm64',
+ 'Android Builder (dbg)': 'swarming_android_gn_debug_static_bot',
+ 'Android Builder': 'swarming_android_gn_release_bot_minimal_symbols',
'Android Clang Builder (dbg)':
- 'android_clang_asan_findbugs_gyp_debug_bot_minimal_symbols',
+ 'android_clang_asan_findbugs_gn_debug_bot_minimal_symbols',
'Android GN (dbg)': 'android_gn_debug_bot_minimal_symbols',
'Android GN': 'android_gn_release_bot_minimal_symbols',
- 'Android Tests (dbg)': 'swarming_android_gyp_debug_static_bot',
- 'Android Tests': 'swarming_android_gyp_release_bot_minimal_symbols',
- 'Cast Android (dbg)': 'android_cast_gyp_debug_static_bot',
+ 'Android Tests (dbg)': 'swarming_android_gn_debug_static_bot',
+ 'Android Tests': 'swarming_android_gn_release_bot_minimal_symbols',
+ 'Cast Android (dbg)': 'android_cast_gn_debug_static_bot',
'Cast Linux': 'cast_gn_release_bot',
'Linux Builder (dbg)': 'swarming_gn_debug_bot',
- 'Linux Builder (dbg)(32)': 'swarming_gyp_debug_bot_no_symbols_x86',
+ 'Linux Builder (dbg)(32)': 'swarming_gn_debug_bot_x86',
'Linux Builder': 'swarming_gn_release_bot',
'Linux Tests (dbg)(1)': 'none',
'Linux Tests (dbg)(1)(32)': 'none',
'Linux Tests': 'none',
},
- 'chromium.mac': {
- 'Mac Builder': 'tbd',
- 'Mac Builder (dbg)': 'tbd',
+ 'chromium.lkgr': {
+ 'ASAN Debug': 'gyp_asan_lsan_edge_fuzzer_debug_bot',
+ 'ASAN Release (symbolized)':
+ 'gyp_asan_lsan_edge_fuzzer_v8_heap_symbolized_release_bot',
+ 'ASAN Release Media':
+ 'gyp_asan_lsan_edge_fuzzer_v8_heap_chromeos_codecs_release_bot',
+ 'ASAN Release': 'gyp_asan_lsan_edge_fuzzer_v8_heap_release_bot',
+ 'ASan Debug (32-bit x86 with V8-ARM)':
+ 'gyp_asan_edge_fuzzer_v8_heap_debug_bot_hybrid',
+ 'ASan Release (32-bit x86 with V8-ARM)':
+ 'gyp_asan_edge_fuzzer_v8_heap_release_bot_hybrid',
+ 'ASan Release (32-bit x86 with V8-ARM, symbolized)':
+ 'gyp_asan_edge_fuzzer_v8_heap_symbolized_release_bot_hybrid',
+ 'ASan Release Media (32-bit x86 with V8-ARM)':
+ 'gyp_asan_edge_fuzzer_v8_heap_chromeos_codecs_release_bot_hybrid',
+ 'ChromiumOS ASAN Release':
+ 'gyp_chromeos_asan_lsan_edge_fuzzer_v8_heap_release_bot',
+ 'MSAN Release (chained origins)': 'gyp_msan_edge_release_bot',
+ 'MSAN Release (no origins)': 'gyp_msan_no_origins_edge_release_bot',
+ 'Mac ASAN Debug': 'gyp_asan_fuzzer_v8_heap_debug_symbols_static_bot',
+ 'Mac ASAN Release Media':
+ 'gyp_asan_fuzzer_v8_heap_chrome_with_codecs_release_bot',
+ 'Mac ASAN Release': 'gyp_asan_fuzzer_v8_heap_release_bot',
+ 'TSAN Debug': 'gyp_tsan_disable_nacl_line_tables_debug_bot',
+ 'TSAN Release': 'gyp_tsan_disable_nacl_line_tables_release_bot',
+ 'Telemetry Harness Upload': 'none',
+ 'UBSan Release': 'gyp_ubsan_release_bot',
+ 'UBSan vptr Release': 'gyp_ubsan_vptr_edge_release_bot',
+ 'Win ASan Release Coverage':
+ 'gyp_asan_edge_fuzzer_v8_heap_release_static_x86',
+ 'Win ASan Release Media':
+ 'gyp_asan_fuzzer_v8_heap_chrome_with_codecs_release_static_x86',
+ 'Win ASan Release': 'gyp_asan_fuzzer_v8_heap_release_static_x86',
+ 'Win SyzyASAN LKGR': 'gyp_syzyasan_no_pch_win_z7_x86',
+ },
- 'Mac GN (dbg)': 'gn_debug_static_bot',
+ 'chromium.mac': {
+ 'Mac Builder': 'swarming_gpu_tests_gyp_release_bot',
+ 'Mac Builder (dbg)': 'swarming_gyp_debug_bot',
+ 'Mac GN (dbg)': 'gn_debug_bot',
'Mac GN': 'gn_release_bot',
'Mac10.10 Tests': 'none',
'Mac10.11 Tests': 'none',
'Mac10.9 Tests (dbg)': 'none',
'Mac10.9 Tests': 'none',
- 'iOS_Device': 'ios_gyp',
- 'iOS_Device_(ninja)': 'ios_gyp',
- 'iOS_Device_GN': 'ios_gn',
- 'iOS_Simulator_(dbg)': 'ios_gyp',
- 'iOS_Simulator_GN_(dbg)': 'ios_gn',
+ 'ios-device': 'ios_gyp',
+ 'ios-device-gn': 'ios_gn',
+ 'ios-simulator': 'ios_gyp',
+ 'ios-simulator-gn': 'ios_gn',
},
'chromium.memory.fyi': {
- 'Chromium Linux ChromeOS MSan Builder': 'tbd',
- 'Chromium Linux MSan Builder': 'tbd',
- 'Chromium Linux TSan Builder': 'tbd',
-
- 'Chromium Linux Builder (valgrind)': 'gyp_valgrind_release_bot',
- 'Chromium OS (valgrind)(1)': 'none',
- 'Chromium OS (valgrind)(2)': 'none',
- 'Chromium OS (valgrind)(3)': 'none',
- 'Chromium OS (valgrind)(4)': 'none',
- 'Chromium OS (valgrind)(5)': 'none',
- 'Chromium OS (valgrind)(6)': 'none',
- 'Chromium OS Builder (valgrind)': 'gyp_valgrind_chromeos_release_bot',
+ 'Chromium Linux ChromeOS MSan Builder':
+ 'swarming_gyp_chromeos_msan_release_bot',
+ 'Chromium Linux MSan Builder':
+ 'swarming_gyp_msan_release_bot',
+ 'Chromium Linux TSan Builder':
+ 'swarming_gyp_tsan_disable_nacl_release_bot',
'Chromium Windows Builder (DrMemory x64)':
'gyp_drmemory_shared_release_x64',
'Chromium Windows Builder (DrMemory)': 'gyp_drmemory_shared_release_x86',
'Linux ChromeOS MSan Tests': 'none',
'Linux MSan Tests': 'none',
'Linux TSan Tests': 'none',
- 'Linux Tests (valgrind)(1)': 'none',
- 'Linux Tests (valgrind)(2)': 'none',
- 'Linux Tests (valgrind)(3)': 'none',
- 'Linux Tests (valgrind)(4)': 'none',
- 'Linux Tests (valgrind)(5)': 'none',
'Windows Browser (DrMemory full) (1)': 'none',
'Windows Browser (DrMemory full) (10)': 'none',
'Windows Browser (DrMemory full) (11)': 'none',
@@ -482,52 +514,65 @@
'Linux Builder': 'swarming_gn_release_bot',
'Linux Builder-Trybot': 'swarming_gn_release_bot',
'Linux Tests': 'swarming_gn_release_bot',
+ 'Mac Builder': 'swarming_gpu_tests_gyp_release_bot',
+ 'Mac Builder-Trybot': 'swarming_gpu_tests_gyp_release_bot',
'Win Builder':
'swarming_gpu_tests_gyp_release_bot_minimal_symbols_x86',
- 'Win Builder-Trybot':
- 'swarming_gpu_tests_gyp_release_trybot_minimal_symbols_x86',
+ 'Win Builder-Trybot': 'swarming_gpu_tests_gyp_release_bot_x86',
},
'client.v8.fyi': {
+ 'Android Builder': 'gn_official_goma_minimal_symbols_android',
'Linux Debug Builder': 'gn_debug_bot',
'V8 Android GN (dbg)': 'android_gn_debug_bot',
'V8 Linux GN': 'gn_release_bot',
+ 'V8-Blink Linux 64': 'noswarming_gn_release_bot_x64',
+ 'V8-Blink Linux 64 - ignition': 'noswarming_gn_release_bot_x64',
+ 'V8-Blink Linux 64 (dbg)': 'noswarming_gn_debug_bot_x64',
+ 'V8-Blink Mac': 'noswarming_gyp_release_bot_x64',
+ 'V8-Blink Win': 'noswarming_gyp_release_bot_minimal_symbols_x86',
},
'chromium.webkit': {
- 'Android Builder': 'gyp_release_bot_android',
- 'WebKit Android (Nexus4)': 'gyp_release_bot_android',
- 'WebKit Linux (dbg)': 'swarming_gn_debug_bot_x64',
- 'WebKit Linux ASAN': 'swarming_gn_asan_lsan_release_bot_x64',
- 'WebKit Linux Leak': 'swarming_gn_release_bot_x64',
- 'WebKit Linux MSAN': 'swarming_gn_msan_release_bot_x64',
- 'WebKit Linux Trusty': 'swarming_gn_release_bot_x64',
- 'WebKit Linux': 'swarming_gn_release_bot_x64',
- 'WebKit Mac Builder (dbg)': 'swarming_gyp_debug_bot_x64',
- 'WebKit Mac Builder': 'swarming_gyp_release_bot_x64',
+ 'Android Builder': 'android_gn_release_bot_minimal_symbols',
+ 'WebKit Android (Nexus4)': 'none',
+ 'WebKit Linux (dbg)': 'swarming_gn_debug_bot',
+ 'WebKit Linux ASAN': 'swarming_gn_asan_lsan_release_bot',
+ 'WebKit Linux Leak': 'swarming_gn_release_bot',
+ 'WebKit Linux MSAN': 'swarming_gn_msan_release_bot',
+ 'WebKit Linux Trusty': 'swarming_gn_release_bot',
+ 'WebKit Linux': 'swarming_gn_release_bot',
+ 'WebKit Mac Builder (dbg)': 'swarming_gyp_debug_bot',
+ 'WebKit Mac Builder': 'swarming_gyp_release_bot',
'WebKit Mac10.10': 'none',
'WebKit Mac10.11 (dbg)': 'none',
- 'WebKit Mac10.11 (retina)': 'swarming_gyp_release_bot_x64',
+ 'WebKit Mac10.11 (retina)': 'swarming_gyp_release_bot',
'WebKit Mac10.11': 'none',
- 'WebKit Mac10.9': 'none',
+ 'WebKit Mac10.9': 'swarming_gyp_release_bot',
'WebKit Win Builder (dbg)': 'swarming_gyp_debug_bot_minimal_symbols_x86',
'WebKit Win Builder': 'swarming_gyp_release_bot_minimal_symbols_x86',
'WebKit Win x64 Builder (dbg)':
- 'swarming_gyp_debug_bot_minimal_symbols_x64',
- 'WebKit Win x64 Builder': 'swarming_gyp_release_bot_minimal_symbols_x64',
+ 'swarming_gn_debug_bot_minimal_symbols_x64',
+ 'WebKit Win x64 Builder': 'swarming_gn_release_bot_minimal_symbols_x64',
'WebKit Win10': 'none',
'WebKit Win7 (dbg)': 'none',
'WebKit Win7': 'none',
},
- 'chromium.webrtc.fyi': {
- 'Android Builder (dbg)': 'tbd',
- 'Android Builder ARM64 (dbg)': 'tbd',
- 'Mac Builder': 'tbd',
- 'Win Builder': 'tbd',
+ 'chromium.webrtc': {
+ 'Linux Builder': 'gn_release_bot_chrome_with_codecs',
+ 'Linux Tester': 'none',
+ 'Mac Builder': 'chrome_with_codecs_blink_logging_gyp_release_trybot',
+ 'Mac Tester': 'none',
+ 'Win Builder': 'chrome_with_codecs_blink_logging_gyp_release_trybot_x86',
+ 'Win10 Tester': 'none',
+ 'Win7 Tester': 'none',
+ 'Win8 Tester': 'none',
+ },
- 'Android GN (dbg)': 'android_gn_debug_bot',
- 'Android GN': 'android_gn_release_bot',
+ 'chromium.webrtc.fyi': {
+ 'Android Builder (dbg)': 'android_gn_debug_static_bot',
+ 'Android Builder ARM64 (dbg)': 'android_gn_debug_static_bot_arm64',
'Android Tests (dbg) (K Nexus5)': 'none',
'Android Tests (dbg) (L Nexus5)': 'none',
'Android Tests (dbg) (L Nexus6)': 'none',
@@ -535,9 +580,11 @@
'Android Tests (dbg) (L Nexus9)': 'none',
'Linux Builder': 'gn_release_bot_chrome_with_codecs',
'Linux Tester': 'none',
+ 'Mac Builder': 'chrome_with_codecs_blink_logging_gyp_release_trybot',
'Mac GN (dbg)': 'gn_debug_static_bot_chrome_with_codecs',
'Mac GN': 'gn_release_bot_chrome_with_codecs',
'Mac Tester': 'none',
+ 'Win Builder': 'chrome_with_codecs_blink_logging_gyp_release_trybot_x86',
'Win x64 GN (dbg)': 'gn_debug_bot_minimal_symbols_chrome_with_codecs',
'Win x64 GN': 'gn_release_bot_minimal_symbols_chrome_with_codecs',
'Win10 Tester': 'none',
@@ -548,10 +595,8 @@
# Windows bots take too long to link w/ full symbols and time out.
'Win Builder': 'swarming_gyp_release_bot_minimal_symbols_x86',
'Win Builder (dbg)': 'swarming_gyp_debug_bot_minimal_symbols_x86',
- 'Win x64 Builder': 'swarming_gyp_release_bot_minimal_symbols_x64',
- 'Win x64 Builder (dbg)': 'swarming_gyp_debug_bot_minimal_symbols_x64',
- 'Win x64 GN (dbg)': 'gn_debug_bot_minimal_symbols',
- 'Win x64 GN': 'gn_release_bot_minimal_symbols',
+ 'Win x64 Builder': 'swarming_gn_release_bot_minimal_symbols_x64',
+ 'Win x64 Builder (dbg)': 'swarming_gn_debug_bot_minimal_symbols_x64',
'Win 7 Tests x64 (1)': 'none',
'Win10 Tests x64': 'none',
'Win7 (32) Tests': 'none',
@@ -559,10 +604,11 @@
'Win7 Tests (dbg)(1)': 'none',
'Win8 Aura': 'gn_release_bot_minimal_symbols_x86',
'Win8 GN (dbg)': 'gn_debug_bot_minimal_symbols_x86',
+ 'WinClang64 (dbg)': 'win_clang_debug_bot',
},
'official.desktop': {
- 'blimp-engine': 'gn_blimp_debug',
+ 'blimp-engine': '//build/args/bots/official.desktop/blimp-engine.gn',
'mac64': 'gyp_official',
'precise64': 'gn_official',
@@ -588,42 +634,29 @@
},
'tryserver.blink': {
- 'linux_chromium_gn_rel': 'tbd',
-
- 'blink_presubmit': 'none',
- 'linux_blink_compile_dbg':
- 'swarming_gn_debug_bot_minimal_symbols_x64',
- 'linux_blink_compile_rel':
- 'swarming_gn_release_trybot_minimal_symbols_x64',
- 'linux_blink_dbg':
- 'swarming_gn_debug_bot_minimal_symbols_x64',
- 'linux_blink_rel':
- 'swarming_gn_release_trybot_minimal_symbols_x64',
- 'linux_blink_rel_ng':
- 'swarming_gn_release_trybot_minimal_symbols_x64',
- 'mac_blink_compile_dbg':
- 'swarming_gyp_debug_bot_minimal_symbols_x64',
- 'mac_blink_compile_rel':
- 'swarming_gyp_release_bot_minimal_symbols_x64',
- 'mac_blink_dbg':
- 'swarming_gyp_debug_bot_minimal_symbols_x64',
- 'mac_blink_rel': 'swarming_gyp_release_trybot_minimal_symbols_x64',
- 'win_blink_compile_dbg': 'swarming_gyp_debug_bot_minimal_symbols_x86',
- 'win_blink_compile_rel':
- 'swarming_gyp_release_trybot_minimal_symbols_x86',
- 'win_blink_dbg': 'swarming_gyp_debug_bot_minimal_symbols_x86',
- 'win_blink_rel': 'swarming_gyp_release_trybot_minimal_symbols_x86',
+ # Most tryservers should have '_trybot' in their config names, but
+ # 'release_trybot' includes 'dcheck_always_on', and the blink
+ # release trybots must *not* enable dchecks, because that could
+ # cause them to produce different baselines than the release
+ # waterfall bots, and run-webkit-tests can't handle that (by design).
+ 'linux_blink_compile_dbg': 'swarming_gn_debug_trybot',
+ 'linux_blink_compile_rel': 'swarming_gn_release_bot_minimal_symbols',
+ 'linux_blink_dbg': 'swarming_gn_debug_trybot',
+ 'linux_blink_rel': 'swarming_gn_release_bot_minimal_symbols',
+ 'mac_blink_compile_dbg': 'swarming_gyp_debug_trybot',
+ 'mac_blink_compile_rel': 'swarming_gyp_release_bot_minimal_symbols',
+ 'mac_blink_dbg': 'swarming_gyp_debug_trybot',
+ 'mac_blink_rel': 'swarming_gyp_release_bot_minimal_symbols',
+ 'win_blink_compile_dbg': 'swarming_gyp_debug_trybot_x86',
+ 'win_blink_compile_rel': 'swarming_gyp_release_bot_minimal_symbols_x86',
+ 'win_blink_dbg': 'swarming_gyp_debug_trybot_x86',
+ 'win_blink_rel': 'swarming_gyp_release_bot_minimal_symbols_x86',
},
'tryserver.chromium.android': {
- 'android_amp': 'tbd',
- 'android_archive_rel_ng': 'tbd',
- 'android_coverage': 'tbd',
- 'android_swarming_rel': 'tbd',
- 'cast_shell_android': 'tbd',
-
- 'android_arm64_dbg_recipe': 'swarming_android_gyp_debug_trybot_arm64',
- 'android_blink_rel': 'swarming_android_gyp_release_trybot',
+ 'android_archive_rel_ng': 'android_gn_release_trybot',
+ 'android_arm64_dbg_recipe': 'swarming_android_gn_debug_trybot_arm64',
+ 'android_blink_rel': 'swarming_android_gn_release_trybot',
'android_chromium_gn_compile_dbg': 'android_gn_debug_trybot',
'android_chromium_gn_compile_rel': 'android_gn_release_trybot',
'android_chromium_gn_rel': 'android_gn_release_trybot',
@@ -634,80 +667,86 @@
'android_chromium_variable_clang': 'findit',
'android_chromium_variable_gn': 'findit',
'android_chromium_variable_nexus4': 'findit',
- 'android_clang_dbg_recipe': 'android_clang_asan_findbugs_gyp_debug_trybot',
- 'android_compile_dbg': 'swarming_android_gyp_debug_trybot',
+ 'android_clang_dbg_recipe': 'android_clang_asan_findbugs_gn_debug_trybot',
+ 'android_compile_dbg': 'swarming_android_gn_debug_trybot',
'android_compile_mips_dbg': 'android_gn_debug_trybot_mipsel',
- 'android_compile_rel': 'swarming_android_gyp_release_trybot',
+ 'android_compile_rel': 'swarming_android_gn_release_trybot',
'android_compile_x64_dbg': 'android_gn_debug_trybot_x64',
'android_compile_x86_dbg': 'android_gn_debug_trybot_x86',
+ 'android_coverage': 'android_gn_debug_trybot_java_coverage',
# TODO(crbug/597596): Switch this back to debug_trybot when cronet's
# shared library loading is fixed.
'android_cronet_tester': 'android_cronet_gn_debug_static_bot',
- 'linux_android_dbg_ng': 'swarming_android_gyp_debug_trybot',
- 'linux_android_rel_ng': 'swarming_android_gyp_release_trybot',
+ 'android_swarming_rel': 'swarming_android_gn_release_trybot',
+ 'cast_shell_android': 'android_cast_gn_debug_static_bot',
+ 'linux_android_dbg_ng': 'swarming_android_gn_debug_trybot',
+ 'linux_android_rel_ng': 'swarming_android_gn_release_trybot',
},
'tryserver.chromium.angle': {
- 'mac_angle_dbg_ng': 'tbd',
- 'mac_angle_rel_ng': 'tbd',
-
'linux_angle_dbg_ng': 'swarming_gpu_fyi_tests_gn_debug_trybot',
'linux_angle_rel_ng': 'swarming_gpu_fyi_tests_gn_release_trybot',
- 'win_angle_dbg_ng':
- 'swarming_gpu_tests_deqp_gles_gyp_debug_bot_minimal_symbols_x86',
- 'win_angle_rel_ng':
- 'swarming_gpu_tests_deqp_gles_gyp_release_trybot_minimal_symbols_x86',
+ 'mac_angle_dbg_ng': 'swarming_gpu_fyi_tests_gyp_debug_trybot',
+ 'mac_angle_rel_ng': 'swarming_gpu_fyi_tests_gyp_release_trybot',
+ 'win_angle_dbg_ng': 'swarming_gpu_tests_deqp_gles_gyp_debug_trybot_x86',
+ 'win_angle_rel_ng': 'swarming_gpu_tests_deqp_gles_gyp_release_trybot_x86',
'win_angle_x64_dbg_ng':
- 'swarming_gpu_tests_deqp_gles_gyp_debug_bot_minimal_symbols_x64',
+ 'swarming_gpu_tests_deqp_gles_gyp_debug_trybot_x64',
'win_angle_x64_rel_ng':
- 'swarming_gpu_tests_deqp_gles_gyp_release_trybot_minimal_symbols_x64',
+ 'swarming_gpu_tests_deqp_gles_gyp_release_trybot_x64',
},
'tryserver.chromium.linux': {
- 'Chromium Linux Codesearch Builder': 'tbd',
- 'ChromiumOS Codesearch Builder': 'tbd',
- 'chromeos_amd64-generic_chromium_compile_only_ng': 'tbd',
- 'chromeos_daisy_chromium_compile_only_ng': 'tbd',
- 'chromeos_x86-generic_chromium_compile_only_ng': 'tbd',
- 'linux_chromium_browser_side_navigation_rel': 'tbd',
- 'linux_chromium_chromeos_asan_rel_ng': 'tbd',
- 'linux_chromium_chromeos_asan_variable': 'tbd',
- 'linux_chromium_chromeos_compile_dbg_ng': 'tbd',
- 'linux_chromium_chromeos_dbg_ng': 'tbd',
- 'linux_chromium_chromeos_msan_rel_ng': 'tbd',
- 'linux_chromium_chromeos_ozone_rel_ng': 'tbd',
- 'linux_chromium_chromeos_variable': 'tbd',
- 'linux_chromium_variable': 'tbd',
-
+ 'Chromium Linux Codesearch Builder': 'codesearch_gn',
+ 'ChromiumOS Codesearch Builder': 'codesearch_gn',
'cast_shell_linux': 'cast_gn_release_trybot',
'chromeos_amd64-generic_variable': 'findit',
+ 'chromeos_amd64-generic_chromium_compile_only_ng': 'cros_chrome_sdk_gn',
+ 'chromeos_daisy_chromium_compile_only_ng': 'cros_chrome_sdk_gn',
'chromeos_daisy_variable': 'findit',
+ 'chromeos_x86-generic_chromium_compile_only_ng': 'cros_chrome_sdk_gn',
'chromeos_x86-generic_variable': 'findit',
'chromium_presubmit': 'none',
+ 'closure_compilation': 'closure_compilation',
'linux_arm': 'swarming_gyp_release_trybot_arm',
'linux_chromium_archive_rel_ng': 'noswarming_gn_release_bot',
'linux_chromium_asan_rel_ng': 'swarming_asan_lsan_gyp_release_trybot',
'linux_chromium_asan_variable': 'findit',
+ 'linux_chromium_browser_side_navigation_rel': 'gyp_release_trybot',
'linux_chromium_cast_variable': 'findit',
- 'linux_chromium_cfi_rel_ng': 'gn_cfi_release_trybot',
+ 'linux_chromium_cfi_rel_ng': 'gn_cfi_release_static_dcheck_always_on',
+ 'linux_chromium_chromeos_asan_rel_ng':
+ 'swarming_asan_lsan_chromeos_gyp_release_trybot',
+ 'linux_chromium_chromeos_asan_variable': 'findit',
+ 'linux_chromium_chromeos_compile_dbg_ng':
+ 'swarming_chromeos_gyp_debug_trybot',
'linux_chromium_chromeos_compile_rel_ng':
- 'swarming_chromeos_gyp_release_trybot',
+ 'swarming_chromeos_gn_release_trybot',
+ 'linux_chromium_chromeos_dbg_ng':
+ 'swarming_chromeos_gyp_debug_trybot',
+ 'linux_chromium_chromeos_msan_rel_ng':
+ 'swarming_chromeos_msan_gyp_release_trybot',
+ 'linux_chromium_chromeos_ozone_rel_ng':
+ 'swarming_chromeos_gyp_ozone_release_trybot',
'linux_chromium_chromeos_rel_ng': 'swarming_chromeos_gyp_release_trybot',
+ 'linux_chromium_chromeos_variable': 'findit',
'linux_chromium_chromeos_variable_chrome': 'findit',
'linux_chromium_clobber_rel_ng': 'gn_release_trybot',
- 'linux_chromium_compile_dbg_32_ng': 'swarming_gyp_debug_trybot_x86',
+ 'linux_chromium_compile_dbg_32_ng': 'swarming_gn_debug_trybot_x86',
'linux_chromium_compile_dbg_ng': 'swarming_gn_debug_trybot',
'linux_chromium_compile_rel_ng': 'swarming_gn_release_trybot',
- 'linux_chromium_dbg_32_ng': 'swarming_gyp_debug_trybot_x86',
+ 'linux_chromium_dbg_32_ng': 'swarming_gn_debug_trybot_x86',
'linux_chromium_dbg_ng': 'swarming_gn_debug_trybot',
'linux_chromium_gn_chromeos_dbg': 'chromeos_gn_debug_bot',
'linux_chromium_gn_chromeos_rel': 'chromeos_ozone_gn_release_trybot',
'linux_chromium_gn_chromeos_variable': 'findit',
'linux_chromium_gn_upload': 'gn_linux_upload',
'linux_chromium_msan_rel_ng': 'swarming_msan_gyp_release_trybot',
- 'linux_chromium_practice_rel_ng': 'gyp_release_trybot',
'linux_chromium_rel_ng': 'swarming_gpu_tests_gn_release_trybot',
'linux_chromium_tsan_rel_ng': 'swarming_tsan_gyp_release_trybot',
+ 'linux_chromium_tsan_rel_ng':
+ 'swarming_gyp_tsan_disable_nacl_release_trybot',
+ 'linux_chromium_variable': 'findit',
'linux_chromium_variable_32': 'findit',
'linux_chromium_variable_chrome': 'findit',
'linux_chromium_variable_clobber': 'findit',
@@ -717,37 +756,30 @@
'linux_chromium_webkit_leak_variable': 'findit',
'linux_chromium_webkit_msan_variable': 'findit',
'linux_chromium_webkit_variable': 'findit',
- 'linux_ecs_ozone': 'embedded_gyp_debug_bot',
- 'linux_full_bisect_builder': 'swarming_gyp_release_bot',
'linux_nacl_sdk': 'nacl_annotator',
'linux_nacl_sdk_build': 'nacl_annotator',
'linux_optional_gpu_tests_rel':
'swarming_gpu_fyi_tests_gn_release_trybot',
'linux_site_isolation': 'gn_release_trybot',
'linux_upload_clang': 'gn_release_bot',
- 'linux_valgrind': 'gyp_valgrind_release_bot',
},
'tryserver.chromium.mac': {
- 'mac_chromium_10.10_rel_ng': 'tbd',
- 'mac_chromium_archive_rel_ng': 'tbd',
- 'mac_chromium_asan_rel_ng': 'tbd',
- 'mac_chromium_asan_variable': 'tbd',
- 'mac_chromium_compile_dbg_ng': 'tbd',
- 'mac_chromium_compile_rel_ng': 'tbd',
- 'mac_chromium_dbg_ng': 'tbd',
- 'mac_chromium_rel_ng': 'tbd',
- 'mac_optional_gpu_tests_rel': 'tbd',
-
- 'ios_dbg_simulator': 'ios_gyp',
- 'ios_dbg_simulator_gn': 'ios_gn',
- 'ios_dbg_simulator_ninja': 'ios_gyp',
- 'ios_rel_device': 'ios_gyp',
- 'ios_rel_device_gn': 'ios_gn',
- 'ios_rel_device_ninja': 'ios_gyp',
- 'mac_chromium_gn_dbg': 'gn_debug_static_bot',
+ 'ios-device': 'ios_gyp',
+ 'ios-device-gn': 'ios_gn',
+ 'ios-simulator': 'ios_gyp',
+ 'ios-simulator-gn': 'ios_gn',
+ 'mac_chromium_10.10_rel_ng': 'swarming_gpu_tests_gyp_release_trybot',
+ 'mac_chromium_archive_rel_ng': 'noswarming_gyp_release_trybot',
+ 'mac_chromium_asan_rel_ng': 'swarming_asan_dcheck_gyp_release_bot',
+ 'mac_chromium_asan_variable': 'findit',
+ 'mac_chromium_compile_dbg_ng': 'swarming_gyp_debug_trybot',
+ 'mac_chromium_compile_rel_ng': 'swarming_gpu_tests_gyp_release_trybot',
+ 'mac_chromium_dbg_ng': 'swarming_gyp_debug_trybot',
+ 'mac_chromium_gn_dbg': 'gn_debug_bot',
'mac_chromium_gn_rel': 'gn_release_trybot',
'mac_chromium_gn_upload': 'gn_release_bot',
+ 'mac_chromium_rel_ng': 'swarming_gpu_tests_gyp_release_trybot',
'mac_chromium_variable': 'findit',
'mac_chromium_variable_10.10': 'findit',
'mac_chromium_variable_10.10_layout': 'findit',
@@ -757,6 +789,8 @@
'mac_chromium_variable_layout': 'findit',
'mac_nacl_sdk': 'nacl_annotator',
'mac_nacl_sdk_build': 'nacl_annotator',
+ 'mac_optional_gpu_tests_rel':
+ 'swarming_gpu_fyi_tests_gyp_release_trybot',
'mac_upload_clang': 'gn_release_bot',
},
@@ -804,23 +838,19 @@
},
'tryserver.chromium.win': {
- 'win10_chromium_x64_rel_ng':
- 'swarming_gyp_release_trybot_minimal_symbols_x64',
- 'win8_chromium_gn_dbg': 'gn_debug_bot_minimal_symbols_x86',
+ 'win10_chromium_x64_rel_ng': 'swarming_gn_release_trybot_x64',
+ 'win10_chromium_x64_rel_ng_exp': 'swarming_gn_release_trybot_x64',
+ 'win8_chromium_gn_dbg': 'swarming_gn_debug_trybot_x86',
'win8_chromium_gn_upload': 'gn_release_bot_minimal_symbols_x86',
'win8_chromium_ng': 'gn_release_trybot_x86',
- 'win_archive': 'noswarming_gyp_release_trybot_minimal_symbols_x86',
- 'win_chromium_compile_dbg_ng':
- 'swarming_gyp_debug_bot_minimal_symbols_x86',
+ 'win_x64_archive': 'noswarming_gyp_release_trybot_x64',
+ 'win_archive': 'noswarming_gyp_release_trybot_x86',
+ 'win_chromium_compile_dbg_ng': 'swarming_gyp_debug_trybot_x86',
'win_chromium_compile_rel_ng':
- 'swarming_gpu_tests_gyp_release_trybot_minimal_symbols_x86',
- 'win_chromium_gn_x64_dbg': 'gn_debug_bot_minimal_symbols',
- 'win_chromium_gn_x64_rel': 'gn_release_trybot',
- 'win_chromium_dbg_ng': 'swarming_gyp_debug_bot_minimal_symbols_x86',
- 'win_chromium_rel_ng':
- 'swarming_gpu_tests_gyp_release_trybot_minimal_symbols_x86',
- 'win_chromium_syzyasan_rel':
- 'swarming_gyp_syzyasan_release_trybot_minimal_symbols_x86',
+ 'swarming_gpu_tests_gyp_release_trybot_x86',
+ 'win_chromium_dbg_ng': 'swarming_gyp_debug_trybot_x86',
+ 'win_chromium_rel_ng': 'swarming_gpu_tests_gyp_release_trybot_x86',
+ 'win_chromium_syzyasan_rel': 'swarming_gyp_syzyasan_release_trybot_x86',
'win_chromium_variable': 'findit',
'win_chromium_variable_archive': 'findit',
'win_chromium_variable_chrome': 'findit',
@@ -829,26 +859,24 @@
'win_chromium_variable_webkit_layout': 'findit',
'win_chromium_variable_webkit_win7_builder': 'findit',
'win_chromium_variable_webkit_win7_builder_x64': 'findit',
- 'win_chromium_x64_rel_ng':
- 'swarming_gyp_release_trybot_minimal_symbols_x64',
+ 'win_chromium_x64_rel_ng': 'swarming_gn_release_trybot_x64',
'win_clang': 'win_clang_debug_bot',
- 'win_clang_dbg': 'swarming_gyp_clang_debug_bot_minimal_symbols_x86',
- 'win_clang_rel':
- 'swarming_gyp_clang_official_release_trybot_minimal_symbols_x86',
+ 'win_clang_dbg': 'swarming_gyp_clang_debug_trybot_x86',
+ 'win_clang_rel': 'swarming_gyp_clang_official_release_trybot_x86',
'win_clang_x64_dbg': 'win_clang_debug_bot',
- 'win_clang_x64_rel':
- 'swarming_gyp_clang_official_release_trybot_minimal_symbols_x64',
+ 'win_clang_x64_rel': 'swarming_gyp_clang_official_release_trybot_x64',
'win_nacl_sdk': 'nacl_annotator',
'win_nacl_sdk_build': 'nacl_annotator',
'win_optional_gpu_tests_rel':
- 'swarming_gpu_tests_deqp_gles_gyp_release_trybot_minimal_symbols_x86',
+ 'swarming_gpu_tests_deqp_gles_gyp_release_trybot_x86',
'win_pgo': 'gyp_official_winpgo',
'win_upload_clang': 'gn_release_bot',
+ 'win_chrome_official': 'gyp_official_goma_minimal_symbols_x86',
},
'tryserver.v8': {
'v8_android_chromium_gn_dbg': 'android_gn_debug_bot',
- 'v8_linux_blink_rel': 'swarming_gn_release_trybot_minimal_symbols_x64',
+ 'v8_linux_blink_rel': 'swarming_gn_release_trybot_x64',
'v8_linux_chromium_gn_rel': 'gn_release_trybot',
},
},
@@ -860,26 +888,26 @@
# is not necessarily so (i.e., we might have mac, win, and linux
# bots all using the 'gn_release_bot' config).
'configs': {
- 'android_asan_gn_debug_bot_minimal_symbols': [
- 'android', 'asan', 'gn', 'debug_bot_minimal_symbols',
+ 'android_asan_gn_clang_shared_debug_minimal_symbols': [
+ 'android', 'asan', 'gn', 'clang', 'shared', 'debug', 'minimal_symbols',
],
- 'android_cast_gyp_debug_static_bot': [
- 'android', 'cast', 'gyp', 'debug_static_bot',
+ 'android_cast_gn_debug_static_bot': [
+ 'android', 'cast', 'gn', 'clang', 'debug_static_bot',
],
- 'android_clang_no_chrome_plugins_asan_gn_debug_bot_minimal_symbols': [
- 'android', 'clang_no_chrome_plugins', 'asan', 'gn',
+ 'android_clang_asan_findbugs_gn_debug_bot_minimal_symbols': [
+ 'android', 'clang', 'asan', 'findbugs', 'gn',
'debug_bot_minimal_symbols',
],
- 'android_clang_asan_findbugs_gyp_debug_bot_minimal_symbols': [
- 'android', 'clang', 'asan', 'findbugs', 'gyp',
- 'debug_bot_minimal_symbols',
+ 'android_clang_asan_findbugs_gn_debug_trybot': [
+ 'android', 'clang', 'asan', 'findbugs', 'gn', 'debug_trybot',
],
- 'android_clang_asan_findbugs_gyp_debug_trybot': [
- 'android', 'clang', 'asan', 'findbugs', 'gyp', 'debug_trybot',
+ 'android_clang_tot_asan': [
+ 'android_without_codecs', 'clang_tot', 'asan', 'gn',
+ 'shared', 'debug', 'minimal_symbols',
],
'android_cronet_data_reduction_proxy_gn_release_bot_minimal_symbols': [
@@ -935,10 +963,6 @@
'android', 'gn', 'debug_static_bot', 'arm64',
],
- 'android_gn_debug_static_bot_mipsel': [
- 'android', 'gn', 'debug_static_bot', 'mipsel',
- ],
-
'android_gn_debug_static_bot_x64': [
'android', 'gn', 'debug_static_bot', 'x64',
],
@@ -947,10 +971,26 @@
'android', 'gn', 'debug_static_bot', 'x86',
],
+ 'android_gn_debug_static_minimal_symbols_mipsel': [
+ 'android', 'gn', 'debug', 'static', 'minimal_symbols', 'mipsel',
+ ],
+
+ 'android_gn_debug_static_trybot': [
+ 'android', 'gn', 'debug_static_trybot',
+ ],
+
+ 'android_gn_debug_static_trybot_arm64': [
+ 'android', 'gn', 'debug_static_trybot', 'arm64',
+ ],
+
'android_gn_debug_trybot': [
'android', 'gn', 'debug_trybot',
],
+ 'android_gn_debug_trybot_java_coverage': [
+ 'android', 'gn', 'debug_trybot', 'java_coverage',
+ ],
+
'android_gn_debug_trybot_mipsel': [
'android', 'gn', 'debug_trybot', 'mipsel',
],
@@ -975,16 +1015,8 @@
'android', 'gn', 'release_trybot',
],
- 'android_gyp_debug_static_bot': [
- 'android', 'gyp', 'debug_static_bot',
- ],
-
- 'android_gyp_debug_static_bot_arm64': [
- 'android', 'gyp', 'debug_static_bot', 'arm64',
- ],
-
- 'android_without_codecs_gyp_release_bot_minimal_symbols': [
- 'android_without_codecs', 'gyp', 'release_bot_minimal_symbols',
+ 'android_without_codecs_gn_release_bot_minimal_symbols': [
+ 'android_without_codecs', 'gn', 'release_bot_minimal_symbols',
],
'cast_gn_release_bot': [
@@ -995,6 +1027,14 @@
'cast', 'gn', 'release_trybot',
],
+ 'chrome_with_codecs_blink_logging_gyp_release_trybot': [
+ 'chrome_with_codecs', 'blink_logging', 'gyp', 'release_trybot',
+ ],
+
+ 'chrome_with_codecs_blink_logging_gyp_release_trybot_x86': [
+ 'chrome_with_codecs', 'blink_logging', 'gyp', 'release_trybot', 'x86',
+ ],
+
'chromeos_gn_debug_bot': [
'chromeos', 'gn', 'debug_bot',
],
@@ -1007,8 +1047,21 @@
'chromeos', 'ozone', 'gn', 'release_trybot',
],
- 'embedded_gyp_debug_bot': [
- 'embedded', 'gyp', 'debug_bot',
+ 'closure_compilation': [
+ # The closure bots run their own recipe and shouldn't go through MB.
+ 'gyp', 'error',
+ ],
+
+ 'codesearch_gn': [
+ # The Codesearch bots run their own recipe and invoke GN directly.
+ 'error', 'gn'
+ ],
+
+ # The 'cros_chrome_sdk_* configs are placeholders that indicate
+ # that the GYP_DEFINES (or GN args) are set by the `cros chrome-sdk`
+ # wrapper and need to be looked at specially.
+ 'cros_chrome_sdk_gn': [
+ 'gn', 'cros_chrome_sdk',
],
# The 'findit' config is used by the *_variable_* bots, which run
@@ -1020,39 +1073,37 @@
'error',
],
- # This is the "deployment" config for the blimp builds. Currently
- # we want them to be debug, non-optimized builds (and we don't need any
- # chrome branding), so we don't use the "official" mixin.
- 'gn_blimp_debug': [
- 'gn', 'blimp', 'debug',
- ],
-
- 'gn_cfi_release_bot': [
- 'gn', 'cfi', 'release_bot',
+ 'gn_cfi_diag_release_static': [
+ 'gn', 'cfi', 'cfi_diag', 'release', 'static',
],
- 'gn_cfi_release_trybot': [
- 'gn', 'cfi', 'release_trybot',
+ 'gn_cfi_release_static': [
+ 'gn', 'cfi', 'release', 'static',
],
- 'gn_cfi_diag_release_bot': [
- 'gn', 'cfi', 'cfi_diag', 'release_bot',
+ 'gn_cfi_release_static_dcheck_always_on': [
+ 'gn', 'cfi', 'release', 'static', 'dcheck_always_on',
],
'gn_debug_bot': [
'gn', 'debug_bot',
],
- 'gn_debug_bot_minimal_symbols': [
- 'gn', 'debug_bot_minimal_symbols',
+ 'gn_debug_bot_minimal_symbols_chrome_with_codecs': [
+ 'gn', 'debug_bot_minimal_symbols', 'chrome_with_codecs',
],
'gn_debug_bot_minimal_symbols_x86': [
'gn', 'debug_bot_minimal_symbols', 'x86',
],
- 'gn_debug_static_bot': [
- 'gn', 'debug_static_bot',
+ 'gn_debug_libfuzzer_asan': [
+ 'gn', 'debug', 'libfuzzer', 'asan', 'proprietary_codecs', 'pdf_xfa',
+ 'disable_nacl',
+ ],
+
+ 'gn_debug_static_bot_chrome_with_codecs': [
+ 'gn', 'debug_static_bot', 'chrome_with_codecs',
],
'gn_linux_upload': [
@@ -1067,7 +1118,9 @@
'gn', 'official', 'goma',
],
- 'gn_official_goma_lto': ['gn', 'official', 'goma', 'lto'],
+ 'gn_official_goma_lto': [
+ 'gn', 'official', 'goma', 'lto',
+ ],
'gn_official_goma_minimal_symbols_android': [
'gn', 'official', 'goma', 'minimal_symbols', 'android',
@@ -1081,22 +1134,166 @@
'gn', 'release_bot',
],
- 'gn_release_bot_minimal_symbols': [
- 'gn', 'release_bot_minimal_symbols',
+ 'gn_release_bot_chrome_with_codecs': [
+ 'gn', 'release_bot', 'chrome_with_codecs',
+ ],
+
+ 'gn_release_bot_minimal_symbols_chrome_with_codecs': [
+ 'gn', 'release_bot_minimal_symbols', 'chrome_with_codecs',
],
'gn_release_bot_minimal_symbols_x86': [
'gn', 'release_bot_minimal_symbols', 'x86',
],
+ 'gn_release_bot_x86': [
+ 'gn', 'release_bot', 'x86',
+ ],
+
+ 'gn_release_drmemory_drfuzz': [
+ 'gn', 'release', 'drmemory', 'drfuzz', 'proprietary_codecs',
+ ],
+
+ 'gn_release_drmemory_drfuzz_x86': [
+ 'gn', 'release', 'drmemory', 'drfuzz', 'x86', 'proprietary_codecs',
+ ],
+
+ 'gn_release_libfuzzer_asan': [
+ 'gn', 'release', 'libfuzzer', 'asan', 'proprietary_codecs', 'pdf_xfa',
+ 'disable_nacl',
+ ],
+
+ 'gn_release_libfuzzer_msan': [
+ 'gn', 'release', 'libfuzzer', 'msan', 'proprietary_codecs', 'pdf_xfa',
+ 'disable_nacl',
+ ],
+ 'gn_release_libfuzzer_ubsan': [
+ 'gn', 'release', 'libfuzzer', 'ubsan_security', 'proprietary_codecs',
+ 'pdf_xfa', 'disable_nacl',
+ ],
+
'gn_release_trybot': [
'gn', 'release_trybot',
],
+ 'gn_release_trybot_x64': [
+ 'gn', 'release_trybot', 'x64',
+ ],
+
'gn_release_trybot_x86': [
'gn', 'release_trybot', 'x86',
],
+ 'gn_windows_analyze': [
+ 'gn', 'no_symbols', 'disable_precompiled_headers',
+ 'shared', 'x86', 'win_analyze',
+ ],
+
+ 'gn_ubsan_vptr_release_bot': [
+ 'gn', 'ubsan_vptr', 'ubsan_no_recover_hack', 'release_bot',
+ ],
+
+ 'gyp_asan_edge_fuzzer_v8_heap_chromeos_codecs_release_bot_hybrid': [
+ 'gyp', 'asan', 'edge', 'fuzzer', 'v8_heap', 'chromeos_codecs',
+ 'release_bot', 'hybrid',
+ ],
+
+ 'gyp_asan_edge_fuzzer_v8_heap_debug_bot_hybrid': [
+ 'gyp', 'asan', 'edge', 'fuzzer', 'v8_heap', 'debug_bot', 'hybrid',
+ ],
+
+ 'gyp_asan_edge_fuzzer_v8_heap_release_bot_hybrid': [
+ 'gyp', 'asan', 'edge', 'fuzzer', 'v8_heap', 'release_bot', 'hybrid',
+ ],
+
+ 'gyp_asan_edge_fuzzer_v8_heap_release_static_x86': [
+ 'gyp', 'asan', 'edge', 'fuzzer', 'v8_heap', 'release', 'static', 'x86',
+ ],
+
+ 'gyp_asan_edge_fuzzer_v8_heap_symbolized_release_bot_hybrid': [
+ 'gyp', 'asan', 'edge', 'fuzzer', 'v8_heap', 'symbolized',
+ 'release_bot', 'hybrid',
+ ],
+
+ 'gyp_asan_fuzzer_v8_heap_chrome_with_codecs_release_bot': [
+ 'gyp', 'asan', 'fuzzer', 'v8_heap', 'chrome_with_codecs', 'release_bot',
+ ],
+
+ 'gyp_asan_fuzzer_v8_heap_chrome_with_codecs_release_static_x86': [
+ 'gyp', 'asan', 'fuzzer', 'v8_heap', 'chrome_with_codecs',
+ 'release', 'static', 'x86',
+ ],
+
+ 'gyp_asan_fuzzer_v8_heap_debug_symbols_static_bot': [
+ 'gyp', 'asan', 'fuzzer', 'v8_heap', 'debug_symbols_static_bot',
+ ],
+
+ 'gyp_asan_fuzzer_v8_heap_release_bot': [
+ 'gyp', 'asan', 'fuzzer', 'v8_heap', 'release_bot',
+ ],
+
+ 'gyp_asan_fuzzer_v8_heap_release_static_x86': [
+ 'gyp', 'asan', 'fuzzer', 'v8_heap', 'release', 'static', 'x86',
+ ],
+
+ 'gyp_asan_lsan_edge_fuzzer_debug_bot': [
+ 'gyp', 'asan', 'lsan', 'edge', 'fuzzer', 'debug_bot',
+ ],
+
+ 'gyp_asan_lsan_edge_fuzzer_v8_heap_chromeos_codecs_release_bot': [
+ 'gyp', 'asan', 'lsan', 'edge', 'v8_heap', 'chromeos_codecs',
+ 'release_bot',
+ ],
+
+ 'gyp_asan_lsan_edge_fuzzer_v8_heap_release_bot': [
+ 'gyp', 'asan', 'lsan', 'edge', 'fuzzer', 'v8_heap', 'release_bot',
+ ],
+
+ 'gyp_asan_lsan_edge_fuzzer_v8_heap_symbolized_release_bot': [
+ 'gyp', 'asan', 'lsan', 'edge', 'v8_heap', 'symbolized', 'release_bot',
+ ],
+
+ 'gyp_chromeos_asan_lsan_edge_fuzzer_v8_heap_release_bot': [
+ 'gyp', 'chromeos', 'asan', 'lsan', 'edge', 'fuzzer', 'v8_heap',
+ 'release_bot',
+ ],
+
+ 'gyp_chromeos_with_codecs_debug_bot': [
+ 'gyp', 'chromeos_with_codecs', 'debug_bot',
+ ],
+
+ 'gyp_clang_minimal_symbols_shared_release_bot_x86': [
+ 'gyp', 'clang', 'minimal_symbols', 'shared_release_bot', 'x86',
+ ],
+
+ 'gyp_debug_bot': [
+ 'gyp', 'debug_bot',
+ ],
+
+ 'gyp_debug_bot_minimal_symbols_x64': [
+ 'gyp', 'debug_bot_minimal_symbols', 'x64',
+ ],
+
+ 'gyp_debug_bot_minimal_symbols_x86': [
+ 'gyp', 'debug_bot_minimal_symbols', 'x86',
+ ],
+
+ 'gyp_drmemory_shared_release_x86': [
+ 'gyp', 'drmemory', 'shared', 'release', 'x86',
+ ],
+
+ 'gyp_drmemory_shared_release_x64': [
+ 'gyp', 'drmemory', 'shared', 'release', 'x64',
+ ],
+
+ 'gyp_msan_edge_release_bot': [
+ 'gyp', 'msan', 'edge', 'release_bot',
+ ],
+
+ 'gyp_msan_no_origins_edge_release_bot': [
+ 'gyp', 'msan_no_origins', 'edge', 'release_bot',
+ ],
+
'gyp_official': [
'gyp', 'official',
],
@@ -1135,8 +1332,12 @@
'gyp', 'official', 'x64',
],
- 'gyp_release_bot_android': [
- 'gyp', 'release_bot', 'android',
+ 'gyp_release_bot': [
+ 'gyp', 'release_bot',
+ ],
+
+ 'gyp_release_bot_minimal_symbols_x86': [
+ 'gyp', 'release_bot_minimal_symbols', 'x86'
],
'gyp_release_trybot': [
@@ -1147,46 +1348,28 @@
'gyp', 'release_trybot', 'x64',
],
- 'gn_release_libfuzzer_asan': [
- 'gn', 'release', 'libfuzzer', 'asan', 'proprietary_codecs', 'pdf_xfa',
- 'disable_nacl',
- ],
-
- 'gn_release_libfuzzer_msan': [
- 'gn', 'release', 'libfuzzer', 'msan', 'proprietary_codecs', 'pdf_xfa',
- 'disable_nacl',
- ],
- 'gn_release_libfuzzer_ubsan': [
- 'gn', 'release', 'libfuzzer', 'ubsan_security', 'proprietary_codecs',
- 'pdf_xfa', 'disable_nacl',
- ],
-
- 'gn_release_drmemory_drfuzz_x86': [
- 'gn', 'release', 'drmemory', 'drfuzz', 'x86', 'proprietary_codecs',
- ],
- 'gn_release_drmemory_drfuzz': [
- 'gn', 'release', 'drmemory', 'drfuzz', 'proprietary_codecs',
+ 'gyp_shared_release_bot_minimal_symbols_x86': [
+ 'gyp', 'shared_release_bot', 'minimal_symbols', 'x86',
],
- 'gn_windows_analyze': [
- 'gn', 'no_symbols', 'disable_precompiled_headers',
- 'shared', 'x86', 'win_analyze',
+ 'gyp_syzyasan_no_pch_win_z7_x86': [
+ 'gyp', 'syzyasan', 'no_pch', 'win_z7', 'x86',
],
- 'gyp_valgrind_release_bot': [
- 'gyp', 'valgrind', 'release_bot',
+ 'gyp_tsan_disable_nacl_line_tables_debug_bot': [
+ 'gyp', 'tsan', 'disable_nacl', 'line_tables', 'debug_bot',
],
- 'gyp_valgrind_chromeos_release_bot': [
- 'gyp', 'chromeos', 'valgrind', 'release_bot',
+ 'gyp_tsan_disable_nacl_line_tables_release_bot': [
+ 'gyp', 'tsan', 'disable_nacl', 'line_tables', 'release_bot',
],
- 'gyp_drmemory_shared_release_x86': [
- 'gyp', 'drmemory', 'shared', 'release', 'x86',
+ 'gyp_ubsan_release_bot': [
+ 'gyp', 'ubsan', 'release_bot',
],
- 'gyp_drmemory_shared_release_x64': [
- 'gyp', 'drmemory', 'shared', 'release', 'x64',
+ 'gyp_ubsan_vptr_edge_release_bot': [
+ 'gyp', 'ubsan_vptr', 'edge', 'release_bot',
],
# The 'ios' configs are just used for auditing. iOS bots
@@ -1198,6 +1381,10 @@
'ios_gyp': ['gyp', 'error'],
+ 'mac_views_browser_gyp_release_bot': [
+ 'mac_views_browser', 'gyp', 'release_bot',
+ ],
+
# This is used to indicate that the bot runs the nacl annotator-based
# configs and switching them is out of scope for MB.
'nacl_annotator': [ 'error' ],
@@ -1208,10 +1395,22 @@
'error',
],
+ 'noswarming_gn_debug_bot_x64': [
+ 'noswarming', 'gn', 'debug_bot', 'x64',
+ ],
+
'noswarming_gn_release_bot': [
'noswarming', 'gn', 'release_bot',
],
+ 'noswarming_gn_release_bot_minimal_symbols_x64': [
+ 'noswarming', 'gn', 'release_bot', 'minimal_symbols', 'x64',
+ ],
+
+ 'noswarming_gn_release_bot_x64': [
+ 'noswarming', 'gn', 'release_bot', 'x64',
+ ],
+
'noswarming_gyp_release_bot_mac_strip': [
'noswarming', 'gyp', 'release_bot', 'mac_strip',
],
@@ -1220,42 +1419,78 @@
'noswarming', 'gyp', 'release_bot', 'minimal_symbols', 'x86',
],
- 'noswarming_gyp_release_trybot_minimal_symbols_x86': [
- 'noswarming', 'gyp', 'release_trybot', 'minimal_symbols', 'x86',
+ 'noswarming_gyp_release_bot_x64': [
+ 'noswarming', 'gyp', 'release_bot', 'x64',
],
- 'swarming_android_gn_release_bot_minimal_symbols': [
- 'swarming', 'android', 'gn', 'release_bot_minimal_symbols',
+ 'noswarming_gyp_release_trybot': [
+ 'noswarming', 'gyp', 'release_trybot',
+ ],
+
+ 'noswarming_gyp_release_trybot_x64': [
+ 'noswarming', 'gyp', 'release_trybot', 'x64',
+ ],
+
+ 'noswarming_gyp_release_trybot_x86': [
+ 'noswarming', 'gyp', 'release_trybot', 'x86',
+ ],
+
+ 'swarming_android_gn_debug_static_bot': [
+ 'swarming', 'android', 'gn', 'debug_static_bot',
],
- 'swarming_android_gyp_debug_static_bot': [
- 'swarming', 'android', 'gyp', 'debug_static_bot',
+ 'swarming_android_gn_debug_static_bot_arm64': [
+ 'swarming', 'android', 'gn', 'debug_static_bot', 'arm64',
],
- 'swarming_android_gyp_debug_static_bot_arm64': [
- 'swarming', 'android', 'gyp', 'debug_static_bot', 'arm64',
+ 'swarming_android_gn_debug_trybot': [
+ 'swarming', 'android', 'gn', 'debug_trybot',
],
- 'swarming_android_gyp_debug_trybot': [
- 'swarming', 'android', 'gyp', 'debug_trybot',
+ 'swarming_android_gn_debug_trybot_arm64': [
+ 'swarming', 'android', 'gn', 'debug_trybot', 'arm64',
],
- 'swarming_android_gyp_debug_trybot_arm64': [
- 'swarming', 'android', 'gyp', 'debug_trybot', 'arm64',
+ 'swarming_android_gn_release_bot_minimal_symbols': [
+ 'swarming', 'android', 'gn', 'release_bot_minimal_symbols',
+ ],
+
+ 'swarming_android_gn_release_bot_minimal_symbols_arm64': [
+ 'swarming', 'android', 'gn', 'release_bot_minimal_symbols', 'arm64',
],
- 'swarming_android_gyp_release_bot_minimal_symbols': [
- 'swarming', 'android', 'gyp', 'release_bot_minimal_symbols',
+ 'swarming_android_gn_release_trybot': [
+ 'swarming', 'android', 'gn', 'release_trybot',
],
- 'swarming_android_gyp_release_trybot': [
- 'swarming', 'android', 'gyp', 'release_trybot',
+ 'swarming_asan_dcheck_gyp_release_bot': [
+ 'swarming', 'asan', 'dcheck_always_on', 'gyp', 'release_bot',
+ ],
+
+ 'swarming_asan_lsan_chromeos_gyp_release_trybot': [
+ 'swarming', 'asan', 'lsan', 'chromeos', 'release_trybot',
],
'swarming_asan_lsan_gyp_release_trybot': [
'swarming', 'asan', 'lsan', 'release_trybot',
],
+ 'swarming_chromeos_gn_release_trybot': [
+ 'swarming', 'chromeos_with_codecs', 'gn', 'release_trybot',
+ ],
+
+ 'swarming_chromeos_gyp_debug_bot': [
+ 'swarming', 'chromeos_with_codecs', 'gyp', 'debug_bot',
+ ],
+
+ 'swarming_chromeos_gyp_debug_trybot': [
+ 'swarming', 'chromeos_with_codecs', 'gyp', 'debug_trybot',
+ ],
+
+ 'swarming_chromeos_gyp_ozone_release_trybot': [
+ 'swarming', 'chromeos_with_codecs', 'gyp', 'ozone', 'release_trybot',
+ ],
+
'swarming_chromeos_gyp_release_bot': [
'swarming', 'chromeos_with_codecs', 'gyp', 'release_bot',
],
@@ -1264,31 +1499,87 @@
'swarming', 'chromeos_with_codecs', 'gyp', 'release_trybot',
],
- 'swarming_msan_gyp_release_trybot': [
+ 'swarming_chromeos_msan_gyp_release_trybot': [
'swarming', 'chromeos', 'msan', 'gyp', 'release_trybot',
],
- 'swarming_gn_asan_lsan_release_bot_x64': [
- 'swarming', 'gn', 'asan', 'lsan', 'release_bot', 'x64',
+ 'swarming_chromeos_ozone_gyp_release_bot': [
+ 'chromeos_with_codecs', 'goma', 'gyp', 'ozone', 'static', 'swarming',
],
- 'swarming_gn_msan_release_bot_x64': [
- 'swarming', 'gn', 'msan', 'release_bot', 'x64',
+ 'swarming_clang_tot_lld_release_shared': [
+ # TODO(crbug.com/605819): Enable debug info in release builds.
+ 'swarming', 'gn', 'clang_tot', 'release', 'shared', 'use_lld',
],
- 'swarming_gpu_fyi_tests_gn_debug_bot': [
- 'swarming', 'gpu_tests', 'internal_gles2_conform_tests', 'gn',
- 'debug_bot', 'angle_deqp_tests',
+ 'swarming_clang_tot_shared_debug': [
+ 'swarming', 'gn', 'clang_tot', 'shared', 'debug',
],
- 'swarming_gpu_fyi_tests_gn_debug_trybot': [
- 'swarming', 'gpu_tests', 'internal_gles2_conform_tests', 'gn',
- 'debug_trybot', 'angle_deqp_tests',
+ 'swarming_gn_asan_lsan_release_bot': [
+ 'swarming', 'gn', 'asan', 'lsan', 'release_bot',
+ ],
+
+ 'swarming_gn_debug_bot': [
+ 'swarming', 'gn', 'debug_bot',
+ ],
+
+ 'swarming_gn_debug_bot_minimal_symbols_x64': [
+ 'swarming', 'gn', 'debug_bot_minimal_symbols', 'x64',
+ ],
+
+ 'swarming_gn_debug_bot_x86': [
+ 'swarming', 'gn', 'debug_bot', 'x86',
+ ],
+
+ 'swarming_gn_debug_trybot': [
+ 'swarming', 'gn', 'debug_trybot',
+ ],
+
+ 'swarming_gn_debug_trybot_x86': [
+ 'swarming', 'gn', 'debug_trybot', 'x86',
+ ],
+
+ 'swarming_gn_msan_release_bot': [
+ 'swarming', 'gn', 'msan', 'release_bot',
+ ],
+
+ 'swarming_gn_release_bot': [
+ 'swarming', 'gn', 'release_bot',
+ ],
+
+ 'swarming_gn_release_bot_arm': [
+ 'swarming', 'gn', 'release_bot', 'arm', 'crosscompile',
+ ],
+
+ 'swarming_gn_release_bot_minimal_symbols': [
+ 'swarming', 'gn', 'release_bot_minimal_symbols',
+ ],
+
+ 'swarming_gn_release_bot_minimal_symbols_x64': [
+ 'swarming', 'gn', 'release_bot_minimal_symbols', 'x64',
+ ],
+
+ 'swarming_gn_release_bot_x64': [
+ 'swarming', 'gn', 'release_bot', 'x64',
],
- 'swarming_gpu_fyi_tests_gn_release_bot': [
+ 'swarming_gn_release_trybot': [
+ 'swarming', 'gn', 'release_bot',
+ ],
+
+ 'swarming_gn_release_trybot_x64': [
+ 'swarming', 'gn', 'release_trybot', 'x64',
+ ],
+
+ 'swarming_gpu_fyi_tests_chromeos_gyp_release_trybot': [
+ 'swarming', 'gpu_tests', 'internal_gles2_conform_tests', 'gyp',
+ 'release_trybot', 'angle_deqp_tests', 'chromeos',
+ ],
+
+ 'swarming_gpu_fyi_tests_gn_debug_trybot': [
'swarming', 'gpu_tests', 'internal_gles2_conform_tests', 'gn',
- 'release_bot', 'angle_deqp_tests',
+ 'debug_trybot', 'angle_deqp_tests',
],
'swarming_gpu_fyi_tests_gn_release_trybot': [
@@ -1296,103 +1587,115 @@
'release_bot', 'angle_deqp_tests',
],
- 'swarming_gpu_tests_deqp_gles_gyp_debug_bot_minimal_symbols_x64': [
- 'swarming', 'gpu_tests', 'angle_deqp_tests',
- 'internal_gles2_conform_tests', 'gyp', 'debug_bot',
- 'minimal_symbols', 'x64',
+ 'swarming_gpu_fyi_tests_gyp_clang_debug_trybot_x86': [
+ 'swarming', 'gpu_tests', 'internal_gles2_conform_tests', 'gyp',
+ 'clang', 'debug_trybot', 'x86',
],
- 'swarming_gpu_tests_deqp_gles_gyp_debug_bot_minimal_symbols_x86': [
- 'swarming', 'gpu_tests', 'angle_deqp_tests',
- 'internal_gles2_conform_tests', 'gyp', 'debug_bot',
- 'minimal_symbols', 'x86',
+ 'swarming_gpu_fyi_tests_gyp_debug_trybot': [
+ 'swarming', 'gpu_tests', 'internal_gles2_conform_tests', 'gyp',
+ 'debug_trybot',
],
- 'swarming_gpu_tests_deqp_gles_gyp_release_trybot_minimal_symbols_x64': [
- 'swarming', 'gpu_tests', 'angle_deqp_tests',
- 'internal_gles2_conform_tests', 'gyp', 'release_trybot',
- 'minimal_symbols', 'x64',
+ 'swarming_gpu_fyi_tests_gyp_release_trybot': [
+ 'swarming', 'gpu_tests', 'internal_gles2_conform_tests', 'gyp',
+ 'release_trybot',
],
- 'swarming_gpu_tests_deqp_gles_gyp_release_trybot_minimal_symbols_x86': [
+ 'swarming_gpu_tests_deqp_gles_gyp_debug_trybot_x64': [
'swarming', 'gpu_tests', 'angle_deqp_tests',
- 'internal_gles2_conform_tests', 'gyp', 'release_trybot',
- 'minimal_symbols', 'x86',
+ 'internal_gles2_conform_tests', 'gyp', 'debug_trybot', 'x64',
],
- 'swarming_gpu_tests_deqp_gles_gyp_release_bot_minimal_symbols_x64': [
+ 'swarming_gpu_tests_deqp_gles_gyp_debug_trybot_x86': [
'swarming', 'gpu_tests', 'angle_deqp_tests',
- 'internal_gles2_conform_tests', 'gyp', 'release_bot',
- 'minimal_symbols', 'x64',
+ 'internal_gles2_conform_tests', 'gyp', 'debug_trybot', 'x86',
],
- 'swarming_gpu_tests_deqp_gles_gyp_release_bot_minimal_symbols_x86': [
+ 'swarming_gpu_tests_deqp_gles_gyp_release_trybot_x64': [
'swarming', 'gpu_tests', 'angle_deqp_tests',
- 'internal_gles2_conform_tests', 'gyp', 'release_bot',
- 'minimal_symbols', 'x86',
+ 'internal_gles2_conform_tests', 'gyp', 'release_trybot', 'x64',
],
- 'swarming_gpu_tests_gn_debug_bot': [
- 'swarming', 'gpu_tests', 'gn', 'debug_bot',
+ 'swarming_gpu_tests_deqp_gles_gyp_release_trybot_x86': [
+ 'swarming', 'gpu_tests', 'angle_deqp_tests',
+ 'internal_gles2_conform_tests', 'gyp', 'release_trybot', 'x86',
],
- 'swarming_gpu_tests_gn_release_bot': [
- 'swarming', 'gpu_tests', 'gn', 'release_bot',
+ 'swarming_gpu_tests_gn_debug_trybot': [
+ 'swarming', 'gpu_tests', 'gn', 'debug_trybot',
],
'swarming_gpu_tests_gn_release_trybot': [
'swarming', 'gpu_tests', 'gn', 'release_trybot',
],
- 'swarming_gpu_tests_gyp_debug_bot_minimal_symbols_x86': [
- 'swarming', 'gpu_tests', 'gyp', 'debug_bot', 'minimal_symbols', 'x86',
+ 'swarming_gpu_tests_gyp_debug_trybot': [
+ 'swarming', 'gpu_tests', 'gyp', 'debug_trybot',
],
- 'swarming_gpu_tests_gyp_release_bot_minimal_symbols_x86': [
- 'swarming', 'gpu_tests', 'gyp', 'release_bot', 'minimal_symbols', 'x86',
+ 'swarming_gpu_tests_gyp_debug_trybot_x86': [
+ 'swarming', 'gpu_tests', 'gyp', 'debug_trybot', 'x86',
],
- 'swarming_gpu_tests_gyp_release_trybot_minimal_symbols_x86': [
- 'swarming', 'gpu_tests', 'gyp', 'release_trybot', 'minimal_symbols',
- 'x86',
+ 'swarming_gpu_tests_gyp_release_bot': [
+ 'swarming', 'gpu_tests', 'gyp', 'release_bot',
],
- 'swarming_gn_debug_bot': [
- 'swarming', 'gn', 'debug_bot',
+ 'swarming_gpu_tests_gyp_release_bot_minimal_symbols_x86': [
+ 'swarming', 'gpu_tests', 'gyp', 'release_bot', 'minimal_symbols', 'x86',
],
- 'swarming_gn_debug_bot_minimal_symbols_x64': [
- 'swarming', 'gn', 'debug_bot_minimal_symbols', 'x64',
+ 'swarming_gpu_tests_gyp_release_bot_x86': [
+ 'swarming', 'gpu_tests', 'gyp', 'release_bot',
],
- 'swarming_gn_debug_bot_x64': [
- 'swarming', 'gn', 'debug_bot', 'x64',
+ 'swarming_gpu_tests_gyp_release_trybot': [
+ 'swarming', 'gpu_tests', 'gyp', 'release_trybot',
],
- 'swarming_gn_debug_trybot': [
- 'swarming', 'gn', 'debug_trybot',
+ 'swarming_gpu_tests_gyp_release_trybot_x86': [
+ 'swarming', 'gpu_tests', 'gyp', 'release_trybot', 'x86',
],
- 'swarming_gn_release_bot': [
- 'swarming', 'gn', 'release_bot',
+ ('swarming_gyp_asan_clang_edge_fuzzer'
+ '_static_v8_heap_x86_full_symbols_release'): [
+ 'swarming', 'gyp', 'asan', 'clang_tot', 'edge', 'fuzzer', 'static',
+ 'v8_heap', 'full_symbols', 'release',
],
- 'swarming_gn_release_bot_x64': [
- 'swarming', 'gn', 'release_bot', 'x64',
+ 'swarming_gyp_asan_clang_fuzzer_shared_v8_heap_x86_full_symbols_release': [
+ 'swarming', 'gyp', 'asan', 'clang_tot', 'fuzzer', 'shared', 'v8_heap',
+ 'full_symbols', 'release',
],
- 'swarming_gn_release_trybot': [
- 'swarming', 'gn', 'release_bot',
+ 'swarming_gyp_asan_clang_fuzzer_static_v8_heap_x86_full_symbols_release': [
+ 'swarming', 'gyp', 'asan', 'clang_tot', 'fuzzer', 'static', 'v8_heap',
+ 'full_symbols', 'release',
],
- 'swarming_gn_release_trybot_minimal_symbols_x64': [
- 'swarming', 'gn', 'release_trybot', 'minimal_symbols', 'x64',
+ 'swarming_gyp_asan_clang_tot_full_symbols_static_release': [
+ 'swarming', 'gyp', 'asan', 'clang_tot', 'full_symbols', 'static',
+ 'release',
+ ],
+
+ 'swarming_gyp_chromeos_msan_release_bot': [
+ 'swarming', 'gyp', 'chromeos', 'msan', 'release_bot',
],
'swarming_gyp_clang_debug_bot_minimal_symbols_x86': [
'swarming', 'gyp', 'clang', 'debug_bot', 'minimal_symbols', 'x86',
],
+ 'swarming_gyp_clang_debug_trybot_x86': [
+ 'swarming', 'gyp', 'clang', 'debug_trybot', 'x86',
+ ],
+
+ 'swarming_gyp_clang_minimal_symbols_shared_release_bot_x64': [
+ 'swarming', 'gyp', 'clang', 'minimal_symbols', 'shared_release_bot',
+ 'x64',
+ ],
+
'swarming_gyp_clang_official_release_bot_minimal_symbols_x64': [
'swarming', 'gyp', 'clang', 'official', 'release_bot',
'minimal_symbols', 'x64',
@@ -1403,98 +1706,144 @@
'minimal_symbols', 'x86',
],
- 'swarming_gyp_clang_official_release_trybot_minimal_symbols_x64': [
- 'swarming', 'gyp', 'clang', 'official', 'release_trybot',
- 'minimal_symbols', 'x64',
+ 'swarming_gyp_clang_official_release_trybot_x64': [
+ 'swarming', 'gyp', 'clang', 'official', 'release_trybot', 'x64',
],
- 'swarming_gyp_clang_official_release_trybot_minimal_symbols_x86': [
- 'swarming', 'gyp', 'clang', 'official', 'release_trybot',
- 'minimal_symbols', 'x86',
+ 'swarming_gyp_clang_official_release_trybot_x86': [
+ 'swarming', 'gyp', 'clang', 'official', 'release_trybot', 'x86',
],
- 'swarming_gyp_debug_bot_minimal_symbols_x64': [
- 'swarming', 'gyp', 'debug_bot_minimal_symbols', 'x64',
+ 'swarming_gyp_clang_shared_release_bot_minimal_symbols_x86': [
+ 'swarming', 'gyp', 'clang', 'shared_release_bot', 'minimal_symbols',
+ 'x86',
],
- 'swarming_gyp_debug_bot_minimal_symbols_x86': [
- 'swarming', 'gyp', 'debug_bot_minimal_symbols', 'x86',
+ 'swarming_gyp_clang_tot_asan_lsan_static_release': [
+ 'swarming', 'gyp', 'clang_tot', 'asan', 'lsan', 'static', 'release',
],
- 'swarming_gyp_debug_bot_no_symbols_x86': [
- 'swarming', 'gyp', 'debug_bot', 'no_symbols', 'x86',
+ 'swarming_gyp_clang_tot_edge_ubsan_no_recover_hack_static_release': [
+ 'swarming', 'gyp', 'clang_tot', 'edge', 'ubsan_no_recover_hack',
+ 'static', 'release',
],
- 'swarming_gyp_debug_bot_x64': [
- 'swarming', 'gyp', 'debug_bot', 'x64',
+ 'swarming_gyp_clang_tot_linux_dump_symbols_shared_release': [
+ # Enable debug info, as on official builders, to catch issues with
+ # optimized debug info.
+ 'swarming', 'gyp', 'clang_tot', 'linux_dump_symbols',
+ 'shared', 'release',
],
- 'swarming_gyp_debug_trybot_x86': [
- 'swarming', 'gyp', 'debug_trybot', 'x86',
+ 'swarming_gyp_clang_tot_minimal_symbols_shared_debug': [
+ 'swarming', 'gyp', 'clang_tot', 'minimal_symbols', 'shared', 'debug',
],
- 'swarming_gyp_release_bot': [
- 'swarming', 'gyp', 'release_bot',
+ 'swarming_gyp_clang_tot_minimal_symbols_shared_debug_use_lld_x64': [
+ 'swarming', 'gyp', 'clang_tot', 'minimal_symbols', 'shared', 'debug',
+ 'use_lld', 'x64',
],
- 'swarming_gyp_release_bot_arm': [
- 'swarming', 'gyp', 'release_bot', 'arm', 'crosscompile',
+ 'swarming_gyp_clang_tot_minimal_symbols_shared_debug_use_lld_x86': [
+ 'swarming', 'gyp', 'clang_tot', 'minimal_symbols', 'shared', 'debug',
+ 'use_lld', 'x86',
],
- 'swarming_gyp_release_bot_minimal_symbols_x64': [
- 'swarming', 'gyp', 'release_bot_minimal_symbols', 'x64',
+ 'swarming_gyp_clang_tot_minimal_symbols_shared_debug_x64': [
+ 'swarming', 'gyp', 'clang_tot', 'minimal_symbols', 'shared', 'debug',
+ 'x64',
],
- 'swarming_gyp_release_bot_minimal_symbols_x86': [
- 'swarming', 'gyp', 'release_bot_minimal_symbols', 'x86',
+ 'swarming_gyp_clang_tot_minimal_symbols_shared_debug_x86': [
+ 'swarming', 'gyp', 'clang_tot', 'minimal_symbols', 'shared', 'debug',
+ 'x86',
],
- 'swarming_gyp_release_bot_x64': [
- 'swarming', 'gyp', 'release_bot', 'x64',
+ 'swarming_gyp_clang_tot_minimal_symbols_shared_release_use_lld_x64': [
+ 'swarming', 'gyp', 'clang_tot', 'minimal_symbols', 'shared', 'release',
+ 'use_lld', 'x64',
],
- 'swarming_gyp_release_trybot_arm': [
- 'swarming', 'gyp', 'release_trybot', 'arm', 'crosscompile',
+ 'swarming_gyp_clang_tot_minimal_symbols_shared_release_use_lld_x86': [
+ 'swarming', 'gyp', 'clang_tot', 'minimal_symbols', 'shared', 'release',
+ 'use_lld', 'x86',
],
- 'swarming_gyp_release_trybot_minimal_symbols_x64': [
- 'swarming', 'gyp', 'release_trybot', 'minimal_symbols', 'x64',
+ 'swarming_gyp_clang_tot_minimal_symbols_shared_release': [
+ 'swarming', 'gyp', 'clang_tot', 'minimal_symbols', 'shared', 'release',
],
- 'swarming_gyp_release_trybot_minimal_symbols_x86': [
- 'swarming', 'gyp', 'release_trybot', 'minimal_symbols', 'x86',
+ 'swarming_gyp_clang_tot_minimal_symbols_shared_release_x64': [
+ 'swarming', 'gyp', 'clang_tot', 'minimal_symbols', 'shared', 'release',
+ 'x64',
],
- 'swarming_gyp_syzyasan_release_trybot_minimal_symbols_x86': [
- 'swarming', 'gyp', 'syzyasan', 'release_trybot', 'minimal_symbols',
+ 'swarming_gyp_clang_tot_minimal_symbols_shared_release_x86': [
+ 'swarming', 'gyp', 'clang_tot', 'minimal_symbols', 'shared', 'release',
'x86',
],
- 'swarming_tsan_gyp_release_trybot': [
- 'swarming', 'disable_nacl', 'tsan', 'gyp', 'release_trybot',
+ 'swarming_gyp_clang_tot_official_minimal_symbols_static_release_x64': [
+ 'swarming', 'gyp', 'clang_tot', 'official', 'minimal_symbols', 'static',
+ 'release', 'x64',
],
- 'gn_debug_bot_minimal_symbols_chrome_with_codecs': [
- 'gn', 'debug_bot_minimal_symbols', 'chrome_with_codecs',
+ 'swarming_gyp_clang_tot_official_minimal_symbols_static_release_x86': [
+ 'swarming', 'gyp', 'clang_tot', 'official', 'minimal_symbols', 'static',
+ 'release', 'x86',
],
- 'gn_debug_static_bot_chrome_with_codecs': [
- 'gn', 'debug_static_bot', 'chrome_with_codecs',
+ 'swarming_gyp_debug_bot': [
+ 'swarming', 'gyp', 'debug_bot',
],
- 'gn_release_bot_chrome_with_codecs': [
- 'gn', 'release_bot', 'chrome_with_codecs',
+ 'swarming_gyp_debug_bot_minimal_symbols_x86': [
+ 'swarming', 'gyp', 'debug_bot_minimal_symbols', 'x86',
],
- 'gn_release_bot_minimal_symbols_chrome_with_codecs': [
- 'gn', 'release_bot_minimal_symbols', 'chrome_with_codecs',
+ 'swarming_gyp_debug_trybot': [
+ 'swarming', 'gyp', 'debug_trybot',
+ ],
+
+ 'swarming_gyp_debug_trybot_x86': [
+ 'swarming', 'gyp', 'debug_trybot', 'x86',
+ ],
+
+ 'swarming_gyp_msan_release_bot': [
+ 'swarming', 'gyp', 'msan', 'release_bot',
+ ],
+
+ 'swarming_gyp_release_bot': [
+ 'swarming', 'gyp', 'release_bot',
],
- # This indicates that we haven't yet set up this bot w/ MB. This is
- # different from 'none' in that a bot set to 'none' should never do
- # compiles; a bot set to 'tbd' should do compiles but we haven't
- # added the entries yet.
- 'tbd': ['error'],
+ 'swarming_gyp_release_bot_minimal_symbols': [
+ 'swarming', 'gyp', 'release_bot_minimal_symbols',
+ ],
+
+ 'swarming_gyp_release_bot_minimal_symbols_x86': [
+ 'swarming', 'gyp', 'release_bot_minimal_symbols', 'x86',
+ ],
+
+ 'swarming_gyp_release_trybot_arm': [
+ 'swarming', 'gyp', 'release_trybot', 'arm', 'crosscompile',
+ ],
+
+ 'swarming_gyp_syzyasan_release_trybot_x86': [
+ 'swarming', 'gyp', 'syzyasan', 'release_trybot', 'x86',
+ ],
+
+ 'swarming_gyp_tsan_disable_nacl_release_bot': [
+ 'swarming', 'gyp', 'tsan', 'disable_nacl', 'release_bot',
+ ],
+
+ 'swarming_gyp_tsan_disable_nacl_release_trybot': [
+ 'swarming', 'gyp', 'tsan', 'disable_nacl', 'release_trybot',
+ ],
+
+ 'swarming_msan_gyp_release_trybot': [
+ 'swarming', 'msan', 'gyp', 'release_trybot',
+ ],
'win_clang_debug_bot': [
'gn', 'clang', 'debug_bot_minimal_symbols',
@@ -1547,14 +1896,19 @@
'gyp_defines': 'asan=1',
},
- # Removes dependencies on X11 and audio libraries for a containerized
- # build.
- 'blimp': {
- 'gn_args': ('use_aura=true use_ozone=true use_alsa=false '
- 'use_pulseaudio=false use_cups=false use_glib=false '
- 'use_low_quality_image_interpolation=true'),
- 'gyp_defines': ('use_aura=1 use_ozone=1 use_alsa=0 '
- 'use_pulseaudio=0 use_cups=0 use_glib=0'),
+ 'blink_logging': {
+ 'gn_args': 'blink_logging_always_on=true',
+ 'gyp_defines': 'blink_logging_always_on=1',
+ },
+
+ 'ffmpeg_branding_chrome': {
+ 'gn_args': 'ffmpeg_branding="Chrome"',
+ 'gyp_defines': 'ffmpeg_branding=Chrome',
+ },
+
+ 'ffmpeg_branding_chromeos': {
+ 'gn_args': 'ffmpeg_branding="ChromeOS"',
+ 'gyp_defines': 'ffmpeg_branding=ChromeOS',
},
'cast': {
@@ -1573,8 +1927,7 @@
},
'chrome_with_codecs': {
- 'gn_args': 'ffmpeg_branding="Chrome" proprietary_codecs=true',
- 'gyp_defines': 'ffmpeg_branding=Chrome proprietary_codecs=1',
+ 'mixins': ['ffmpeg_branding_chrome', 'proprietary_codecs'],
},
'chromeos': {
@@ -1582,15 +1935,17 @@
'gyp_defines': 'chromeos=1',
},
+ 'chromeos_codecs': {
+ 'mixins': ['ffmpeg_branding_chromeos', 'proprietary_codecs'],
+ },
+
'chromeos_with_codecs': {
- 'gn_args': 'ffmpeg_branding="ChromeOS" proprietary_codecs=true',
- 'gyp_defines': 'ffmpeg_branding=ChromeOS proprietary_codecs=1',
- 'mixins': ['chromeos'],
+ 'mixins': ['chromeos', 'chromeos_codecs'],
},
- 'clang_no_chrome_plugins': {
- 'gn_args': 'clang_use_chrome_plugins=false',
- 'gyp_defines': 'clang_use_chrome_plugins=0',
+ 'clang_tot': {
+ 'gn_args': 'llvm_force_head_revision=true clang_use_chrome_plugins=false',
+ 'gyp_defines': 'llvm_force_head_revision=1 clang_use_chrome_plugins=0',
'mixins': ['clang'],
},
@@ -1601,9 +1956,22 @@
'cronet': {
'gn_args': ('disable_file_support=true disable_ftp_support=true '
- 'enable_websockets=false'),
+ 'enable_websockets=false use_platform_icu_alternatives=true '
+ 'disable_brotli_filter=true'),
'gyp_defines': ('disable_file_support=1 disable_ftp_support=1 '
- 'enable_websockets=0'),
+ 'enable_websockets=0 use_platform_icu_alternatives=1 '
+ 'disable_brotli_filter=1'),
+ },
+
+ 'cros_chrome_sdk': {
+ # This is used so that the cros chrome_sdk (simplechrome) builders
+ # can manage the list of GYP_DEFINES and gn args in their .ebuild
+ # files and just pass through the desired arguments, hence not
+ # really using MB. If a bot uses this mixin, we expect that
+ # both GYP_DEFINES and GN_ARGS are set in the environment,
+ # and that GYP_DEFINES has chromeos=1 and GN_ARGS has
+ # target_os="chromeos" in it.
+ 'cros_passthrough': True,
},
'crosscompile': {
@@ -1636,10 +2004,19 @@
'mixins': ['debug_bot', 'minimal_symbols'],
},
+ 'debug_symbols_static_bot': {
+ 'mixins': ['debug', 'static', 'goma'],
+ },
+
'debug_static_bot': {
'mixins': ['debug', 'static', 'minimal_symbols', 'goma'],
},
+ 'debug_static_trybot': {
+ 'mixins': ['debug', 'static', 'dcheck_always_on', 'minimal_symbols',
+ 'goma'],
+ },
+
'debug_trybot': {
'mixins': ['debug_bot_minimal_symbols'],
},
@@ -1654,9 +2031,9 @@
'gyp_defines': 'chromium_win_pch=0',
},
- 'embedded': {
- 'gn_args': 'error',
- 'gyp_defines': 'embedded=1',
+ 'edge': {
+ 'gn_args': 'sanitizer_coverage_flags="edge"',
+ 'gyp_defines': 'sanitizer_coverage=edge',
},
# This mixin is used to force configs that use it to fail. It
@@ -1668,11 +2045,26 @@
'gyp_defines': 'target_arch=unknown',
},
+ 'ffmpeg_branding_chromeos': {
+ 'gn_args': 'ffmpeg_branding="ChromeOS"',
+ 'gyp_defines': 'ffmpeg_branding=ChromeOS',
+ },
+
'findbugs': {
'gn_args': 'run_findbugs=true',
'gyp_defines': 'run_findbugs=1',
},
+ 'full_symbols': {
+ 'gn_args': 'symbol_level=2',
+ 'gyp_defines': 'fastbuild=0',
+ },
+
+ 'fuzzer': {
+ 'gn_args': 'error', # TODO(GYP): implement enable_ipc_fuzzer=true
+ 'gyp_defines': 'enable_ipc_fuzzer=1',
+ },
+
'gn_linux_upload': {
'type': 'gn',
@@ -1688,8 +2080,8 @@
'goma': {
# The MB code will properly escape goma_dir if necessary in the GYP
# code path; the GN code path needs no escaping.
- 'gn_args': 'use_goma=true goma_dir="$(goma_dir)"',
- 'gyp_defines': 'use_goma=1 gomadir=$(goma_dir)',
+ 'gn_args': 'use_goma=true',
+ 'gyp_defines': 'use_goma=1',
},
'gpu_tests': {
@@ -1698,13 +2090,33 @@
'gyp': {'type': 'gyp'},
+ 'hybrid': {
+ 'gn_args': 'error', # TODO(GYP): figure out the equivalent for this
+ 'gyp_defines': 'v8_target_arch=arm target_arch=ia32 host_arch=x86_64',
+ 'mixins': ['disable_nacl'],
+ },
+
'internal_gles2_conform_tests': {
'gn_args': 'internal_gles2_conform_tests=true',
'gyp_defines': 'internal_gles2_conform_tests=1',
},
+ 'java_coverage': {
+ 'gn_args': 'emma_coverage=true emma_filter="org.chromium.*"',
+ },
+
'libfuzzer': { 'gn_args': 'use_libfuzzer=true' },
+ 'line_tables': {
+ 'gn_args': '', # TODO(GYP): check that this is not needed
+ 'gyp_defines': 'debug_extra_cflags="-gline-tables-only"',
+ },
+
+ 'linux_dump_symbols': {
+ 'gn_args': 'error', # TODO(crbug.com/605819): implement this.
+ 'gyp_defines': 'linux_dump_symbols=1',
+ },
+
'ubsan_security': { 'gn_args': 'is_ubsan_security=true' },
'lsan': {
@@ -1722,6 +2134,11 @@
'gyp_defines': 'mac_strip_release=1',
},
+ 'mac_views_browser': {
+ 'gn_args': 'mac_views_browser=true',
+ 'gyp_defines': 'mac_views_browser=1',
+ },
+
'minimal_symbols': {
'gn_args': 'symbol_level=1',
'gyp_defines': 'fastbuild=1',
@@ -1739,6 +2156,18 @@
'use_prebuilt_instrumented_libraries=1'),
},
+ 'msan_no_origins': {
+ 'gn_args': ('is_msan=true msan_track_origins=0 '
+ 'use_prebuilt_instrumented_libraries=true'),
+ 'gyp_defines': ('msan=1 msan_track_origins=0 '
+ 'use_prebuilt_instrumented_libraries=1'),
+ },
+
+ 'no_pch': {
+ 'gn_args': 'disable_precompiled_headers=true',
+ 'gyp_defines': 'chromium_win_pch=0',
+ },
+
'no_symbols': {
'gn_args': 'symbol_level=0',
'gyp_defines': 'fastbuild=2',
@@ -1792,6 +2221,10 @@
'gyp_defines': 'component=shared_library',
},
+ 'shared_release_bot': {
+ 'mixins': ['shared', 'release', 'goma']
+ },
+
'static': {
'gn_args': 'is_component_build=false',
'gyp_defines': 'component=static_library',
@@ -1802,6 +2235,12 @@
'gyp_defines': 'test_isolation_mode=prepare',
},
+ 'symbolized': {
+ 'gn_args': 'error', # TODO(GYP): add an equivalent flag for this
+ 'gyp_defines':
+ 'release_extra_cflags="-O1 -fno-inline-functions -fno-inline"',
+ },
+
'syzyasan': {
'gn_args': 'is_syzyasan=true',
'gyp_defines': 'syzyasan=1'
@@ -1812,11 +2251,44 @@
'gyp_defines': 'tsan=1',
},
+ 'ubsan': {
+ 'gn_args': 'is_ubsan=true',
+ 'gyp_defines': 'ubsan=1',
+ },
+
+ 'ubsan_no_recover_hack': {
+ # TODO(krasin): Remove when https://llvm.org/bugs/show_bug.cgi?id=25569
+ # is fixed and just use ubsan_vptr instead.
+ 'mixins': ['ubsan_vptr'],
+ 'gn_args': 'is_ubsan_no_recover=true',
+ 'gyp_defines': 'release_extra_cflags=-fno-sanitize-recover=undefined',
+ },
+
+ 'ubsan_vptr': {
+ 'gn_args': 'is_ubsan_vptr=true',
+ 'gyp_defines': 'ubsan_vptr=1',
+ },
+
+ 'use_lld': {
+ 'gn_args': 'use_lld=true',
+ 'gyp_defines': 'use_lld=1',
+ },
+
+ 'v8_heap': {
+ 'gn_args': 'error', # TODO(GYP): implement v8_enable_verify_heap=true
+ 'gyp_defines': 'v8_enable_verify_heap=1',
+ },
+
'win_analyze': {
'gn_args': 'use_vs_code_analysis=true',
'gyp_defines': 'win_analyze=1',
},
+ 'win_z7': {
+ 'gn_args': 'error', # TODO(GYP): implement win_z7=true
+ 'gyp_defines': 'win_z7=1',
+ },
+
'x64': {
'gn_args': 'target_cpu="x64"',
'gyp_defines': 'target_arch=x64',
@@ -1833,10 +2305,5 @@
'gn_args': 'is_component_build=true enable_iterator_debugging=false',
'gyp_defines': 'component=shared_library build_for_tool=drmemory',
},
-
- 'valgrind': {
- # TODO: add gn_args for 'build_for_tool=memcheck'
- 'gyp_defines': 'build_for_tool=memcheck',
- }
},
}
diff --git a/chromium/tools/mb/mb_unittest.py b/chromium/tools/mb/mb_unittest.py
index dbb093d3898..20ed720e374 100755
--- a/chromium/tools/mb/mb_unittest.py
+++ b/chromium/tools/mb/mb_unittest.py
@@ -56,6 +56,8 @@ class FakeMBW(mb.MetaBuildWrapper):
return self.files[path]
def WriteFile(self, path, contents, force_verbose=False):
+ if self.args.dryrun or self.args.verbose or force_verbose:
+ self.Print('\nWriting """\\\n%s""" to %s.\n' % (contents, path))
self.files[path] = contents
def Call(self, cmd, env=None, buffer_output=True):
@@ -118,6 +120,7 @@ TEST_CONFIG = """\
'fake_gyp_crosscompile_builder': 'gyp_crosscompile',
'fake_gn_debug_builder': 'gn_debug_goma',
'fake_gyp_builder': 'gyp_debug',
+ 'fake_gn_args_bot': '//build/args/bots/fake_master/fake_gn_args_bot.gn',
},
},
'mixins': {
@@ -131,8 +134,8 @@ TEST_CONFIG = """\
'gyp': {'type': 'gyp'},
'gn': {'type': 'gn'},
'goma': {
- 'gn_args': 'use_goma=true goma_dir="$(goma_dir)"',
- 'gyp_defines': 'goma=1 gomadir=$(goma_dir)',
+ 'gn_args': 'use_goma=true',
+ 'gyp_defines': 'goma=1',
},
'rel': {
'gn_args': 'is_debug=false',
@@ -176,6 +179,9 @@ class UnitTest(unittest.TestCase):
def fake_mbw(self, files=None, win32=False):
mbw = FakeMBW(win32=win32)
mbw.files.setdefault(mbw.default_config, TEST_CONFIG)
+ mbw.files.setdefault(
+ mbw.ToAbsPath('//build/args/bots/fake_master/fake_gn_args_bot.gn'),
+ 'is_debug = false\n')
if files:
for path, contents in files.items():
mbw.files[path] = contents
@@ -299,18 +305,36 @@ class UnitTest(unittest.TestCase):
})
def test_gn_gen(self):
+ mbw = self.fake_mbw()
self.check(['gen', '-c', 'gn_debug_goma', '//out/Default', '-g', '/goma'],
- ret=0,
- out=('/fake_src/buildtools/linux64/gn gen //out/Default '
- '\'--args=is_debug=true use_goma=true goma_dir="/goma"\' '
- '--check\n'))
+ mbw=mbw, ret=0)
+ self.assertMultiLineEqual(mbw.files['/fake_src/out/Default/args.gn'],
+ ('goma_dir = "/goma"\n'
+ 'is_debug = true\n'
+ 'use_goma = true\n'))
+
+ # Make sure we log both what is written to args.gn and the command line.
+ self.assertIn('Writing """', mbw.out)
+ self.assertIn('/fake_src/buildtools/linux64/gn gen //out/Default --check',
+ mbw.out)
mbw = self.fake_mbw(win32=True)
self.check(['gen', '-c', 'gn_debug_goma', '-g', 'c:\\goma', '//out/Debug'],
- mbw=mbw, ret=0,
- out=('c:\\fake_src\\buildtools\\win\\gn.exe gen //out/Debug '
- '"--args=is_debug=true use_goma=true goma_dir=\\"'
- 'c:\\goma\\"" --check\n'))
+ mbw=mbw, ret=0)
+ self.assertMultiLineEqual(mbw.files['c:\\fake_src\\out\\Debug\\args.gn'],
+ ('goma_dir = "c:\\\\goma"\n'
+ 'is_debug = true\n'
+ 'use_goma = true\n'))
+ self.assertIn('c:\\fake_src\\buildtools\\win\\gn.exe gen //out/Debug '
+ '--check\n', mbw.out)
+
+ mbw = self.fake_mbw()
+ self.check(['gen', '-m', 'fake_master', '-b', 'fake_gn_args_bot',
+ '//out/Debug'],
+ mbw=mbw, ret=0)
+ self.assertEqual(
+ mbw.files['/fake_src/out/Debug/args.gn'],
+ 'import("//build/args/bots/fake_master/fake_gn_args_bot.gn")\n')
def test_gn_gen_fails(self):
@@ -388,9 +412,13 @@ class UnitTest(unittest.TestCase):
def test_gn_lookup_goma_dir_expansion(self):
self.check(['lookup', '-c', 'gn_rel_bot', '-g', '/foo'], ret=0,
- out=("/fake_src/buildtools/linux64/gn gen _path_ "
- "'--args=is_debug=false use_goma=true "
- "goma_dir=\"/foo\"'\n" ))
+ out=('\n'
+ 'Writing """\\\n'
+ 'goma_dir = "/foo"\n'
+ 'is_debug = false\n'
+ 'use_goma = true\n'
+ '""" to _path_/args.gn.\n\n'
+ '/fake_src/buildtools/linux64/gn gen _path_\n'))
def test_gyp_analyze(self):
mbw = self.check(['analyze', '-c', 'gyp_rel_bot', '//out/Release',
@@ -437,7 +465,6 @@ class UnitTest(unittest.TestCase):
def test_validate(self):
mbw = self.fake_mbw()
- mbw.files[mbw.default_config] = TEST_CONFIG
self.check(['validate'], mbw=mbw, ret=0)
def test_bad_validate(self):
diff --git a/chromium/tools/md_browser/md_browser.py b/chromium/tools/md_browser/md_browser.py
index 2b968525320..f2e05f9308d 100644..100755
--- a/chromium/tools/md_browser/md_browser.py
+++ b/chromium/tools/md_browser/md_browser.py
@@ -1,3 +1,4 @@
+#!/usr/bin/env python
# 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.
@@ -25,12 +26,16 @@ def main(argv):
parser = argparse.ArgumentParser(prog='md_browser')
parser.add_argument('-p', '--port', type=int, default=8080,
help='port to run on (default = %(default)s)')
+ parser.add_argument('-d', '--directory', type=str, default=SRC_DIR)
args = parser.parse_args(argv)
try:
- s = Server(args.port, SRC_DIR)
+ s = Server(args.port, args.directory)
print("Listening on http://localhost:%s/" % args.port)
- print(" Try loading http://localhost:%s/docs/README.md" % args.port)
+ if os.path.isfile(os.path.join(args.directory, 'docs', 'README.md')):
+ print(" Try loading http://localhost:%s/docs/README.md" % args.port)
+ elif os.path.isfile(os.path.join(args.directory, 'README.md')):
+ print(" Try loading http://localhost:%s/README.md" % args.port)
s.serve_forever()
s.shutdown()
return 0
@@ -71,7 +76,7 @@ class Server(SocketServer.TCPServer):
def __init__(self, port, top_level):
SocketServer.TCPServer.__init__(self, ('0.0.0.0', port), Handler)
self.port = port
- self.top_level = top_level
+ self.top_level = os.path.abspath(top_level)
def server_bind(self):
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
@@ -89,7 +94,7 @@ class Handler(SimpleHTTPServer.SimpleHTTPRequestHandler):
full_path = os.path.abspath(os.path.join(self.server.top_level, path[1:]))
- if not full_path.startswith(SRC_DIR):
+ if not full_path.startswith(self.server.top_level):
self._DoUnknown()
elif path == '/doc.css':
self._DoCSS('doc.css')
@@ -142,9 +147,11 @@ class Handler(SimpleHTTPServer.SimpleHTTPRequestHandler):
self.wfile.write('<html><body>I do not know how to serve %s.</body>'
'</html>' % self.path)
- def _Read(self, relpath):
+ def _Read(self, relpath, relative_to=None):
+ if relative_to is None:
+ relative_to = self.server.top_level
assert not relpath.startswith(os.sep)
- path = os.path.join(self.server.top_level, relpath)
+ path = os.path.join(relative_to, relpath)
with codecs.open(path, encoding='utf-8') as fp:
return fp.read()
@@ -154,7 +161,8 @@ class Handler(SimpleHTTPServer.SimpleHTTPRequestHandler):
self.end_headers()
def _WriteTemplate(self, template):
- contents = self._Read(os.path.join('tools', 'md_browser', template))
+ contents = self._Read(os.path.join('tools', 'md_browser', template),
+ relative_to=SRC_DIR)
self.wfile.write(contents.encode('utf-8'))
diff --git a/chromium/tools/origin_trials/OWNERS b/chromium/tools/origin_trials/OWNERS
index d9278608565..0d67a41a799 100644
--- a/chromium/tools/origin_trials/OWNERS
+++ b/chromium/tools/origin_trials/OWNERS
@@ -1,3 +1 @@
-dhnishi@chromium.org
-iclelland@chromium.org
-mek@chromium.org
+file://content/common/origin_trials/OWNERS
diff --git a/chromium/tools/origin_trials/eftest.key b/chromium/tools/origin_trials/eftest.key
index 10015d89550..3a7a7a91955 100644
--- a/chromium/tools/origin_trials/eftest.key
+++ b/chromium/tools/origin_trials/eftest.key
@@ -1 +1 @@
-ƒgôÍ*
+g* CLg(ɐv,Ku:(pҚ Y+dV: \ No newline at end of file
diff --git a/chromium/tools/polymer/generate_compiled_resources_gyp.py b/chromium/tools/polymer/generate_compiled_resources_gyp.py
index 38f81578ab4..d825b171a6f 100755
--- a/chromium/tools/polymer/generate_compiled_resources_gyp.py
+++ b/chromium/tools/polymer/generate_compiled_resources_gyp.py
@@ -32,7 +32,11 @@ _COMPILED_RESOURCES_TEMPLATE = """
def main(created_by, html_files):
targets = ""
- for html_file in html_files:
+ def _target_name(target_file):
+ assert target_file.endswith(".html")
+ return path.basename(target_file)[:-len(".html")] + "-extracted"
+
+ for html_file in sorted(html_files, key=_target_name):
html_base = path.basename(html_file)
if html_base in _POLYMERS:
continue
@@ -52,7 +56,7 @@ def main(created_by, html_files):
dependencies.append(_WEB_ANIMATIONS_TARGET)
continue
- target = import_base[:-5] + "-extracted"
+ target = _target_name(import_base)
if not path.isfile(path.join(html_dir, import_dir, target + ".js")):
continue
diff --git a/chromium/tools/roll_angle.py b/chromium/tools/roll_angle.py
index 6432cc4a093..2b253ee56ee 100755
--- a/chromium/tools/roll_angle.py
+++ b/chromium/tools/roll_angle.py
@@ -102,7 +102,7 @@ def _GenerateCLDescriptionCommand(angle_current, angle_new, bugs, tbr):
def GetBugString(bugs):
bug_str = 'BUG='
for bug in bugs:
- bug_str += str(bug) + ','
+ bug_str += bug + ','
return bug_str.rstrip(',')
if angle_current.git_commit != angle_new.git_commit:
@@ -219,6 +219,7 @@ class AutoRoller(object):
['git','log',
'%s..%s' % (angle_current.git_commit, angle_new.git_commit)],
working_dir=working_dir).split('\n')
+ ignored_projects = set(['angleproject'])
bugs = set()
for line in lines:
line = line.strip()
@@ -226,12 +227,13 @@ class AutoRoller(object):
if line.startswith(bug_prefix):
bugs_strings = line[len(bug_prefix):].split(',')
for bug_string in bugs_strings:
- try:
- bugs.add(int(bug_string))
- except:
- # skip this, it may be a project specific bug such as
- # "angleproject:X" or an ill-formed BUG= message
- pass
+ ignore_bug = False
+ for ignored_project in ignored_projects:
+ if bug_string.startswith(ignored_project + ':'):
+ ignore_bug = True
+ break
+ if not ignore_bug:
+ bugs.add(bug_string)
return bugs
def _UpdateReadmeFile(self, readme_path, new_revision):
diff --git a/chromium/tools/roll_webgl_conformance.py b/chromium/tools/roll_webgl_conformance.py
index 7ea056f1f50..4c9eb73d641 100755
--- a/chromium/tools/roll_webgl_conformance.py
+++ b/chromium/tools/roll_webgl_conformance.py
@@ -20,7 +20,11 @@ extra_trybots = [
{
"mastername": "tryserver.chromium.mac",
"buildernames": ["mac_optional_gpu_tests_rel"]
- }
+ },
+ {
+ "mastername": "tryserver.chromium.linux",
+ "buildernames": ["linux_optional_gpu_tests_rel"]
+ },
]
SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__))
@@ -229,7 +233,7 @@ class AutoRoller(object):
readme.write(m)
readme.truncate()
- def PrepareRoll(self, ignore_checks, skip_tryjobs):
+ def PrepareRoll(self, ignore_checks, run_tryjobs):
# TODO(kjellander): use os.path.normcase, os.path.join etc for all paths for
# cross platform compatibility.
@@ -280,7 +284,7 @@ class AutoRoller(object):
self._RunCommand(['git', 'cl', 'upload'],
extra_env={'EDITOR': 'true'})
- if not skip_tryjobs:
+ if run_tryjobs:
# Kick off tryjobs.
base_try_cmd = ['git', 'cl', 'try']
self._RunCommand(base_try_cmd)
@@ -365,11 +369,10 @@ def main():
help=('Skips checks for being on the master branch, dirty workspaces and '
'the updating of the checkout. Will still delete and create local '
'Git branches.'))
- parser.add_argument('--skip-tryjobs', action='store_true', default=False,
- help=('Skip the dry-run tryjobs for the newly generated CL. Use this '
- 'when you expect to have to make many changes to the WebGL '
- 'conformance test expectations in the same CL and want to avoid '
- 'wasted tryjobs.'))
+ parser.add_argument('--run-tryjobs', action='store_true', default=False,
+ help=('Start the dry-run tryjobs for the newly generated CL. Use this '
+ 'when you have no need to make changes to the WebGL conformance '
+ 'test expectations in the same CL and want to avoid.'))
parser.add_argument('-v', '--verbose', action='store_true', default=False,
help='Be extra verbose in printing of log messages.')
args = parser.parse_args()
@@ -383,7 +386,7 @@ def main():
if args.abort:
return autoroller.Abort()
else:
- return autoroller.PrepareRoll(args.ignore_checks, args.skip_tryjobs)
+ return autoroller.PrepareRoll(args.ignore_checks, args.run_tryjobs)
if __name__ == '__main__':
sys.exit(main())
diff --git a/chromium/tools/roll_webrtc.py b/chromium/tools/roll_webrtc.py
index f016fb39c15..4291c3820f5 100755
--- a/chromium/tools/roll_webrtc.py
+++ b/chromium/tools/roll_webrtc.py
@@ -36,8 +36,9 @@ TRYJOB_STATUS_SLEEP_SECONDS = 30
# Use a shell for subcommands on Windows to get a PATH search.
IS_WIN = sys.platform.startswith('win')
WEBRTC_PATH = os.path.join('third_party', 'webrtc')
-LIBJINGLE_PATH = os.path.join('third_party', 'libjingle', 'source', 'talk')
-LIBJINGLE_README = os.path.join('third_party', 'libjingle', 'README.chromium')
+# Run these CQ trybots in addition to the default ones in infra/config/cq.cfg.
+EXTRA_TRYBOTS = ('tryserver.chromium.linux:linux_chromium_archive_rel_ng;'
+ 'tryserver.chromium.mac:mac_chromium_archive_rel_ng')
# Result codes from build/third_party/buildbot_8_4p1/buildbot/status/results.py
# plus the -1 code which is used when there's no result yet.
@@ -152,38 +153,20 @@ def _PrintTrybotsStatus(tryjob_results):
print '%s: %s' % (status, ','.join(sorted(name_list)))
-def _GenerateCLDescriptionCommand(webrtc_current, libjingle_current,
- webrtc_new, libjingle_new):
- delim = ''
- webrtc_str = ''
+def _GenerateCLDescriptionCommand(webrtc_current, webrtc_new):
def GetChangeLogURL(git_repo_url, current_hash, new_hash):
return '%s/+log/%s..%s' % (git_repo_url, current_hash[0:7], new_hash[0:7])
- if webrtc_current.git_commit != webrtc_new.git_commit:
- webrtc_str = 'WebRTC %s:%s' % (webrtc_current.commit_position,
- webrtc_new.commit_position)
- webrtc_changelog_url = GetChangeLogURL(webrtc_current.git_repo_url,
- webrtc_current.git_commit,
- webrtc_new.git_commit)
-
- libjingle_str = ''
- if libjingle_current.git_commit != libjingle_new.git_commit:
- if webrtc_str:
- delim += ', '
- libjingle_str = 'Libjingle %s:%s' % (libjingle_current.commit_position,
- libjingle_new.commit_position)
- libjingle_changelog_url = GetChangeLogURL(libjingle_current.git_repo_url,
- libjingle_current.git_commit,
- libjingle_new.git_commit)
-
- description = [ '-m', 'Roll ' + webrtc_str + delim + libjingle_str ]
- if webrtc_str:
- description.extend(['-m', webrtc_str])
- description.extend(['-m', 'Changes: %s' % webrtc_changelog_url])
- if libjingle_str:
- description.extend(['-m', libjingle_str])
- description.extend(['-m', 'Changes: %s' % libjingle_changelog_url])
+ webrtc_str = 'WebRTC %s:%s' % (webrtc_current.commit_position,
+ webrtc_new.commit_position)
+ webrtc_changelog_url = GetChangeLogURL(webrtc_current.git_repo_url,
+ webrtc_current.git_commit,
+ webrtc_new.git_commit)
+
+ description = [ '-m', 'Roll ' + webrtc_str ]
+ description.extend(['-m', 'Changes: %s' % webrtc_changelog_url])
description.extend(['-m', 'TBR='])
+ description.extend(['-m', 'CQ_EXTRA_TRYBOTS=%s' % EXTRA_TRYBOTS])
return description
@@ -299,26 +282,22 @@ class AutoRoller(object):
deps_filename = os.path.join(self._chromium_src, 'DEPS')
deps = _ParseDepsFile(deps_filename)
webrtc_current = self._GetDepsCommitInfo(deps, WEBRTC_PATH)
- libjingle_current = self._GetDepsCommitInfo(deps, LIBJINGLE_PATH)
# Find ToT revisions.
webrtc_latest = self._GetCommitInfo(WEBRTC_PATH)
- libjingle_latest = self._GetCommitInfo(LIBJINGLE_PATH)
if IS_WIN:
# Make sure the roll script doesn't use Windows line endings.
self._RunCommand(['git', 'config', 'core.autocrlf', 'true'])
self._UpdateDep(deps_filename, WEBRTC_PATH, webrtc_latest)
- self._UpdateDep(deps_filename, LIBJINGLE_PATH, libjingle_latest)
if self._IsTreeClean():
- print 'The latest revision is already rolled for WebRTC and libjingle.'
+ print 'The latest revision is already rolled for WebRTC.'
self._DeleteRollBranch()
else:
- self._UpdateReadmeFile(LIBJINGLE_README, libjingle_latest.commit_position)
description = _GenerateCLDescriptionCommand(
- webrtc_current, libjingle_current, webrtc_latest, libjingle_latest)
+ webrtc_current, webrtc_latest)
logging.debug('Committing changes locally.')
self._RunCommand(['git', 'add', '--update', '.'])
self._RunCommand(['git', 'commit'] + description)
@@ -397,7 +376,7 @@ class AutoRoller(object):
def main():
parser = argparse.ArgumentParser(
- description='Find webrtc and libjingle revisions for roll.')
+ description='Find webrtc revisions for roll.')
parser.add_argument('--abort',
help=('Aborts a previously prepared roll. '
'Closes any associated issues and deletes the roll branches'),
diff --git a/chromium/tools/valgrind/chrome_tests.py b/chromium/tools/valgrind/chrome_tests.py
index e108384f1b1..57df8bbd4be 100755
--- a/chromium/tools/valgrind/chrome_tests.py
+++ b/chromium/tools/valgrind/chrome_tests.py
@@ -322,7 +322,9 @@ class ChromeTests:
return self.SimpleTest("chrome", "cast_unittests")
def TestCC(self):
- return self.SimpleTest("cc", "cc_unittests")
+ return self.SimpleTest("cc", "cc_unittests",
+ cmd_args=[
+ "--cc-layer-tree-test-long-timeout"])
def TestChromeApp(self):
return self.SimpleTest("chrome_app", "chrome_app_unittests")
diff --git a/chromium/tools/valgrind/drmemory/suppressions.txt b/chromium/tools/valgrind/drmemory/suppressions.txt
index 36f69910dae..bb77522a41f 100644
--- a/chromium/tools/valgrind/drmemory/suppressions.txt
+++ b/chromium/tools/valgrind/drmemory/suppressions.txt
@@ -487,27 +487,6 @@ NPCTRL.dll!DllGetClassObject
NPCTRL.dll!DllGetClassObject
HANDLE LEAK
-name=http://crbug.com/373333
-system call NtGdiCreateCompatibleDC
-*!CreateCompatibleDC
-*!SkScalerContext_GDI::SkScalerContext_GDI
-*!LogFontTypeface::onCreateScalerContext
-*!SkTypeface::createScalerContext
-*!SkGlyphCache::VisitCache
-...
-*!SkPaint::descriptorProc
-...
-*!blink::RenderBlockFlow::layoutBlockFlow
-*!blink::RenderBlockFlow::layoutBlock
-*!blink::RenderBlock::layout
-
-HANDLE LEAK
-name=https://github.com/DynamoRIO/drmemory/issues/1545
-system call NtGdiCreateCompatibleDC
-GDI32.dll!CreateCompatibleDC
-skia.dll!LogFontTypeface::onGetTableData
-
-HANDLE LEAK
name=http://crbug.com/379000
system call NtCreate*
...
@@ -810,3 +789,22 @@ ipc.dll!IPC::internal::ChannelReader::HandleTranslatedMessage
ipc.dll!IPC::internal::ChannelReader::TranslateInputData
ipc.dll!IPC::internal::ChannelReader::AsyncReadComplete
ipc.dll!IPC::ChannelWin::OnIOCompleted
+
+UNADDRESSABLE ACCESS
+name=bug_604078
+content.dll!content::BluetoothBlacklist::PopulateWithServerProvidedValues
+content.dll!content::BluetoothBlacklist::BluetoothBlacklist
+content.dll!content::BluetoothBlacklist::Get
+
+
+UNINITIALIZED READ
+name=bug_608111
+DWrite.dll!DWriteCreateFactory
+skia.dll!SkDWriteFontFileStreamWrapper::GetFileSize
+...
+blink_platform.dll!blink::SimpleFontData::platformWidthForGlyph
+
+UNADDRESSABLE ACCESS
+name=bug_608064
+*!ExtensionService::NotifyExtensionLoaded
+*!ExtensionService::AddExtension
diff --git a/chromium/tools/valgrind/drmemory/suppressions_full.txt b/chromium/tools/valgrind/drmemory/suppressions_full.txt
index a03efb6cb78..97b85cc140f 100644
--- a/chromium/tools/valgrind/drmemory/suppressions_full.txt
+++ b/chromium/tools/valgrind/drmemory/suppressions_full.txt
@@ -1350,23 +1350,6 @@ name=http://crbug.com/57266 (2)
*!vp8_*
LEAK
-name=http://crbug.com/70062
-*!PR_Calloc
-*!PR_NewLock
-...
-*!InitSessionCacheLocks
-*!initSessionCacheLocksLazily
-*!PR_CallOnce
-*!ssl_InitSessionCacheLocks
-*!lock_cache
-*!ssl_LookupSID
-*!ssl2_BeginClientHandshake
-*!ssl_Do1stHandshake
-*!SSL_ForceHandshake
-*!net::SSL*SocketNSS::DoHandshake
-*!net::SSL*SocketNSS::DoHandshakeLoop
-
-LEAK
name=http://crbug.com/74417 a
*!replace_operator_new
*!disk_cache::BackendImpl::CreateEntryImpl
@@ -1407,13 +1390,6 @@ name=http://crbug.com/80550 (2)
*!RenderWidgetHost::WasRestored
LEAK
-name=http://crbug.com/87612
-...
-*!SSL_ConfigSecureServer
-*!net::SSLServerSocketNSS::InitializeSSLOptions
-*!net::SSLServerSocketNSS::Handshake
-
-LEAK
name=http://crbug.com/88640
*!generic_cpp_alloc
*!operator new
@@ -1520,19 +1496,6 @@ UNINITIALIZED READ
name=bug_343663
blink_web.dll!blink::RenderBlock::computeInlinePreferredLogicalWidths
-UNINITIALIZED READ
-name=bug_343797
-...
-blink_web.dll!blink::MediaQueryExp::create
-blink_web.dll!blink::BisonCSSParser::createFloatingMediaQueryExp
-blink_web.dll!cssyyparse
-
-UNINITIALIZED READ
-name=bug_343915
-blink_web.dll!blink::BisonCSSParser::parseFlex
-blink_web.dll!blink::BisonCSSParser::parseValue
-blink_web.dll!cssyyparse
-
UNADDRESSABLE ACCESS
name=BUG_343958
blink_web.dll!blink::Node::getFlag
@@ -1605,13 +1568,6 @@ skia.dll!SkCanvas::drawBitmap
content.dll!content::ScreenshotData::EncodeOnWorker
UNINITIALIZED READ
-name=bug_363487
-blink_web.dll!blink::RenderLayerCompositor::updateIfNeeded
-blink_web.dll!blink::RenderLayerCompositor::updateIfNeededRecursive
-blink_web.dll!blink::FrameView::updateLayoutAndStyleForPainting
-blink_web.dll!blink::PageAnimator::updateLayoutAndStyleForPainting
-
-UNINITIALIZED READ
name=bug_365101
*!device::BluetoothAdapterWin::AdapterStateChanged
@@ -1635,13 +1591,6 @@ name=bug_42043
...
QuickTime.qts!*
-UNINITIALIZED READ
-name=bug_369141
-...
-*!blink::RenderLayerClipper::updateClipRects
-*!blink::RenderLayerClipper::parentClipRects
-*!blink::RenderLayerClipper::backgroundClipRect
-
HANDLE LEAK
name=bug_370178
system call NtCreateEvent
@@ -1831,8 +1780,8 @@ KERNELBASE.dll!DuplicateHandle
KERNEL32.dll!DuplicateHandle
base.dll!base::SharedMemory::ShareToProcessCommon
gl_wrapper.dll!gl::GLImageSharedMemory::Initialize
-content.dll!content::GpuChannel::CreateImageForGpuMemoryBuffer
-content.dll!content::GpuCommandBufferStub::OnCreateImage
+*!*::GpuChannel::CreateImageForGpuMemoryBuffer
+*!*::GpuCommandBufferStub::OnCreateImage
HANDLE LEAK
name=https://crbug.com/481305
@@ -1858,26 +1807,6 @@ aura.dll!aura::WindowTreeHostPlatform::WindowTreeHostPlatform
aura.dll!aura::WindowTreeHost::Create
UNINITIALIZED READ
-name=bug_492821
-*!blink::CSSPropertyParser::validUnit
-...
-*!blink::CSSPropertyParser::parseValue
-*!blink::CSSPropertyParser::parseValue
-*!blink::CSSParserImpl::consumeDeclarationValue
-*!blink::CSSParserImpl::consumeDeclaration
-*!blink::CSSParserImpl::consumeDeclarationList
-*!blink::CSSParserImpl::consumeStyleRule
-*!blink::CSSParserImpl::consumeQualifiedRule
-*!blink::CSSParserImpl::consumeRuleList<>
-*!blink::CSSParserImpl::parseStyleSheet
-*!blink::CSSParser::parseSheet
-*!blink::StyleSheetContents::parseStringAtPosition
-*!blink::StyleEngine::parseSheet
-*!blink::StyleEngine::createSheet
-*!blink::StyleElement::createSheet
-*!blink::StyleElement::process
-
-UNINITIALIZED READ
name=bug_493167
system call NtWriteFile parameter #5
KERNELBASE.dll!WriteFile
@@ -2121,17 +2050,6 @@ content.dll!content::PepperGraphics2DHost::Create
content.dll!content::ContentRendererPepperHostFactory::CreateResourceHost
UNINITIALIZED READ
-name=bug_591092
-webcore_shared.dll!std::_Equal<>
-webcore_shared.dll!WTF::operator==<>
-webcore_shared.dll!blink::CSSVariableData::operator==
-webcore_shared.dll!blink::dataEquivalent<>
-webcore_shared.dll!blink::dataEquivalent<>
-...
-webcore_shared.dll!blink::Document::updateStyle
-webcore_shared.dll!blink::Document::updateLayoutTree
-
-UNINITIALIZED READ
name=bug_593594
blink_platform.dll!qcms_transform_data_rgba_out_lut_sse2
blink_platform.dll!qcms_transform_data_type
diff --git a/chromium/tools/valgrind/gtest_exclude/base_unittests.gtest.txt b/chromium/tools/valgrind/gtest_exclude/base_unittests.gtest.txt
index 989459dcb55..c98265df11c 100644
--- a/chromium/tools/valgrind/gtest_exclude/base_unittests.gtest.txt
+++ b/chromium/tools/valgrind/gtest_exclude/base_unittests.gtest.txt
@@ -7,10 +7,6 @@ WatchdogTest.AlarmTest
TimerTest.RepeatingTimer
TimerTest.RepeatingTimer_Cancel
-# Crashes occasionally, see http://crbug.com/7477
-base::ObserverListThreadSafeTest.CrossThreadObserver
-base::ObserverListThreadSafeTest.CrossThreadNotifications
-
# Hangs sometimes on linux, see http://crbug.com/22138
ClipboardTest.*
diff --git a/chromium/tools/valgrind/gtest_exclude/browser_tests.gtest-drmemory.txt b/chromium/tools/valgrind/gtest_exclude/browser_tests.gtest-drmemory.txt
index 80514c28ab2..3166fdcc4fe 100644
--- a/chromium/tools/valgrind/gtest_exclude/browser_tests.gtest-drmemory.txt
+++ b/chromium/tools/valgrind/gtest_exclude/browser_tests.gtest-drmemory.txt
@@ -58,9 +58,6 @@ SmartSessionRestoreTest.CorrectLoadingOrder
# https://crbug.com/516368
PushMessagingBrowserTest.PushEventSuccess
-# https://crbug.com/519039
-AppViewTest.KillGuestCommunicatingWithWrongAppView
-
# https://crbug.com/519087
ExtensionTabsTest.GetAllWindowsAllTypes
@@ -144,6 +141,7 @@ HostedAppTest*
ImageWriterPrivateApiTest.TestWriteFromFile
InlineInstallPrivateApiTestApp*
InstallGoodExtensionSettingsWebUITest.showOptions
+ManageProfileUITestAsync.CreateExistingSupervisedUser
MaterialHistoryBrowserTest*
MimeHandlerViewTest.Abort
MimeHandlerViewTest.EmbeddedDataUrlObject
@@ -151,9 +149,15 @@ MultilanguageOptionsWebUI*
PDFExtensionTest*
PasswordsPrivateApiTest.RequestPlaintextPassword
PolicyPref*
+PredictorBrowserTest*
ProfileWindow*
PushMessagingBrowserTest.SubscribeWithoutKeySuccessNotificationsGranted
SubframeTaskBrowserTest.TaskManagerShowsSubframeTasks
SyncSetupWebUITestAsync.RestoreSyncDataTypes
+WebRtcDisableEncryptionFlagBrowserTest.VerifyEncryption
WebUIWebView*
+WebrtcEventLogApiTest*
ZoomControllerBrowserTest.NavigationResetsManualMode
+
+# https://crbug.com/603334
+AppViewTests/AppViewTest.KillGuestCommunicatingWithWrongAppView/*
diff --git a/chromium/tools/valgrind/gtest_exclude/cc_unittests.gtest-drmemory_win32.txt b/chromium/tools/valgrind/gtest_exclude/cc_unittests.gtest-drmemory_win32.txt
index 563f0c76243..66cf2c53f6c 100644
--- a/chromium/tools/valgrind/gtest_exclude/cc_unittests.gtest-drmemory_win32.txt
+++ b/chromium/tools/valgrind/gtest_exclude/cc_unittests.gtest-drmemory_win32.txt
@@ -43,6 +43,7 @@ LayerTreeHostTestBeginMainFrameTimeIsAlsoImplTime.RunMultiThread_DirectRenderer
LayerTreeHostCopyRequestCompletionCausesCommit.RunMultiThread_DirectRenderer
LayerTreeHostCopyRequestTestLostOutputSurface.RunMultiThread_DirectRenderer
LayerTreeHostTestStartPageScaleAnimation.RunMultiThread_DelegatingRenderer
+LayerTreeHostTestStartPageScaleAnimation.RunMultiThread_DirectRenderer
# https://crbug.com/571268
LayerTreeHostTestGpuRasterDeviceSizeChanged.*
diff --git a/chromium/tools/valgrind/gtest_exclude/components_unittests.gtest.txt b/chromium/tools/valgrind/gtest_exclude/components_unittests.gtest.txt
index 9289e21187b..ecc05cfbadb 100644
--- a/chromium/tools/valgrind/gtest_exclude/components_unittests.gtest.txt
+++ b/chromium/tools/valgrind/gtest_exclude/components_unittests.gtest.txt
@@ -6,6 +6,3 @@ AudioDirectiveListTest.*
# http://crbug.com/523462
PluginsFieldTrialTest.NoPrefLeftBehind
-
-# Fails under valgrind Linux, see http://crbug.com/587664
-DataReductionProxyConfigServiceClientTest.HTTPRequests
diff --git a/chromium/tools/valgrind/gtest_exclude/content_browsertests.gtest-drmemory.txt b/chromium/tools/valgrind/gtest_exclude/content_browsertests.gtest-drmemory.txt
index 676da4d82b3..53187ebcd99 100644
--- a/chromium/tools/valgrind/gtest_exclude/content_browsertests.gtest-drmemory.txt
+++ b/chromium/tools/valgrind/gtest_exclude/content_browsertests.gtest-drmemory.txt
@@ -64,3 +64,17 @@ WebRtcMediaRecorderTest.MediaRecorderPeerConnection
# https://crbug.com/592320
SitePerProcessBrowserTest.SubframeGestureEventRouting
+
+# https://crbug.com/603337
+SingleProcessMemoryTracingTest.ManyInterleavedDumps
+SingleProcessMemoryTracingTest.RendererInitiatedSingleDump
+
+# https://crbug.com/608081
+SitePerProcessBrowserTest.NavigateRemoteFrameToBlankAndDataURLs
+SitePerProcessBrowserTest.RFPHDestruction
+
+# https://crbug.com/608117
+WebRtcDataChannelTest.DataChannelGC
+
+# https://crbug.com/611557
+FindRequestManagerTest.RapidFire
diff --git a/chromium/tools/valgrind/gtest_exclude/content_unittests.gtest-drmemory_win32.txt b/chromium/tools/valgrind/gtest_exclude/content_unittests.gtest-drmemory_win32.txt
index 4cc5686e176..f12d3ced4dd 100644
--- a/chromium/tools/valgrind/gtest_exclude/content_unittests.gtest-drmemory_win32.txt
+++ b/chromium/tools/valgrind/gtest_exclude/content_unittests.gtest-drmemory_win32.txt
@@ -11,3 +11,6 @@ RenderWidgetCompositorOutputSurfaceTest.FallbackSuccessNormalSuccess
# http://crbug.com/554665
WebContentsVideoCaptureDeviceTest.VariableResolution_AnyWithinLimits
WebContentsVideoCaptureDeviceTest.VariableResolution_FixedAspectRatio
+
+# https://crbug.com/604056
+CodecProfiles/RTCVideoDecoderTest.GetVDAErrorCounterForTesting*
diff --git a/chromium/tools/valgrind/gtest_exclude/net_unittests.gtest-drmemory_win32.txt b/chromium/tools/valgrind/gtest_exclude/net_unittests.gtest-drmemory_win32.txt
index c865baf0e4f..8388d668f14 100644
--- a/chromium/tools/valgrind/gtest_exclude/net_unittests.gtest-drmemory_win32.txt
+++ b/chromium/tools/valgrind/gtest_exclude/net_unittests.gtest-drmemory_win32.txt
@@ -34,3 +34,9 @@ ProxyResolverV8TracingWrapperTest.*
# https://crbug.com/598953
*QuicConnectionTest.TooManyReceivedPackets*
+
+# https://crbug.com/604611
+BidirectionalStreamTest.*
+
+# https://crbug.com/611533
+*HttpStreamFactoryBidirectionalQuicTest.RequestBidirectionalStreamImpl*
diff --git a/chromium/tools/valgrind/gtest_exclude/remoting_unittests.gtest-drmemory_win32.txt b/chromium/tools/valgrind/gtest_exclude/remoting_unittests.gtest-drmemory_win32.txt
index 276d6acb4d8..038c5ef41ec 100644
--- a/chromium/tools/valgrind/gtest_exclude/remoting_unittests.gtest-drmemory_win32.txt
+++ b/chromium/tools/valgrind/gtest_exclude/remoting_unittests.gtest-drmemory_win32.txt
@@ -13,6 +13,3 @@ RdpClientTest.Basic
# https://crbug.com/581519
Webrtc/ConnectionTest.Video/0
-
-# https://crbug.com/599769
-RemoteSecurityKeyMessageReaderTest.MultipleMessages
diff --git a/chromium/tools/valgrind/gtest_exclude/unit_tests.gtest-drmemory_win32.txt b/chromium/tools/valgrind/gtest_exclude/unit_tests.gtest-drmemory_win32.txt
index 06fd527ed91..673468a845e 100644
--- a/chromium/tools/valgrind/gtest_exclude/unit_tests.gtest-drmemory_win32.txt
+++ b/chromium/tools/valgrind/gtest_exclude/unit_tests.gtest-drmemory_win32.txt
@@ -84,3 +84,6 @@ SigninErrorNotifierTest.NoErrorAuthStatusProviders
# https://crbug.com/577410
PluginInfoMessageFilterTest.FindEnabledPlugin
+
+# https://crbug.com/612590
+NativeDesktopMediaListTest.UpdateThumbnail
diff --git a/chromium/tools/valgrind/memcheck/suppressions.txt b/chromium/tools/valgrind/memcheck/suppressions.txt
index 9d5b4ad330d..d844892a633 100644
--- a/chromium/tools/valgrind/memcheck/suppressions.txt
+++ b/chromium/tools/valgrind/memcheck/suppressions.txt
@@ -625,17 +625,6 @@
fun:_ZN4base6Thread10ThreadMainEv
}
{
- # also bug 17979. It's a nest of leaks.
- bug_17385
- Memcheck:Leak
- fun:_Znw*
- ...
- fun:_ZN3IPC12ChannelProxy7Context13CreateChannel*Channel4ModeE
- fun:_ZN3IPC12ChannelProxy4Init*
- ...
- fun:_ZN3IPC11SyncChannel*Channel4Mode*Listener*
-}
-{
bug_17540_16661
Memcheck:Leak
fun:_Znw*
@@ -929,21 +918,11 @@
fun:_ZN14GpuProcessHost4InitEv
}
{
- bug_67261a
- Memcheck:Leak
- fun:_Znw*
- ...
- fun:_ZN3sql10Connection18GetUniqueStatementEPKc
- fun:_ZN3sql10Connection18GetCachedStatementERKNS_11StatementIDEPKc
- fun:_ZN8appcache16AppCacheDatabase22PrepareCachedStatementERKN3sql11StatementIDEPKcPNS1_9StatementE
-}
-{
bug_67261b
Memcheck:Leak
fun:_Znw*
fun:_ZN3sql10Connection18GetUniqueStatementEPKc
fun:_ZN3sql10Connection18GetCachedStatementERKNS_11StatementIDEPKc
- fun:_ZN3sql9MetaTable19PrepareGetStatementEPNS_9StatementEPKc
...
fun:_ZN7storage13QuotaDatabase28IsOriginDatabaseBootstrappedEv
}
@@ -1211,15 +1190,6 @@
obj:*
}
{
- bug_100982
- Memcheck:Leak
- fun:_Znw*
- fun:_ZN5blink12RenderRegion22setRenderBoxRegionInfoEPKNS_9RenderBoxEiib
- fun:_ZNK7blink9RenderBox19renderBoxRegionInfoEPNS_12RenderRegionEiNS0_24RenderBoxRegionInfoFlagsE
- ...
- fun:_ZN5blink11RenderBlock5paintERNS_9PaintInfoERKNS_8IntPointE
-}
-{
bug_101750
Memcheck:Leak
fun:malloc
@@ -2011,24 +1981,13 @@
fun:_ZN5blink24DocumentThreadableLoader11loadRequestERKNS_15ResourceRequestENS_19SecurityCheckPolicyE
}
{
- bug_340952
- Memcheck:Leak
- fun:_Znw*
- fun:_ZN5blink15DOMWrapperWorldC2Eii
- fun:_ZN5blink15DOMWrapperWorldC1Eii
- fun:_ZN5blink15DOMWrapperWorld6createEii
- fun:_ZN5blink15DOMWrapperWorld9mainWorldEv
- ...
- fun:_ZN7content22BufferedDataSourceTestC2Ev
-}
-{
bug_340752
Memcheck:Uninitialized
...
- fun:_ZN5blink4Heap19checkAndMarkPointerEPNS_7VisitorEPh
+ fun:_ZN5blink10ThreadHeap19checkAndMarkPointerEPNS_7VisitorEPh
fun:_ZN5blink11ThreadState10visitStackEPNS_7VisitorE
...
- fun:_ZN5blink4Heap14collectGarbageENS_7BlinkGC10StackState*
+ fun:_ZN5blink10ThreadHeap14collectGarbageENS_7BlinkGC10StackState*
}
{
bug_342591
@@ -2233,19 +2192,6 @@
fun:_ZN7content28ShellURLRequestContextGetter20GetURLRequestContextEv
}
{
- bug_381065
- Memcheck:Leak
- fun:_Znw*
- ...
- fun:_ZN5blink18ModulesInitializer4initEv
- fun:_ZN5blink19initializeWithoutV8EPNS_8PlatformE
- fun:_ZN5blink10initializeEPNS_8PlatformE
- fun:_ZN7content27TestBlinkWebUnitTestSupportC2Ev
- fun:_ZN7content27TestBlinkWebUnitTestSupportC1Ev
- fun:_ZN7content17UnitTestTestSuiteC2EPN4base9TestSuiteE
- fun:_ZN7content17UnitTestTestSuiteC1EPN4base9TestSuiteE
-}
-{
bug_385381
Memcheck:Unaddressable
fun:_ZN5blink23FrameLoaderStateMachine9advanceToENS0_5StateE
@@ -2474,20 +2420,6 @@
fun:_ZN2v88internal27Runtime_CreateObjectLiteralEiPPNS0_6ObjectEPNS0_7IsolateE
}
{
- bug_399853_a
- Memcheck:Uninitialized
- fun:_ZNK8SkStroke10strokePathERK6SkPathPS0_
- fun:_ZNK11SkStrokeRec11applyToPathEP6SkPathRKS0_
- fun:_ZNK7SkPaint11getFillPathERK6SkPathPS0_PK6SkRect
-}
-{
- bug_399853_b
- Memcheck:Uninitialized
- fun:_ZNK8SkStroke10strokePathERK6SkPathPS0_
- fun:_ZNK11SkStrokeRec11applyToPathEP6SkPathRKS0_
- fun:_ZN15SkScalerContext15internalGetPathERK7SkGlyphP6SkPathS4_P8SkMatrix
-}
-{
bug_417119
Memcheck:Leak
fun:_Znw*
@@ -2714,16 +2646,6 @@
fun:_ZN7content26ResourceDispatcherHostImpl23OnRenderViewHostCreatedEiibb
}
{
- bug_492821
- Memcheck:Uninitialized
- fun:_ZN5blink17CSSPropertyParser9validUnitEPNS_14CSSParserValueENS0_5UnitsENS_13CSSParserModeENS0_31ReleaseParsedCalcValueConditionE
- fun:_ZN5blink17CSSPropertyParser9validUnitEPNS_14CSSParserValueENS0_5UnitsENS0_31ReleaseParsedCalcValueConditionE
- ...
- fun:_ZN5blink17CSSPropertyParser10parseValueENS_13CSSPropertyIDEb
- fun:_ZN5blink17CSSPropertyParser10parseValueENS_13CSSPropertyID*
- fun:_ZN5blink13CSSParserImpl23consumeDeclarationValueENS_19CSSParserTokenRangeENS_13CSSPropertyIDEbNS_13StyleRuleBase4TypeE
-}
-{
bug_514434
Memcheck:Leak
fun:malloc
@@ -2963,13 +2885,6 @@
fun:_ZN5blink9FrameView6layoutEv
}
{
- bug_571272
- Memcheck:Overlap
- fun:memcpy*
- fun:_ZN3net10QuicFramer14EncryptPayloadENS_15EncryptionLevel*
- fun:_ZN3net17QuicPacketCreator15SerializePacketEPcm
-}
-{
bug_571543
Memcheck:Leak
...
@@ -2984,12 +2899,11 @@
bug_576259_a
Memcheck:Uninitialized
fun:_ZN7GrGLGpu11bindTextureEiRK15GrTextureParamsbP11GrGLTexture
+ ...
fun:_ZN7GrGLGpu12flushGLStateERK10GrPipelineRK20GrPrimitiveProcessor
fun:_ZN7GrGLGpu6onDrawERK10GrPipelineRK20GrPrimitiveProcessorPK6GrMeshi
fun:_ZN5GrGpu4drawERK10GrPipelineRK20GrPrimitiveProcessorPK6GrMeshi
fun:_ZN13GrVertexBatch6onDrawEP17GrBatchFlushState
- ...
- fun:_ZN2cc17SingleThreadProxy36ScheduledActionDrawAndSwapIfPossibleEv
}
{
bug_576259_b
@@ -3017,7 +2931,6 @@
fun:_ZN5blink14PersistentBaseINS_15StyleFilterDataELNS_31WeaknessPersistentConfigurationE0ELNS_38CrossThreadnessPersistentConfigurationE0EEnwEm
fun:_ZN5blink26RefCountedGarbageCollectedINS_15StyleFilterDataEE13makeKeepAliveEv
fun:_ZN5blink26RefCountedGarbageCollectedINS_15StyleFilterDataEE3refEv
- fun:_ZN3WTF6RefPtrIN5blink15StyleFilterDataEEC2IS2_EERKNS_6RawPtrIT_EEPNSt9enable_ifIXsr3std10is_base_ofIS2_S6_EE5valueEvE4typeE
fun:_ZN5blink7DataRefINS_15StyleFilterDataEE4initEv
fun:_ZN5blink13ComputedStyle18createInitialStyleEv
fun:_ZN5blink13ComputedStyle19mutableInitialStyleEv
@@ -3145,14 +3058,12 @@
fun:_ZN4base4BindIMN7content21ChromeAppCacheServiceEFvRKNS_8FilePathEPNS1_15ResourceContextEPN3net23URLRequestContextGetterE13scoped_refptrIN7storage20SpecialStoragePolicyEEEJPS2_S3_S7_SB_IS9_ESE_EEENS_8CallbackINS_8internal22MakeUnboundRunTypeImplIT_JDpT0_EE4TypeEEESM_DpOSN_
}
{
- bug_600484
+ bug_602964
Memcheck:Leak
fun:_Znw*
- fun:_ZN4mojo3edk2js13HandleWrapper6Create*
- fun:_ZN3gin9ConverterIN4mojo6Handle*
- fun:_ZN3gin11ConvertToV8IN4mojo6Handle*
- fun:_ZN3gin10ToV8TraitsIN4mojo6HandleELb0EE14TryConvertToV8*
- fun:_ZN3gin14TryConvertToV8IN4mojo6Handle*
- fun:_ZN3gin10Dictionary3SetIN4mojo6Handle*
- fun:_ZN4mojo3edk2js12_GLOBAL__N_114CreateDataPipe*
+ fun:_ZN4base4BindIMNS_12_GLOBAL__N_121PostTaskAndReplyRelayEFvvEJNS_8internal17UnretainedWrapper*
+ fun:_ZN4base8internal20PostTaskAndReplyImpl16PostTaskAndReplyERKN15tracked_objects8LocationERKNS*
+ fun:_ZN4base10TaskRunner16PostTaskAndReplyERKN15tracked_objects8LocationERKNS_8CallbackIFvvELNS*
+ fun:_ZN4base26PostTaskAndReplyWithResultIN3net20WifiPHYLayerProtocolES2_EEbPNS*
+ fun:_ZN7metrics22NetworkMetricsProvider25ProbeWifiPHYLayerProtocolEv
}
diff --git a/chromium/tools/valgrind/memcheck/suppressions_linux.txt b/chromium/tools/valgrind/memcheck/suppressions_linux.txt
index 870cee2d360..7474efa0b63 100644
--- a/chromium/tools/valgrind/memcheck/suppressions_linux.txt
+++ b/chromium/tools/valgrind/memcheck/suppressions_linux.txt
@@ -126,18 +126,3 @@
fun:_ZN2ui16AXTreeSerializerIPN5views16AXAuraObjWrapperENS_10AXNodeDataENS_10AXTreeDataEE16SerializeChangesES3_PNS_16AXTreeUpdateBaseIS4_S5_EE
fun:_ZN35AXTreeSourceAuraTest_Serialize_Test8TestBodyEv
}
-{
- bug_588849a
- Memcheck:Leak
- fun:_Znw*
- fun:_ZN4base4BindIMN6syncer15ModelSafeWorkerEFvNS_8CallbackIFvNS1_14ModelSafeGroupEELNS_8internal8CopyModeE1EEEEJPS2_RS8_EEENS3_INS6_22MakeUnboundRunTypeImplIT_JDpT0_EE4TypeELS7_1EEESE_DpOSF_
- fun:_ZN6syncer15ModelSafeWorker28UnregisterForLoopDestructionEN4base8CallbackIFvNS_14ModelSafeGroupEELNS1_8internal8CopyModeE1EEE
- fun:_ZN12browser_sync20SyncBackendRegistrar8ShutdownEv
-}
-{
- bug_588849b
- Memcheck:Leak
- fun:_Znw*
- fun:_ZN30ProfileSyncServiceAutofillTest24CreateDataTypeControllerEN6syncer9ModelTypeE
- fun:_ZN30ProfileSyncServiceAutofillTest16StartSyncServiceERKN4base8CallbackIF*syncer9ModelTypeE
-}
diff --git a/chromium/tools/vim/ninja-build.vim b/chromium/tools/vim/ninja-build.vim
index 70e5a83cf21..76e2049f791 100644
--- a/chromium/tools/vim/ninja-build.vim
+++ b/chromium/tools/vim/ninja-build.vim
@@ -41,17 +41,17 @@ def path_to_source_root():
return candidate
-def path_to_build_dir(configuration):
- """Returns <chrome_root>/<output_dir>/(Release|Debug)."""
+def path_to_build_dir():
+ """Returns <chrome_root>/<output_dir>/(Release|Debug|<other>)."""
chrome_root = path_to_source_root()
sys.path.append(os.path.join(chrome_root, 'tools', 'vim'))
from ninja_output import GetNinjaOutputDirectory
- return GetNinjaOutputDirectory(chrome_root, configuration)
+ return GetNinjaOutputDirectory(chrome_root)
-def compute_ninja_command_for_current_buffer(configuration=None):
+def compute_ninja_command_for_current_buffer():
"""Returns the shell command to compile the file in the current buffer."""
- build_dir = path_to_build_dir(configuration)
+ build_dir = path_to_build_dir()
# ninja needs filepaths for the ^ syntax to be relative to the
# build directory.
@@ -65,8 +65,8 @@ def compute_ninja_command_for_current_buffer(configuration=None):
vim.command('return "%s"' % build_cmd)
-def compute_ninja_command_for_targets(targets='', configuration=None):
- build_cmd = ' '.join(['ninja', '-C', path_to_build_dir(configuration),
+def compute_ninja_command_for_targets(targets=''):
+ build_cmd = ' '.join(['ninja', '-C', path_to_build_dir(),
targets])
vim.command('return "%s"' % build_cmd)
endpython
diff --git a/chromium/tools/vim/ninja_output.py b/chromium/tools/vim/ninja_output.py
index 5bb638ab6d9..e6add1302c8 100644
--- a/chromium/tools/vim/ninja_output.py
+++ b/chromium/tools/vim/ninja_output.py
@@ -10,8 +10,8 @@ import itertools
import re
-def GetNinjaOutputDirectory(chrome_root, configuration=None):
- """Returns <chrome_root>/<output_dir>/(Release|Debug).
+def GetNinjaOutputDirectory(chrome_root):
+ """Returns <chrome_root>/<output_dir>/(Release|Debug|<other>).
If either of the following environment variables are set, their
value is used to determine the output directory:
@@ -20,11 +20,7 @@ def GetNinjaOutputDirectory(chrome_root, configuration=None):
Otherwise, all directories starting with the word out are examined.
- The output directory must contain {configuration}/build.ninja (if
- configuration is None, both Debug and Release will be checked).
-
- The configuration chosen is the one most recently generated/built,
- but can be overriden via the <configuration> parameter.
+ The configuration chosen is the one most recently generated/built.
"""
output_dirs = []
@@ -45,15 +41,13 @@ def GetNinjaOutputDirectory(chrome_root, configuration=None):
if os.path.isdir(out):
output_dirs.append(os.path.relpath(out, start = chrome_root))
- configs = ['Debug', 'Release', 'Default']
- if configuration:
- configs = [configuration]
-
def generate_paths():
- for out_dir, config in itertools.product(output_dirs, configs):
- path = os.path.join(chrome_root, out_dir, config)
- if os.path.exists(os.path.join(path, 'build.ninja')):
- yield path
+ for out_dir in output_dirs:
+ out_path = os.path.join(chrome_root, out_dir)
+ for config in os.listdir(out_path):
+ path = os.path.join(out_path, config)
+ if os.path.exists(os.path.join(path, 'build.ninja')):
+ yield path
def approx_directory_mtime(path):
# This is a heuristic; don't recurse into subdirectories.