xref: /aosp_15_r20/tools/treble/build/sandbox/build_android_sandboxed.py (revision 105f628577ac4ba0e277a494fbb614ed8c12a994)
1*105f6285SAndroid Build Coastguard Worker# Copyright 2020 Google LLC
2*105f6285SAndroid Build Coastguard Worker#
3*105f6285SAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
4*105f6285SAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
5*105f6285SAndroid Build Coastguard Worker# You may obtain a copy of the License at
6*105f6285SAndroid Build Coastguard Worker#
7*105f6285SAndroid Build Coastguard Worker#     https://www.apache.org/licenses/LICENSE-2.0
8*105f6285SAndroid Build Coastguard Worker#
9*105f6285SAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
10*105f6285SAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS,
11*105f6285SAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*105f6285SAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
13*105f6285SAndroid Build Coastguard Worker# limitations under the License.
14*105f6285SAndroid Build Coastguard Worker"""Builds an Android target in a secure sandbox."""
15*105f6285SAndroid Build Coastguard Worker
16*105f6285SAndroid Build Coastguard Workerimport argparse
17*105f6285SAndroid Build Coastguard Workerimport os
18*105f6285SAndroid Build Coastguard Workerfrom . import config
19*105f6285SAndroid Build Coastguard Workerfrom . import nsjail
20*105f6285SAndroid Build Coastguard Workerfrom . import rbe
21*105f6285SAndroid Build Coastguard Worker
22*105f6285SAndroid Build Coastguard Worker_DEFAULT_COMMAND_WRAPPER = \
23*105f6285SAndroid Build Coastguard Worker  '/src/tools/treble/build/sandbox/build_android_target.sh'
24*105f6285SAndroid Build Coastguard Worker
25*105f6285SAndroid Build Coastguard Worker
26*105f6285SAndroid Build Coastguard Workerdef build(build_target,
27*105f6285SAndroid Build Coastguard Worker          release_target,
28*105f6285SAndroid Build Coastguard Worker          variant,
29*105f6285SAndroid Build Coastguard Worker          nsjail_bin,
30*105f6285SAndroid Build Coastguard Worker          chroot,
31*105f6285SAndroid Build Coastguard Worker          dist_dir,
32*105f6285SAndroid Build Coastguard Worker          build_id,
33*105f6285SAndroid Build Coastguard Worker          max_cpus,
34*105f6285SAndroid Build Coastguard Worker          build_goals,
35*105f6285SAndroid Build Coastguard Worker          config_file=None,
36*105f6285SAndroid Build Coastguard Worker          command_wrapper=_DEFAULT_COMMAND_WRAPPER,
37*105f6285SAndroid Build Coastguard Worker          use_rbe=False,
38*105f6285SAndroid Build Coastguard Worker          readonly_bind_mounts=[],
39*105f6285SAndroid Build Coastguard Worker          env=[]):
40*105f6285SAndroid Build Coastguard Worker  """Builds an Android target in a secure sandbox.
41*105f6285SAndroid Build Coastguard Worker
42*105f6285SAndroid Build Coastguard Worker  Args:
43*105f6285SAndroid Build Coastguard Worker    build_target: A string with the name of the build target.
44*105f6285SAndroid Build Coastguard Worker    release_target: The release target config, e.g., next, trunk_food, ...
45*105f6285SAndroid Build Coastguard Worker    variant: A string with the build variant.
46*105f6285SAndroid Build Coastguard Worker    nsjail_bin: A string with the path to the nsjail binary.
47*105f6285SAndroid Build Coastguard Worker    chroot: A string with the path to the chroot of the NsJail sandbox.
48*105f6285SAndroid Build Coastguard Worker    dist_dir: A string with the path to the Android dist directory.
49*105f6285SAndroid Build Coastguard Worker    build_id: A string with the Android build identifier.
50*105f6285SAndroid Build Coastguard Worker    max_cpus: An integer with maximum number of CPUs.
51*105f6285SAndroid Build Coastguard Worker    build_goals: A list of strings with the goals and options to provide to the
52*105f6285SAndroid Build Coastguard Worker      build command.
53*105f6285SAndroid Build Coastguard Worker    config_file: A string path to an overlay configuration file.
54*105f6285SAndroid Build Coastguard Worker    command_wrapper: A string path to the command wrapper.
55*105f6285SAndroid Build Coastguard Worker    use_rbe: If true, will attempt to use RBE for the build.
56*105f6285SAndroid Build Coastguard Worker    readonly_bind_mounts: A list of string paths to be mounted as read-only.
57*105f6285SAndroid Build Coastguard Worker    env: An array of environment variables to define in the NsJail sandbox in
58*105f6285SAndroid Build Coastguard Worker      the `var=val` syntax.
59*105f6285SAndroid Build Coastguard Worker
60*105f6285SAndroid Build Coastguard Worker  Returns:
61*105f6285SAndroid Build Coastguard Worker    A list of commands that were executed. Each command is a list of strings.
62*105f6285SAndroid Build Coastguard Worker  """
63*105f6285SAndroid Build Coastguard Worker  if config_file:
64*105f6285SAndroid Build Coastguard Worker    cfg = config.Config(config_file)
65*105f6285SAndroid Build Coastguard Worker    android_target = cfg.get_build_config_android_target(build_target)
66*105f6285SAndroid Build Coastguard Worker    if cfg.has_tag(build_target, 'skip'):
67*105f6285SAndroid Build Coastguard Worker      print('Warning: skipping build_target "{}" due to tag being set'.format(
68*105f6285SAndroid Build Coastguard Worker          build_target))
69*105f6285SAndroid Build Coastguard Worker      return []
70*105f6285SAndroid Build Coastguard Worker  else:
71*105f6285SAndroid Build Coastguard Worker    android_target = build_target
72*105f6285SAndroid Build Coastguard Worker
73*105f6285SAndroid Build Coastguard Worker  # All builds are required to run with the root of the
74*105f6285SAndroid Build Coastguard Worker  # Android source tree as the current directory.
75*105f6285SAndroid Build Coastguard Worker  source_dir = os.getcwd()
76*105f6285SAndroid Build Coastguard Worker  command = [
77*105f6285SAndroid Build Coastguard Worker      command_wrapper,
78*105f6285SAndroid Build Coastguard Worker      '%s-%s-%s' % (android_target, release_target, variant),
79*105f6285SAndroid Build Coastguard Worker      '/src',
80*105f6285SAndroid Build Coastguard Worker      'make',
81*105f6285SAndroid Build Coastguard Worker      '-j',
82*105f6285SAndroid Build Coastguard Worker  ] + build_goals
83*105f6285SAndroid Build Coastguard Worker
84*105f6285SAndroid Build Coastguard Worker  extra_nsjail_args = []
85*105f6285SAndroid Build Coastguard Worker  cleanup = lambda: None
86*105f6285SAndroid Build Coastguard Worker  nsjail_wrapper = []
87*105f6285SAndroid Build Coastguard Worker  if use_rbe:
88*105f6285SAndroid Build Coastguard Worker    cleanup = rbe.setup(env)
89*105f6285SAndroid Build Coastguard Worker    env = rbe.prepare_env(env)
90*105f6285SAndroid Build Coastguard Worker    extra_nsjail_args.extend(rbe.get_extra_nsjail_args())
91*105f6285SAndroid Build Coastguard Worker    readonly_bind_mounts.extend(rbe.get_readonlybind_mounts())
92*105f6285SAndroid Build Coastguard Worker    nsjail_wrapper = rbe.get_nsjail_bin_wrapper()
93*105f6285SAndroid Build Coastguard Worker
94*105f6285SAndroid Build Coastguard Worker  ret = nsjail.run(
95*105f6285SAndroid Build Coastguard Worker      nsjail_bin=nsjail_bin,
96*105f6285SAndroid Build Coastguard Worker      chroot=chroot,
97*105f6285SAndroid Build Coastguard Worker      overlay_config=config_file,
98*105f6285SAndroid Build Coastguard Worker      source_dir=source_dir,
99*105f6285SAndroid Build Coastguard Worker      command=command,
100*105f6285SAndroid Build Coastguard Worker      build_target=build_target,
101*105f6285SAndroid Build Coastguard Worker      dist_dir=dist_dir,
102*105f6285SAndroid Build Coastguard Worker      build_id=build_id,
103*105f6285SAndroid Build Coastguard Worker      max_cpus=max_cpus,
104*105f6285SAndroid Build Coastguard Worker      extra_nsjail_args=extra_nsjail_args,
105*105f6285SAndroid Build Coastguard Worker      readonly_bind_mounts=readonly_bind_mounts,
106*105f6285SAndroid Build Coastguard Worker      env=env,
107*105f6285SAndroid Build Coastguard Worker      nsjail_wrapper=nsjail_wrapper)
108*105f6285SAndroid Build Coastguard Worker
109*105f6285SAndroid Build Coastguard Worker  cleanup()
110*105f6285SAndroid Build Coastguard Worker
111*105f6285SAndroid Build Coastguard Worker  return ret
112*105f6285SAndroid Build Coastguard Worker
113*105f6285SAndroid Build Coastguard Worker
114*105f6285SAndroid Build Coastguard Workerdef arg_parser():
115*105f6285SAndroid Build Coastguard Worker  """Returns an ArgumentParser for sanboxed android builds."""
116*105f6285SAndroid Build Coastguard Worker  # Use the top level module docstring for the help description
117*105f6285SAndroid Build Coastguard Worker  parser = argparse.ArgumentParser(
118*105f6285SAndroid Build Coastguard Worker      description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
119*105f6285SAndroid Build Coastguard Worker  parser.add_argument('--build_target', help='The build target.')
120*105f6285SAndroid Build Coastguard Worker  parser.add_argument(
121*105f6285SAndroid Build Coastguard Worker      '--release_target',
122*105f6285SAndroid Build Coastguard Worker      required=True,
123*105f6285SAndroid Build Coastguard Worker      help='Release target config, e.g., next, trunk_food, trunk_staging, ...')
124*105f6285SAndroid Build Coastguard Worker  parser.add_argument(
125*105f6285SAndroid Build Coastguard Worker      '--variant', default='userdebug', help='The Android build variant.')
126*105f6285SAndroid Build Coastguard Worker  parser.add_argument(
127*105f6285SAndroid Build Coastguard Worker      '--nsjail_bin', required=True, help='Path to NsJail binary.')
128*105f6285SAndroid Build Coastguard Worker  parser.add_argument(
129*105f6285SAndroid Build Coastguard Worker      '--chroot',
130*105f6285SAndroid Build Coastguard Worker      required=True,
131*105f6285SAndroid Build Coastguard Worker      help='Path to the chroot to be used for building the Android '
132*105f6285SAndroid Build Coastguard Worker      'platform. This will be mounted as the root filesystem in the '
133*105f6285SAndroid Build Coastguard Worker      'NsJail sandbox.')
134*105f6285SAndroid Build Coastguard Worker  parser.add_argument(
135*105f6285SAndroid Build Coastguard Worker      '--config_file',
136*105f6285SAndroid Build Coastguard Worker      required=True,
137*105f6285SAndroid Build Coastguard Worker      help='Path to the overlay configuration file.')
138*105f6285SAndroid Build Coastguard Worker  parser.add_argument(
139*105f6285SAndroid Build Coastguard Worker      '--command_wrapper',
140*105f6285SAndroid Build Coastguard Worker      default=_DEFAULT_COMMAND_WRAPPER,
141*105f6285SAndroid Build Coastguard Worker      help='Path to the command wrapper. '
142*105f6285SAndroid Build Coastguard Worker      'Defaults to \'%s\'.' % _DEFAULT_COMMAND_WRAPPER)
143*105f6285SAndroid Build Coastguard Worker  parser.add_argument(
144*105f6285SAndroid Build Coastguard Worker      '--readonly_bind_mount',
145*105f6285SAndroid Build Coastguard Worker      type=str,
146*105f6285SAndroid Build Coastguard Worker      default=[],
147*105f6285SAndroid Build Coastguard Worker      action='append',
148*105f6285SAndroid Build Coastguard Worker      help='Path to the a path to be mounted as readonly inside the secure '
149*105f6285SAndroid Build Coastguard Worker      'build sandbox. Can be specified multiple times')
150*105f6285SAndroid Build Coastguard Worker  parser.add_argument(
151*105f6285SAndroid Build Coastguard Worker      '--env',
152*105f6285SAndroid Build Coastguard Worker      '-e',
153*105f6285SAndroid Build Coastguard Worker      type=str,
154*105f6285SAndroid Build Coastguard Worker      default=[],
155*105f6285SAndroid Build Coastguard Worker      action='append',
156*105f6285SAndroid Build Coastguard Worker      help='Specify an environment variable to the NSJail sandbox. Can be specified '
157*105f6285SAndroid Build Coastguard Worker      'muliple times. Syntax: var_name=value')
158*105f6285SAndroid Build Coastguard Worker  parser.add_argument(
159*105f6285SAndroid Build Coastguard Worker      '--dist_dir',
160*105f6285SAndroid Build Coastguard Worker      help='Path to the Android dist directory. This is where '
161*105f6285SAndroid Build Coastguard Worker      'Android platform release artifacts will be written.')
162*105f6285SAndroid Build Coastguard Worker  parser.add_argument(
163*105f6285SAndroid Build Coastguard Worker      '--build_id',
164*105f6285SAndroid Build Coastguard Worker      help='Build identifier what will label the Android platform '
165*105f6285SAndroid Build Coastguard Worker      'release artifacts.')
166*105f6285SAndroid Build Coastguard Worker  parser.add_argument(
167*105f6285SAndroid Build Coastguard Worker      '--max_cpus',
168*105f6285SAndroid Build Coastguard Worker      type=int,
169*105f6285SAndroid Build Coastguard Worker      help='Limit of concurrent CPU cores that the NsJail sanbox '
170*105f6285SAndroid Build Coastguard Worker      'can use.')
171*105f6285SAndroid Build Coastguard Worker  parser.add_argument(
172*105f6285SAndroid Build Coastguard Worker      '--context',
173*105f6285SAndroid Build Coastguard Worker      action='append',
174*105f6285SAndroid Build Coastguard Worker      default=[],
175*105f6285SAndroid Build Coastguard Worker      help='One or more contexts used to select build goals from the '
176*105f6285SAndroid Build Coastguard Worker      'configuration.')
177*105f6285SAndroid Build Coastguard Worker  parser.add_argument(
178*105f6285SAndroid Build Coastguard Worker      '--use_rbe', action='store_true', help='Executes the build on RBE')
179*105f6285SAndroid Build Coastguard Worker  return parser
180*105f6285SAndroid Build Coastguard Worker
181*105f6285SAndroid Build Coastguard Worker
182*105f6285SAndroid Build Coastguard Workerdef parse_args(parser):
183*105f6285SAndroid Build Coastguard Worker  """Parses command line arguments.
184*105f6285SAndroid Build Coastguard Worker
185*105f6285SAndroid Build Coastguard Worker  Returns:
186*105f6285SAndroid Build Coastguard Worker    A dict of all the arguments parsed.
187*105f6285SAndroid Build Coastguard Worker  """
188*105f6285SAndroid Build Coastguard Worker  # Convert the Namespace object to a dict
189*105f6285SAndroid Build Coastguard Worker  return vars(parser.parse_args())
190*105f6285SAndroid Build Coastguard Worker
191*105f6285SAndroid Build Coastguard Worker
192*105f6285SAndroid Build Coastguard Workerdef main():
193*105f6285SAndroid Build Coastguard Worker  args = parse_args(arg_parser())
194*105f6285SAndroid Build Coastguard Worker
195*105f6285SAndroid Build Coastguard Worker  # The --build_target argument could not be required
196*105f6285SAndroid Build Coastguard Worker  # using the standard 'required' argparse option because
197*105f6285SAndroid Build Coastguard Worker  # the argparser is reused by merge_android_sandboxed.py which
198*105f6285SAndroid Build Coastguard Worker  # does not require --build_target.
199*105f6285SAndroid Build Coastguard Worker  if args['build_target'] is None:
200*105f6285SAndroid Build Coastguard Worker    raise ValueError('--build_target is required.')
201*105f6285SAndroid Build Coastguard Worker
202*105f6285SAndroid Build Coastguard Worker  cfg = config.Config(args['config_file'])
203*105f6285SAndroid Build Coastguard Worker  build_goals = cfg.get_build_goals(args['build_target'], set(args['context']))
204*105f6285SAndroid Build Coastguard Worker  build_flags = cfg.get_build_flags(args['build_target'], set(args['context']))
205*105f6285SAndroid Build Coastguard Worker
206*105f6285SAndroid Build Coastguard Worker  build(
207*105f6285SAndroid Build Coastguard Worker      build_target=args['build_target'],
208*105f6285SAndroid Build Coastguard Worker      release_target=args['release_target'],
209*105f6285SAndroid Build Coastguard Worker      variant=args['variant'],
210*105f6285SAndroid Build Coastguard Worker      nsjail_bin=args['nsjail_bin'],
211*105f6285SAndroid Build Coastguard Worker      chroot=args['chroot'],
212*105f6285SAndroid Build Coastguard Worker      config_file=args['config_file'],
213*105f6285SAndroid Build Coastguard Worker      command_wrapper=args['command_wrapper'],
214*105f6285SAndroid Build Coastguard Worker      readonly_bind_mounts=args['readonly_bind_mount'],
215*105f6285SAndroid Build Coastguard Worker      env=args['env'],
216*105f6285SAndroid Build Coastguard Worker      dist_dir=args['dist_dir'],
217*105f6285SAndroid Build Coastguard Worker      build_id=args['build_id'],
218*105f6285SAndroid Build Coastguard Worker      max_cpus=args['max_cpus'],
219*105f6285SAndroid Build Coastguard Worker      use_rbe=args['use_rbe'],
220*105f6285SAndroid Build Coastguard Worker      build_goals=build_goals + build_flags)
221*105f6285SAndroid Build Coastguard Worker
222*105f6285SAndroid Build Coastguard Worker
223*105f6285SAndroid Build Coastguard Workerif __name__ == '__main__':
224*105f6285SAndroid Build Coastguard Worker  main()
225