import argparse
import os
import re
import subprocess
import sys
import uuid
sys.path.append(os.path.join(os.path.dirname(__file__), os.pardir, os.pardir,
'third_party', 'depot_tools'))
import android_build_server_helper
import gn_helper
def _retrieve_gn_args(out_dir):
is_android = False
use_android_build_server = True
use_reclient = None
if gn_helper.exists(out_dir):
for k, v in gn_helper.args(out_dir):
if k == "use_reclient" and v == "true":
use_reclient = True
continue
if k == "use_reclient" and v == "false":
use_reclient = False
continue
if k == "android_static_analysis" and v != '"build_server"':
use_android_build_server = False
continue
if k == "target_os" and v == '"android"':
is_android = True
continue
if use_android_build_server is None and is_android:
use_android_build_server = True
return use_reclient, use_android_build_server
def main():
parser = argparse.ArgumentParser()
parser.add_argument('source', nargs='+',
help=('The source file being analyzed.'
'Multiple source arguments can be passed in order to batch '
'process if desired.'))
parser.add_argument('--perform-build', action='store_true',
help=('If specified, actually build the target, including any generated '
'prerequisite files. '
'If --perform-build is not passed, the contents of '
'the GeneratedFile results will only be returned if a build has '
'been previously completed, and may be stale.'))
parser.add_argument('--out-dir',
help=('Output directory, containing args.gn, which specifies the build '
'configuration.'))
parser.add_argument('--log-dir', help=('Directory to save log files to.'))
parser.add_argument('--format', choices=['proto', 'prototext', 'json'],
default='proto', help=('Output format.'))
options = parser.parse_args()
this_dir = os.path.dirname(__file__)
repo_root = os.path.join(this_dir, '..', '..')
targets = []
use_prepare = True
use_prepare_header_only = True
for source in options.source:
_, ext = os.path.splitext(source)
if ext == '.java':
use_prepare = False
if ext not in ('.c', '.cc', '.cxx', '.cpp', '.m', '.mm', '.S',
'.h', '.hxx', '.hpp', '.inc'):
use_prepare_header_only = False
target = os.path.relpath(source, start=options.out_dir) + "^"
targets.append(target)
use_reclient, use_android_build_server = _retrieve_gn_args(options.out_dir)
if use_reclient:
sys.stderr.write(
'ide_query won\'t work well with "use_reclient=true"\n'
'Set "use_reclient=false" in args.gn.\n')
sys.exit(1)
if options.perform_build:
if os.path.exists(os.path.join(options.out_dir, '.siso_last_targets')):
os.remove(os.path.join(options.out_dir, '.siso_last_targets'))
args = ['siso', 'ninja']
args.extend([
'-k=0',
'-C',
options.out_dir,
])
if use_prepare:
args.extend(['--prepare'])
if options.log_dir:
args.extend(['-log_dir', options.log_dir])
args.extend(targets)
build_id = str(uuid.uuid4())
os.environ.setdefault("AUTONINJA_BUILD_ID", build_id)
env = os.environ.copy()
if use_prepare_header_only:
env['SISO_EXPERIMENTS'] = 'no-fast-deps,prepare-header-only,ignore-missing-targets'
else:
env['SISO_EXPERIMENTS'] = 'no-fast-deps,ignore-missing-targets'
with android_build_server_helper.build_server_context(
build_id,
options.out_dir,
use_android_build_server=use_android_build_server,
):
with subprocess.Popen(
args,
cwd=repo_root,
env=env,
stderr=subprocess.STDOUT,
stdout=subprocess.PIPE,
universal_newlines=True
) as p:
for line in p.stdout:
print(line, end='', file=sys.stderr)
p.wait()
if p.returncode != 0:
sys.stderr.write('build failed with %d\n' % p.returncode)
args = ['siso', 'query', 'ideanalysis', '-C', options.out_dir]
if options.format:
args.extend(['--format', options.format])
args.extend(targets)
subprocess.run(args, cwd=repo_root, check=True)
if __name__ == '__main__':
sys.exit(main())