代码拉取完成,页面将自动刷新
同步操作将从 dengly/depot_tools 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
#!/usr/bin/env python3
# Copyright 2018 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""
This is script to upload ninja_log from googler.
Server side implementation is in
https://cs.chromium.org/chromium/infra/go/src/infra/appengine/chromium_build_stats/
Uploaded ninjalog is stored in BigQuery table having following schema.
https://cs.chromium.org/chromium/infra/go/src/infra/appengine/chromium_build_stats/ninjaproto/ninjalog.proto
The log will be used to analyze user side build performance.
"""
import argparse
import gzip
import io
import json
import logging
import multiprocessing
import os
import platform
import subprocess
import sys
import time
import urllib.request
# These build configs affect build performance.
ALLOWLISTED_CONFIGS = (
"symbol_level",
"use_goma",
"is_debug",
"is_component_build",
"enable_nacl",
"host_os",
"host_cpu",
"target_os",
"target_cpu",
"blink_symbol_level",
"is_java_debug",
"treat_warnings_as_errors",
"disable_android_lint",
"use_errorprone_java_compiler",
"incremental_install",
"android_static_analysis",
)
def IsGoogler():
"""Check whether this user is Googler or not."""
p = subprocess.run(
"cipd auth-info",
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
shell=True,
)
if p.returncode != 0:
return False
lines = p.stdout.splitlines()
if len(lines) == 0:
return False
l = lines[0]
# |l| will be like 'Logged in as <user>@google.com.' for googler using
# reclient.
return l.startswith("Logged in as ") and l.endswith("@google.com.")
def ParseGNArgs(gn_args):
"""Parse gn_args as json and return config dictionary."""
configs = json.loads(gn_args)
build_configs = {}
for config in configs:
key = config["name"]
if key not in ALLOWLISTED_CONFIGS:
continue
if "current" in config:
build_configs[key] = config["current"]["value"]
else:
build_configs[key] = config["default"]["value"]
return build_configs
def GetBuildTargetFromCommandLine(cmdline):
"""Get build targets from commandline."""
# Skip argv0, argv1: ['/path/to/python3', '/path/to/depot_tools/ninja.py']
idx = 2
# Skipping all args that involve these flags, and taking all remaining args
# as targets.
onearg_flags = ("-C", "-d", "-f", "-j", "-k", "-l", "-p", "-t", "-w")
zeroarg_flags = ("--version", "-n", "-v")
targets = []
while idx < len(cmdline):
arg = cmdline[idx]
if arg in onearg_flags:
idx += 2
continue
if arg[:2] in onearg_flags or arg in zeroarg_flags:
idx += 1
continue
# A target doesn't start with '-'.
if arg.startswith("-"):
idx += 1
continue
# Avoid uploading absolute paths accidentally. e.g. b/270907050
if os.path.isabs(arg):
idx += 1
continue
targets.append(arg)
idx += 1
return targets
def GetJflag(cmdline):
"""Parse cmdline to get flag value for -j"""
for i in range(len(cmdline)):
if (cmdline[i] == "-j" and i + 1 < len(cmdline)
and cmdline[i + 1].isdigit()):
return int(cmdline[i + 1])
if cmdline[i].startswith("-j") and cmdline[i][len("-j"):].isdigit():
return int(cmdline[i][len("-j"):])
def GetMetadata(cmdline, ninjalog):
"""Get metadata for uploaded ninjalog.
Returned metadata has schema defined in
https://cs.chromium.org?q="type+Metadata+struct+%7B"+file:%5Einfra/go/src/infra/appengine/chromium_build_stats/ninjalog/
TODO(tikuta): Collect GOMA_* env var.
"""
build_dir = os.path.dirname(ninjalog)
build_configs = {}
try:
args = ["gn", "args", build_dir, "--list", "--short", "--json"]
if sys.platform == "win32":
# gn in PATH is bat file in windows environment (except cygwin).
args = ["cmd", "/c"] + args
gn_args = subprocess.check_output(args)
build_configs = ParseGNArgs(gn_args)
except subprocess.CalledProcessError as e:
logging.error("Failed to call gn %s", e)
build_configs = {}
# Stringify config.
for k in build_configs:
build_configs[k] = str(build_configs[k])
metadata = {
"platform": platform.system(),
"cpu_core": multiprocessing.cpu_count(),
"build_configs": build_configs,
"targets": GetBuildTargetFromCommandLine(cmdline),
}
jflag = GetJflag(cmdline)
if jflag is not None:
metadata["jobs"] = jflag
return metadata
def GetNinjalog(cmdline):
"""GetNinjalog returns the path to ninjalog from cmdline."""
# ninjalog is in current working directory by default.
ninjalog_dir = "."
i = 0
while i < len(cmdline):
cmd = cmdline[i]
i += 1
if cmd == "-C" and i < len(cmdline):
ninjalog_dir = cmdline[i]
i += 1
continue
if cmd.startswith("-C") and len(cmd) > len("-C"):
ninjalog_dir = cmd[len("-C"):]
return os.path.join(ninjalog_dir, ".ninja_log")
def main():
parser = argparse.ArgumentParser()
parser.add_argument(
"--server",
default="chromium-build-stats.appspot.com",
help="server to upload ninjalog file.",
)
parser.add_argument("--ninjalog", help="ninjalog file to upload.")
parser.add_argument("--verbose",
action="store_true",
help="Enable verbose logging.")
parser.add_argument(
"--cmdline",
required=True,
nargs=argparse.REMAINDER,
help="command line args passed to ninja.",
)
args = parser.parse_args()
if args.verbose:
logging.basicConfig(level=logging.INFO)
else:
# Disable logging.
logging.disable(logging.CRITICAL)
if not IsGoogler():
return 0
ninjalog = args.ninjalog or GetNinjalog(args.cmdline)
if not os.path.isfile(ninjalog):
logging.warning("ninjalog is not found in %s", ninjalog)
return 1
# We assume that each ninja invocation interval takes at least 2 seconds.
# This is not to have duplicate entry in server when current build is no-op.
if os.stat(ninjalog).st_mtime < time.time() - 2:
logging.info("ninjalog is not updated recently %s", ninjalog)
return 0
output = io.BytesIO()
with open(ninjalog) as f:
with gzip.GzipFile(fileobj=output, mode="wb") as g:
g.write(f.read().encode())
g.write(b"# end of ninja log\n")
metadata = GetMetadata(args.cmdline, ninjalog)
logging.info("send metadata: %s", json.dumps(metadata))
g.write(json.dumps(metadata).encode())
resp = urllib.request.urlopen(
urllib.request.Request(
"https://" + args.server + "/upload_ninja_log/",
data=output.getvalue(),
headers={"Content-Encoding": "gzip"},
))
if resp.status != 200:
logging.warning("unexpected status code for response: %s", resp.status)
return 1
logging.info("response header: %s", resp.headers)
logging.info("response content: %s", resp.read())
return 0
if __name__ == "__main__":
sys.exit(main())
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。