blob: aa202b58f54d302eb8c5dfa25a8c2b343ea73e79 [file] [log] [blame]
Bertrand SIMONNET6b6a1312014-10-29 18:37:51 -07001# Copyright 2014 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""Install debug symbols for specified packages.
6
7Only reinstall the debug symbols if they are not already installed to save time.
8
9The debug symbols are packaged outside of the prebuilt package in a
10.debug.tbz2 archive when FEATURES=separatedebug is set (by default on
11builders). On local machines, separatedebug is not set and the debug symbols
12are part of the prebuilt package.
13"""
14
Bertrand SIMONNET6b6a1312014-10-29 18:37:51 -070015import argparse
Alex Klein161495b2019-09-26 16:59:46 -060016import functools
Chris McDonald59650c32021-07-20 15:29:28 -060017import logging
Alex Klein161495b2019-09-26 16:59:46 -060018import multiprocessing
Bertrand SIMONNET6b6a1312014-10-29 18:37:51 -070019import os
20import pickle
Bertrand SIMONNET6b6a1312014-10-29 18:37:51 -070021import tempfile
Mike Frysingere852b072021-05-21 12:39:03 -040022import urllib.parse
Bertrand SIMONNET6b6a1312014-10-29 18:37:51 -070023
24from chromite.lib import binpkg
Mike Frysinger06a51c82021-04-06 11:39:17 -040025from chromite.lib import build_target_lib
Bertrand SIMONNET6b6a1312014-10-29 18:37:51 -070026from chromite.lib import cache
27from chromite.lib import commandline
Alex Klein161495b2019-09-26 16:59:46 -060028from chromite.lib import constants
Bertrand SIMONNET6b6a1312014-10-29 18:37:51 -070029from chromite.lib import cros_build_lib
Chris McDonald59650c32021-07-20 15:29:28 -060030from chromite.lib import gs
Bertrand SIMONNET6b6a1312014-10-29 18:37:51 -070031from chromite.lib import osutils
Gilad Arnold83233ed2015-05-08 12:12:13 -070032from chromite.lib import path_util
Mike Frysinger151f5fb2019-10-22 20:36:25 -040033from chromite.utils import outcap
Bertrand SIMONNET01394c32015-02-09 17:20:25 -080034
Chris McDonald59650c32021-07-20 15:29:28 -060035
Bertrand SIMONNET01394c32015-02-09 17:20:25 -080036if cros_build_lib.IsInsideChroot():
Alex Klein1699fab2022-09-08 08:46:06 -060037 # pylint: disable=import-error
38 from portage import create_trees
Bertrand SIMONNET6b6a1312014-10-29 18:37:51 -070039
Mike Frysinger6a2b0f22020-02-20 13:34:07 -050040
Alex Klein1699fab2022-09-08 08:46:06 -060041DEBUG_SYMS_EXT = ".debug.tbz2"
Bertrand SIMONNET6b6a1312014-10-29 18:37:51 -070042
Bertrand SIMONNET1e146e52014-12-11 14:11:56 -080043# We cache the package indexes. When the format of what we store changes,
44# bump the cache version to avoid problems.
Alex Klein1699fab2022-09-08 08:46:06 -060045CACHE_VERSION = "1"
Bertrand SIMONNET1e146e52014-12-11 14:11:56 -080046
47
Bertrand SIMONNET6b6a1312014-10-29 18:37:51 -070048class DebugSymbolsInstaller(object):
Alex Klein1699fab2022-09-08 08:46:06 -060049 """Container for enviromnent objects, needed to make multiprocessing work."""
Bertrand SIMONNET6b6a1312014-10-29 18:37:51 -070050
Alex Klein1699fab2022-09-08 08:46:06 -060051 def __init__(self, vartree, gs_context, sysroot, stdout_to_null):
52 self._vartree = vartree
53 self._gs_context = gs_context
54 self._sysroot = sysroot
55 self._stdout_to_null = stdout_to_null
56 self._capturer = outcap.OutputCapturer()
Bertrand SIMONNET6b6a1312014-10-29 18:37:51 -070057
Alex Klein1699fab2022-09-08 08:46:06 -060058 def __enter__(self):
59 if self._stdout_to_null:
60 self._capturer.StartCapturing()
Mike Frysinger151f5fb2019-10-22 20:36:25 -040061
Alex Klein1699fab2022-09-08 08:46:06 -060062 return self
Bertrand SIMONNET6b6a1312014-10-29 18:37:51 -070063
Alex Klein1699fab2022-09-08 08:46:06 -060064 def __exit__(self, _exc_type, _exc_val, _exc_tb):
65 if self._stdout_to_null:
66 self._capturer.StopCapturing()
Bertrand SIMONNET6b6a1312014-10-29 18:37:51 -070067
Alex Klein1699fab2022-09-08 08:46:06 -060068 def Install(self, cpv, url):
69 """Install the debug symbols for |cpv|.
Bertrand SIMONNET6b6a1312014-10-29 18:37:51 -070070
Alex Klein1699fab2022-09-08 08:46:06 -060071 This will install the debug symbols tarball in PKGDIR so that it can be
72 used later.
Bertrand SIMONNET6b6a1312014-10-29 18:37:51 -070073
Alex Klein1699fab2022-09-08 08:46:06 -060074 Args:
75 cpv: the cpv of the package to build. This assumes that the cpv is
76 installed in the sysroot.
77 url: url of the debug symbols archive. This could be a Google Storage url
78 or a local path.
79 """
80 archive = os.path.join(
81 self._vartree.settings["PKGDIR"], cpv + DEBUG_SYMS_EXT
82 )
83 # GsContext does not understand file:// scheme so we need to extract the
84 # path ourselves.
85 parsed_url = urllib.parse.urlsplit(url)
86 if not parsed_url.scheme or parsed_url.scheme == "file":
87 url = parsed_url.path
Bertrand SIMONNET1e146e52014-12-11 14:11:56 -080088
Alex Klein1699fab2022-09-08 08:46:06 -060089 if not os.path.isfile(archive):
90 self._gs_context.Copy(url, archive, debug_level=logging.DEBUG)
Bertrand SIMONNET6b6a1312014-10-29 18:37:51 -070091
Alex Klein1699fab2022-09-08 08:46:06 -060092 compression = cros_build_lib.CompressionDetectType(archive)
93 compressor = cros_build_lib.FindCompressor(compression)
Mike Frysinger2e169a92022-04-27 02:15:09 -040094
Alex Klein1699fab2022-09-08 08:46:06 -060095 with osutils.TempDir(sudo_rm=True) as tempdir:
96 cros_build_lib.sudo_run(
97 ["tar", "-I", compressor, "-xf", archive, "-C", tempdir],
98 debug_level=logging.DEBUG,
99 capture_output=True,
100 )
Bertrand SIMONNET6b6a1312014-10-29 18:37:51 -0700101
Alex Klein1699fab2022-09-08 08:46:06 -0600102 with open(
103 self._vartree.getpath(cpv, filename="CONTENTS"), "a"
104 ) as content_file:
105 # Merge the content of the temporary dir into the sysroot.
106 # pylint: disable=protected-access
107 link = self._vartree.dbapi._dblink(cpv)
108 link.mergeme(
109 tempdir, self._sysroot, content_file, None, "", {}, None
110 )
Bertrand SIMONNET6b6a1312014-10-29 18:37:51 -0700111
112
Bertrand SIMONNET6b6a1312014-10-29 18:37:51 -0700113def ShouldGetSymbols(cpv, vardb, remote_symbols):
Alex Klein1699fab2022-09-08 08:46:06 -0600114 """Return True if the symbols for cpv are available and are not installed.
Bertrand SIMONNET6b6a1312014-10-29 18:37:51 -0700115
Alex Klein1699fab2022-09-08 08:46:06 -0600116 We try to check if the symbols are installed before checking availability as
117 a GS request is more expensive than checking locally.
Bertrand SIMONNET6b6a1312014-10-29 18:37:51 -0700118
Alex Klein1699fab2022-09-08 08:46:06 -0600119 Args:
120 cpv: cpv of the package
121 vardb: a vartree dbapi
122 remote_symbols: a mapping from cpv to debug symbols url
Bertrand SIMONNET6b6a1312014-10-29 18:37:51 -0700123
Alex Klein1699fab2022-09-08 08:46:06 -0600124 Returns:
125 True if |cpv|'s debug symbols are not installed and are available
126 """
127 features, contents = vardb.aux_get(cpv, ["FEATURES", "CONTENTS"])
Bertrand SIMONNET6b6a1312014-10-29 18:37:51 -0700128
Alex Klein1699fab2022-09-08 08:46:06 -0600129 return (
130 "separatedebug" in features
131 and not "/usr/lib/debug/" in contents
132 and cpv in remote_symbols
133 )
Bertrand SIMONNET6b6a1312014-10-29 18:37:51 -0700134
135
136def RemoteSymbols(vartree, binhost_cache=None):
Alex Klein1699fab2022-09-08 08:46:06 -0600137 """Get the cpv to debug symbols mapping.
Bertrand SIMONNET6b6a1312014-10-29 18:37:51 -0700138
Alex Klein1699fab2022-09-08 08:46:06 -0600139 If several binhost contain debug symbols for the same cpv, keep only the
140 highest priority one.
Bertrand SIMONNET6b6a1312014-10-29 18:37:51 -0700141
Alex Klein1699fab2022-09-08 08:46:06 -0600142 Args:
143 vartree: a vartree
144 binhost_cache: a cache containing the cpv to debug symbols url for all
145 known binhosts. None if we are not caching binhosts.
Bertrand SIMONNET6b6a1312014-10-29 18:37:51 -0700146
Alex Klein1699fab2022-09-08 08:46:06 -0600147 Returns:
148 a dictionary mapping the cpv to a remote debug symbols gsurl.
149 """
150 symbols_mapping = {}
151 for binhost in vartree.settings["PORTAGE_BINHOST"].split():
152 if binhost:
153 symbols_mapping.update(ListBinhost(binhost, binhost_cache))
154 return symbols_mapping
Bertrand SIMONNET6b6a1312014-10-29 18:37:51 -0700155
156
Bertrand SIMONNET1e146e52014-12-11 14:11:56 -0800157def GetPackageIndex(binhost, binhost_cache=None):
Alex Klein1699fab2022-09-08 08:46:06 -0600158 """Get the packages index for |binhost|.
Bertrand SIMONNET1e146e52014-12-11 14:11:56 -0800159
Alex Klein1699fab2022-09-08 08:46:06 -0600160 If a cache is provided, use it to a cache remote packages index.
Bertrand SIMONNET1e146e52014-12-11 14:11:56 -0800161
Alex Klein1699fab2022-09-08 08:46:06 -0600162 Args:
163 binhost: a portage binhost, local, google storage or http.
164 binhost_cache: a cache for the remote packages index.
Bertrand SIMONNET1e146e52014-12-11 14:11:56 -0800165
Alex Klein1699fab2022-09-08 08:46:06 -0600166 Returns:
167 A PackageIndex object.
168 """
169 key = binhost.split("://")[-1]
170 key = key.rstrip("/").split("/")
Bertrand SIMONNET1e146e52014-12-11 14:11:56 -0800171
Alex Klein1699fab2022-09-08 08:46:06 -0600172 if binhost_cache and binhost_cache.Lookup(key).Exists():
173 with open(binhost_cache.Lookup(key).path, "rb") as f:
174 return pickle.load(f)
Bertrand SIMONNET1e146e52014-12-11 14:11:56 -0800175
Alex Klein1699fab2022-09-08 08:46:06 -0600176 pkgindex = binpkg.GrabRemotePackageIndex(binhost)
177 if pkgindex and binhost_cache:
178 # Only cache remote binhosts as local binhosts can change.
179 with tempfile.NamedTemporaryFile(delete=False) as temp_file:
180 pickle.dump(pkgindex, temp_file)
181 temp_file.file.close()
182 binhost_cache.Lookup(key).Assign(temp_file.name)
183 elif pkgindex is None:
184 urlparts = urllib.parse.urlsplit(binhost)
185 if urlparts.scheme not in ("file", ""):
186 # Don't fail the build on network errors. Print a warning message and
187 # continue.
188 logging.warning("Could not get package index %s", binhost)
189 return None
Bertrand SIMONNETdd66ab52015-01-08 14:48:51 -0800190
Alex Klein1699fab2022-09-08 08:46:06 -0600191 binhost = urlparts.path
192 if not os.path.isdir(binhost):
193 raise ValueError("unrecognized binhost format for %s.")
194 pkgindex = binpkg.GrabLocalPackageIndex(binhost)
Bertrand SIMONNET1e146e52014-12-11 14:11:56 -0800195
Alex Klein1699fab2022-09-08 08:46:06 -0600196 return pkgindex
Bertrand SIMONNET1e146e52014-12-11 14:11:56 -0800197
198
Bertrand SIMONNET6b6a1312014-10-29 18:37:51 -0700199def ListBinhost(binhost, binhost_cache=None):
Alex Klein1699fab2022-09-08 08:46:06 -0600200 """Return the cpv to debug symbols mapping for a given binhost.
Bertrand SIMONNET6b6a1312014-10-29 18:37:51 -0700201
Alex Klein1699fab2022-09-08 08:46:06 -0600202 List the content of the binhost to extract the cpv to debug symbols
203 mapping. If --cachebinhost is set, we cache the result to avoid the
204 cost of gsutil every time.
Bertrand SIMONNET6b6a1312014-10-29 18:37:51 -0700205
Alex Klein1699fab2022-09-08 08:46:06 -0600206 Args:
207 binhost: a portage binhost, local or on google storage.
208 binhost_cache: a cache containing mappings cpv to debug symbols url for a
209 given binhost (None if we don't want to cache).
Bertrand SIMONNET6b6a1312014-10-29 18:37:51 -0700210
Alex Klein1699fab2022-09-08 08:46:06 -0600211 Returns:
212 A cpv to debug symbols url mapping.
213 """
Bertrand SIMONNET6b6a1312014-10-29 18:37:51 -0700214
Alex Klein1699fab2022-09-08 08:46:06 -0600215 symbols = {}
216 pkgindex = GetPackageIndex(binhost, binhost_cache)
217 if pkgindex is None:
218 return symbols
219
220 for p in pkgindex.packages:
221 if p.get("DEBUG_SYMBOLS") == "yes":
222 path = p.get("PATH", p["CPV"] + ".tbz2")
223 base_url = pkgindex.header.get("URI", binhost)
224 symbols[p["CPV"]] = os.path.join(
225 base_url, path.replace(".tbz2", DEBUG_SYMS_EXT)
226 )
227
Bertrand SIMONNETdd66ab52015-01-08 14:48:51 -0800228 return symbols
229
Bertrand SIMONNET6b6a1312014-10-29 18:37:51 -0700230
231def GetMatchingCPV(package, vardb):
Alex Klein1699fab2022-09-08 08:46:06 -0600232 """Return the cpv of the installed package matching |package|.
Bertrand SIMONNET6b6a1312014-10-29 18:37:51 -0700233
Alex Klein1699fab2022-09-08 08:46:06 -0600234 Args:
235 package: package name
236 vardb: a vartree dbapi
Bertrand SIMONNET6b6a1312014-10-29 18:37:51 -0700237
Alex Klein1699fab2022-09-08 08:46:06 -0600238 Returns:
239 The cpv of the installed package whose name matchex |package|.
240 """
241 matches = vardb.match(package)
242 if not matches:
243 cros_build_lib.Die("Could not find package %s" % package)
244 if len(matches) != 1:
245 cros_build_lib.Die(
246 "Ambiguous package name: %s.\n"
247 "Matching: %s" % (package, " ".join(matches))
248 )
249 return matches[0]
Bertrand SIMONNET6b6a1312014-10-29 18:37:51 -0700250
251
Alex Klein161495b2019-09-26 16:59:46 -0600252def GetVartree(sysroot):
Alex Klein1699fab2022-09-08 08:46:06 -0600253 """Get the portage vartree.
Bertrand SIMONNET6b6a1312014-10-29 18:37:51 -0700254
Alex Klein1699fab2022-09-08 08:46:06 -0600255 This must be called in subprocesses only. The vartree is not serializable,
256 and is implemented as a singleton in portage, so it always breaks the
257 parallel call when initialized before it is called.
258 """
259 trees = create_trees(target_root=sysroot, config_root=sysroot)
260 return trees[sysroot]["vartree"]
Bertrand SIMONNET6b6a1312014-10-29 18:37:51 -0700261
Bertrand SIMONNET6b6a1312014-10-29 18:37:51 -0700262
Alex Klein161495b2019-09-26 16:59:46 -0600263def GetBinhostCache(options):
Alex Klein1699fab2022-09-08 08:46:06 -0600264 """Get and optionally clear the binhost cache."""
265 cache_dir = os.path.join(
266 path_util.FindCacheDir(), "cros_install_debug_syms-v" + CACHE_VERSION
267 )
268 if options.clearcache:
269 osutils.RmDir(cache_dir, ignore_missing=True)
Bertrand SIMONNET6b6a1312014-10-29 18:37:51 -0700270
Alex Klein1699fab2022-09-08 08:46:06 -0600271 binhost_cache = None
272 if options.cachebinhost:
273 binhost_cache = cache.DiskCache(cache_dir)
Bertrand SIMONNET6b6a1312014-10-29 18:37:51 -0700274
Alex Klein1699fab2022-09-08 08:46:06 -0600275 return binhost_cache
Bertrand SIMONNETbef192e2014-12-17 14:09:16 -0800276
Alex Klein161495b2019-09-26 16:59:46 -0600277
278def GetInstallArgs(options, sysroot):
Alex Klein1699fab2022-09-08 08:46:06 -0600279 """Resolve the packages that are to have their debug symbols installed.
Alex Klein161495b2019-09-26 16:59:46 -0600280
Alex Klein1699fab2022-09-08 08:46:06 -0600281 This function must be called in subprocesses only since it requires the
282 portage vartree.
283 See: GetVartree
Alex Klein161495b2019-09-26 16:59:46 -0600284
Alex Klein1699fab2022-09-08 08:46:06 -0600285 Returns:
286 list[(pkg, binhost_url)]
287 """
288 vartree = GetVartree(sysroot)
289 symbols_mapping = RemoteSymbols(vartree, GetBinhostCache(options))
Bertrand SIMONNET6b6a1312014-10-29 18:37:51 -0700290
Alex Klein1699fab2022-09-08 08:46:06 -0600291 if options.all:
292 to_install = vartree.dbapi.cpv_all()
293 else:
294 to_install = [
295 GetMatchingCPV(p, vartree.dbapi) for p in options.packages
296 ]
Bertrand SIMONNET6b6a1312014-10-29 18:37:51 -0700297
Alex Klein1699fab2022-09-08 08:46:06 -0600298 to_install = [
299 p
300 for p in to_install
301 if ShouldGetSymbols(p, vartree.dbapi, symbols_mapping)
302 ]
Bertrand SIMONNET6b6a1312014-10-29 18:37:51 -0700303
Alex Klein1699fab2022-09-08 08:46:06 -0600304 return [(p, symbols_mapping[p]) for p in to_install]
Alex Klein161495b2019-09-26 16:59:46 -0600305
306
307def ListInstallArgs(options, sysroot):
Alex Klein1699fab2022-09-08 08:46:06 -0600308 """List the args for the calling process."""
309 lines = ["%s %s" % arg for arg in GetInstallArgs(options, sysroot)]
310 print("\n".join(lines))
Alex Klein161495b2019-09-26 16:59:46 -0600311
312
313def GetInstallArgsList(argv):
Alex Klein1699fab2022-09-08 08:46:06 -0600314 """Get the install args from the --list reexec of the command."""
315 # Insert the --list as the first argument to prevent parsing --list as a
316 # package when a package is given.
317 cmd = [argv[0]] + ["--list"] + argv[1:]
318 result = cros_build_lib.run(cmd, capture_output=True, encoding="utf-8")
319 lines = result.stdout.splitlines()
320 return [line.split() for line in lines if line]
Alex Klein161495b2019-09-26 16:59:46 -0600321
322
323def _InstallOne(sysroot, debug, args):
Alex Klein1699fab2022-09-08 08:46:06 -0600324 """Parallelizable wrapper for the DebugSymbolsInstaller.Install method."""
325 vartree = GetVartree(sysroot)
326 gs_context = gs.GSContext(boto_file=vartree.settings["BOTO_CONFIG"])
327 with DebugSymbolsInstaller(
328 vartree, gs_context, sysroot, not debug
329 ) as installer:
330 installer.Install(*args)
Alex Klein161495b2019-09-26 16:59:46 -0600331
332
333def GetParser():
Alex Klein1699fab2022-09-08 08:46:06 -0600334 """Build the argument parser."""
335 parser = commandline.ArgumentParser(description=__doc__)
336 parser.add_argument("--board", help="Board name (required).", required=True)
337 parser.add_argument(
338 "--all",
339 action="store_true",
340 default=False,
341 help="Install the debug symbols for all installed packages",
342 )
343 parser.add_argument(
344 "packages",
345 nargs=argparse.REMAINDER,
346 help="list of packages that need the debug symbols.",
347 )
Alex Klein161495b2019-09-26 16:59:46 -0600348
Alex Klein1699fab2022-09-08 08:46:06 -0600349 advanced = parser.add_argument_group("Advanced options")
350 advanced.add_argument(
351 "--nocachebinhost",
352 dest="cachebinhost",
353 default=True,
354 action="store_false",
355 help="Don't cache the list of files contained in binhosts. "
356 "(Default: cache)",
357 )
358 advanced.add_argument(
359 "--clearcache",
360 action="store_true",
361 default=False,
362 help="Clear the binhost cache.",
363 )
364 advanced.add_argument(
365 "-j",
366 "--jobs",
367 default=multiprocessing.cpu_count(),
368 type=int,
369 help="Number of processes to run in parallel.",
370 )
371 advanced.add_argument(
372 "--list",
373 action="store_true",
374 default=False,
375 help="List the packages whose debug symbols would be installed and "
376 "their binhost path.",
377 )
Alex Klein161495b2019-09-26 16:59:46 -0600378
Alex Klein1699fab2022-09-08 08:46:06 -0600379 return parser
Alex Klein161495b2019-09-26 16:59:46 -0600380
381
382def ParseArgs(argv):
Alex Klein1699fab2022-09-08 08:46:06 -0600383 """Parse and validate arguments."""
384 parser = GetParser()
Alex Klein161495b2019-09-26 16:59:46 -0600385
Alex Klein1699fab2022-09-08 08:46:06 -0600386 options = parser.parse_args(argv)
387 if options.all and options.packages:
388 parser.error("Cannot use --all with a list of packages")
Alex Klein161495b2019-09-26 16:59:46 -0600389
Alex Klein1699fab2022-09-08 08:46:06 -0600390 options.Freeze()
Alex Klein161495b2019-09-26 16:59:46 -0600391
Alex Klein1699fab2022-09-08 08:46:06 -0600392 return options
Alex Klein161495b2019-09-26 16:59:46 -0600393
394
395def main(argv):
Alex Klein1699fab2022-09-08 08:46:06 -0600396 if not cros_build_lib.IsInsideChroot():
397 raise commandline.ChrootRequiredError(argv)
Alex Klein161495b2019-09-26 16:59:46 -0600398
Alex Klein1699fab2022-09-08 08:46:06 -0600399 options = ParseArgs(argv)
Mike Frysinger2b1fed52022-04-27 02:15:33 -0400400
Alex Klein1699fab2022-09-08 08:46:06 -0600401 cmd = [
402 os.path.join(constants.CHROMITE_BIN_DIR, "cros_install_debug_syms")
403 ] + argv
404 if osutils.IsNonRootUser():
405 cros_build_lib.sudo_run(cmd)
406 return
Bertrand SIMONNET6b6a1312014-10-29 18:37:51 -0700407
Alex Klein1699fab2022-09-08 08:46:06 -0600408 # sysroot must have a trailing / as the tree dictionary produced by
409 # create_trees in indexed with a trailing /.
410 sysroot = build_target_lib.get_default_sysroot_path(options.board) + "/"
Alex Klein161495b2019-09-26 16:59:46 -0600411
Alex Klein1699fab2022-09-08 08:46:06 -0600412 if options.list:
413 ListInstallArgs(options, sysroot)
414 return
Alex Klein161495b2019-09-26 16:59:46 -0600415
Alex Klein1699fab2022-09-08 08:46:06 -0600416 args = GetInstallArgsList(cmd)
Alex Klein161495b2019-09-26 16:59:46 -0600417
Alex Klein1699fab2022-09-08 08:46:06 -0600418 if not args:
419 logging.info("No packages found needing debug symbols.")
420 return
Alex Klein161495b2019-09-26 16:59:46 -0600421
Alex Klein1699fab2022-09-08 08:46:06 -0600422 # Partial to simplify the arguments to parallel since the first two are the
423 # same for every call.
424 partial_install = functools.partial(_InstallOne, sysroot, options.debug)
425 with multiprocessing.Pool(processes=options.jobs) as pool:
426 pool.map(partial_install, args)
Bertrand SIMONNET6b6a1312014-10-29 18:37:51 -0700427
Alex Klein1699fab2022-09-08 08:46:06 -0600428 logging.debug("installation done, updating packages index file")
429 packages_dir = os.path.join(sysroot, "packages")
430 packages_file = os.path.join(packages_dir, "Packages")
431 # binpkg will set DEBUG_SYMBOLS automatically if it detects the debug symbols
432 # in the packages dir.
433 pkgindex = binpkg.GrabLocalPackageIndex(packages_dir)
434 with open(packages_file, "w") as p:
435 pkgindex.Write(p)