blob: c11fd7cb72747752bcc974429389a3a654c89e98 [file] [log] [blame]
Fumitoshi Ukai8599cf52024-02-15 04:34:521#!/usr/bin/env python3
2# Copyright 2024 The Chromium Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5"""A script gets the information needed by lDE language services.
6
7Expected to run it at repository root, where top DEP, .gn etc exists.
8Not intended to run by user.
9See go/reqs-for-peep
10"""
11
12import argparse
13import os
14import re
15import subprocess
16import sys
Junji Watanabe000c40b2025-04-18 07:50:0817import uuid
Fumitoshi Ukai8599cf52024-02-15 04:34:5218
Junji Watanabe000c40b2025-04-18 07:50:0819sys.path.append(os.path.join(os.path.dirname(__file__), os.pardir, os.pardir,
20 'third_party', 'depot_tools'))
21import android_build_server_helper
22import gn_helper
Fumitoshi Ukai8599cf52024-02-15 04:34:5223
Junji Watanabe000c40b2025-04-18 07:50:0824def _retrieve_gn_args(out_dir):
25 """
26 Retrieves relevant GN args and calculate the defaults.
27 """
28 is_android = False
29 use_android_build_server = True
Fumitoshi Ukai128f48d2024-06-04 08:25:2030 use_reclient = None
Junji Watanabe000c40b2025-04-18 07:50:0831 if gn_helper.exists(out_dir):
32 for k, v in gn_helper.args(out_dir):
33 if k == "use_reclient" and v == "true":
34 use_reclient = True
35 continue
36 if k == "use_reclient" and v == "false":
37 use_reclient = False
38 continue
39 if k == "android_static_analysis" and v != '"build_server"':
40 use_android_build_server = False
41 continue
42 if k == "target_os" and v == '"android"':
43 is_android = True
44 continue
45 if use_android_build_server is None and is_android:
46 use_android_build_server = True
47
48 return use_reclient, use_android_build_server
Fumitoshi Ukai128f48d2024-06-04 08:25:2049
Fumitoshi Ukai8599cf52024-02-15 04:34:5250
51def main():
52 parser = argparse.ArgumentParser()
Philipp Wollermannc5830102024-04-19 04:35:2353 parser.add_argument('source', nargs='+',
Fumitoshi Ukai8599cf52024-02-15 04:34:5254 help=('The source file being analyzed.'
Philipp Wollermannc5830102024-04-19 04:35:2355 'Multiple source arguments can be passed in order to batch '
56 'process if desired.'))
Fumitoshi Ukai8599cf52024-02-15 04:34:5257 parser.add_argument('--perform-build', action='store_true',
58 help=('If specified, actually build the target, including any generated '
59 'prerequisite files. '
60 'If --perform-build is not passed, the contents of '
61 'the GeneratedFile results will only be returned if a build has '
62 'been previously completed, and may be stale.'))
63 parser.add_argument('--out-dir',
Philipp Wollermannc5830102024-04-19 04:35:2364 help=('Output directory, containing args.gn, which specifies the build '
Fumitoshi Ukai8599cf52024-02-15 04:34:5265 'configuration.'))
Richard Wang02fbd2dd2024-12-03 08:29:3166 parser.add_argument('--log-dir', help=('Directory to save log files to.'))
Fumitoshi Ukai3788c9e2025-02-06 06:05:4767 parser.add_argument('--format', choices=['proto', 'prototext', 'json'],
68 default='proto', help=('Output format.'))
Fumitoshi Ukai8599cf52024-02-15 04:34:5269 options = parser.parse_args()
70
71 this_dir = os.path.dirname(__file__)
72 repo_root = os.path.join(this_dir, '..', '..')
73
74 targets = []
Fumitoshi Ukai82a82622025-02-06 02:49:1675 use_prepare = True
Fumitoshi Ukai3fb1a042024-10-08 00:58:2576 use_prepare_header_only = True
Fumitoshi Ukai8599cf52024-02-15 04:34:5277 for source in options.source:
Fumitoshi Ukai3fb1a042024-10-08 00:58:2578 _, ext = os.path.splitext(source)
Fumitoshi Ukai82a82622025-02-06 02:49:1679 if ext == '.java':
80 # need to include generated *.jar for java.
81 use_prepare = False
Fumitoshi Ukai3fb1a042024-10-08 00:58:2582 if ext not in ('.c', '.cc', '.cxx', '.cpp', '.m', '.mm', '.S',
83 '.h', '.hxx', '.hpp', '.inc'):
84 use_prepare_header_only = False
Fumitoshi Ukai8599cf52024-02-15 04:34:5285 # source is repo root (cwd) relative,
86 # but siso uses out dir relative target.
87 target = os.path.relpath(source, start=options.out_dir) + "^"
88 targets.append(target)
89
Junji Watanabe000c40b2025-04-18 07:50:0890 use_reclient, use_android_build_server = _retrieve_gn_args(options.out_dir)
91
92 if use_reclient:
Fumitoshi Ukaid1f5e3352024-05-09 04:31:0493 # b/335795623 ide_query compiler_arguments contain non-compiler arguments
94 sys.stderr.write(
Fumitoshi Ukai128f48d2024-06-04 08:25:2095 'ide_query won\'t work well with "use_reclient=true"\n'
96 'Set "use_reclient=false" in args.gn.\n')
Fumitoshi Ukaid1f5e3352024-05-09 04:31:0497 sys.exit(1)
Fumitoshi Ukai8599cf52024-02-15 04:34:5298 if options.perform_build:
Fumitoshi Ukai9ac4c6212025-03-19 03:31:3299 # forget last targets of normal build as this build will update
100 # .siso_fs_state.
101 if os.path.exists(os.path.join(options.out_dir, '.siso_last_targets')):
102 os.remove(os.path.join(options.out_dir, '.siso_last_targets'))
Fumitoshi Ukaid1f5e3352024-05-09 04:31:04103 args = ['siso', 'ninja']
Fumitoshi Ukai4ec43222024-04-30 08:51:36104 # use `-k=0` to build generated files as much as possible.
105 args.extend([
106 '-k=0',
Fumitoshi Ukai4ec43222024-04-30 08:51:36107 '-C',
108 options.out_dir,
109 ])
Fumitoshi Ukai82a82622025-02-06 02:49:16110 if use_prepare:
111 args.extend(['--prepare'])
Richard Wang02fbd2dd2024-12-03 08:29:31112 if options.log_dir:
113 args.extend(['-log_dir', options.log_dir])
Fumitoshi Ukai8599cf52024-02-15 04:34:52114 args.extend(targets)
Junji Watanabeed7f7a02025-04-25 00:05:43115 # Set build ID for android build server.
116 build_id = str(uuid.uuid4())
117 os.environ.setdefault("AUTONINJA_BUILD_ID", build_id)
Fumitoshi Ukai35d16de2024-05-02 09:18:32118 env = os.environ.copy()
Fumitoshi Ukai3fb1a042024-10-08 00:58:25119 if use_prepare_header_only:
Fumitoshi Ukai86ca44c2025-04-11 04:41:52120 env['SISO_EXPERIMENTS'] = 'no-fast-deps,prepare-header-only,ignore-missing-targets'
Fumitoshi Ukai3fb1a042024-10-08 00:58:25121 else:
Fumitoshi Ukai86ca44c2025-04-11 04:41:52122 env['SISO_EXPERIMENTS'] = 'no-fast-deps,ignore-missing-targets'
Junji Watanabe000c40b2025-04-18 07:50:08123 with android_build_server_helper.build_server_context(
124 build_id,
125 options.out_dir,
126 use_android_build_server=use_android_build_server,
127 ):
128 with subprocess.Popen(
129 args,
130 cwd=repo_root,
131 env=env,
132 stderr=subprocess.STDOUT,
133 stdout=subprocess.PIPE,
134 universal_newlines=True
135 ) as p:
136 for line in p.stdout:
137 print(line, end='', file=sys.stderr)
138 # loop ends when program finishes, but must wait else returncode is None.
139 p.wait()
140 if p.returncode != 0:
141 # TODO: report error in IdeAnalysis.Status?
142 sys.stderr.write('build failed with %d\n' % p.returncode)
143 # even if build fails, it should report ideanalysis back.
Fumitoshi Ukai8599cf52024-02-15 04:34:52144
145 args = ['siso', 'query', 'ideanalysis', '-C', options.out_dir]
Fumitoshi Ukai3788c9e2025-02-06 06:05:47146 if options.format:
147 args.extend(['--format', options.format])
Fumitoshi Ukai8599cf52024-02-15 04:34:52148 args.extend(targets)
149 subprocess.run(args, cwd=repo_root, check=True)
150
151if __name__ == '__main__':
152 sys.exit(main())