blob: 243b3d7c300155204d9d6ae63c7cd85067a18b43 [file] [log] [blame]
# Copyright 2015 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Utilities to create sysroots."""
from __future__ import print_function
import multiprocessing
import os
from chromite.cbuildbot import constants
from chromite.lib import osutils
from chromite.lib import portage_util
from chromite.lib import toolchain
_PORTAGE_WRAPPER_TEMPLATE = """#!/bin/sh
# If we try to use sudo when the sandbox is active, we get ugly warnings that
# just confuse developers. Disable the sandbox in this case by rexecing.
if [ "${{SANDBOX_ON}}" = "1" ]; then
SANDBOX_ON=0 exec "$0" "$@"
else
unset LD_PRELOAD
fi
export CHROMEOS_ROOT="{source_root}"
export CHOST="{chost}"
export PORTAGE_CONFIGROOT="{sysroot}"
export SYSROOT="{sysroot}"
if [ -z "$PORTAGE_USERNAME" ]; then
export PORTAGE_USERNAME=$(basename "${{HOME}}")
fi
export ROOT="{sysroot}"
exec sudo -E {command} "$@"
"""
_BOARD_WRAPPER_TEMPLATE = """#!/bin/sh
exec {command} --board="{board}" "$@"
"""
_PKGCONFIG_WRAPPER_TEMPLATE = """#!/bin/bash
PKG_CONFIG_LIBDIR=$(printf '%s:' "{sysroot}"/usr/*/pkgconfig)
export PKG_CONFIG_LIBDIR
export PKG_CONFIG_SYSROOT_DIR="{sysroot}"
exec pkg-config "$@"
"""
_wrapper_dir = '/usr/local/bin'
_CONFIGURATION_PATH = 'etc/make.conf.board_setup'
def CreateWrapper(command_name, template, **kwargs):
"""Creates a wrapper from a given template.
Args:
command_name: name of the wrapper.
template: wrapper template.
kwargs: fields to be set in the template.
"""
wrapper_path = os.path.join(_wrapper_dir, command_name)
osutils.WriteFile(wrapper_path, template.format(**kwargs), makedirs=True)
os.chown(wrapper_path, 0, 0)
os.chmod(wrapper_path, 0o755)
def GetConfigFilePath(sysroot):
"""Returns the path to the configuration file for |sysroot|.
sysroot: Path to the sysroot.
"""
return os.path.join(sysroot, _CONFIGURATION_PATH)
def GetStandardField(sysroot, field):
"""Returns the value of a standard field.
Args:
sysroot: Path to the sysroot.
field: Field from the standard configuration file to get.
"""
return osutils.SourceEnvironment(GetConfigFilePath(sysroot),
[field], multiline=True).get(field)
def CreateAllWrappers(sysroot, chost=None, friendly_name=None):
"""Creates all the wrappers for a given sysroot.
Creates all portage tools wrappers, plus wrappers for gdb, cros_workon and
pkg-config.
Args:
sysroot: path to the sysroot.
chost: toolchain to use. Defaults to the sysroot's CHOST.
friendly_name: suffix to add to the commands. Defaults to the last component
of |sysroot|.
"""
if chost is None:
chost = GetStandardField(sysroot, 'CHOST')
board = friendly_name or os.path.basename(sysroot)
for cmd in ('ebuild', 'eclean', 'emaint', 'equery', 'portageq', 'qcheck',
'qdepends', 'qfile', 'qlist', 'qmerge', 'qsize'):
CreateWrapper('%s-%s' % (cmd, board), _PORTAGE_WRAPPER_TEMPLATE,
sysroot=sysroot, chost=chost, command=cmd,
source_root=constants.SOURCE_ROOT)
CreateWrapper('emerge-%s' % board, _PORTAGE_WRAPPER_TEMPLATE,
sysroot=sysroot, chost=chost,
command='emerge --root-deps',
source_root=constants.SOURCE_ROOT)
CreateWrapper('cros_workon-%s' % board, _BOARD_WRAPPER_TEMPLATE,
board=board, command='cros_workon')
CreateWrapper('cros_gdb-%s' % board, _BOARD_WRAPPER_TEMPLATE,
board=board, command='gdb')
CreateWrapper('pkg-config-%s' % board, _PKGCONFIG_WRAPPER_TEMPLATE,
sysroot=sysroot)
# Create a link to the debug symbols in the chroot so that gdb can detect
# them.
debug_symlink = os.path.join('/usr/lib/debug', sysroot.lstrip('/'))
sysroot_debug = os.path.join(sysroot, 'usr/lib/debug')
osutils.SafeMakedirs(os.path.dirname(debug_symlink))
osutils.SafeMakedirs(sysroot_debug)
# If the symlink already exists, recreate it to be sure.
if os.path.islink(debug_symlink):
os.unlink(debug_symlink)
os.symlink(sysroot_debug, debug_symlink)
def _DictToKeyValue(dictionary):
"""Formats dictionary in to a key=value string.
Args:
dictionary: a python dictionary.
"""
output = []
for key in sorted(dictionary.keys()):
output.append('%s="%s"' % (key, dictionary[key]))
return '\n'.join(output)
def GenerateBoardConfig(sysroot, board):
"""Generate the sysroot configuration for a given board.
Args:
sysroot: path to the sysroot.
board: board name to use to generate the configuration.
"""
config = {}
toolchains = toolchain.GetToolchainsForBoard(board)
config['CHOST'] = toolchain.FilterToolchains(toolchains, 'default',
True).keys()[0]
config['ARCH'] = toolchain.GetArchForTarget(config['CHOST'])
# Compute the overlay list.
overlay_list = portage_util.FindOverlays(constants.BOTH_OVERLAYS, board)
prefix = os.path.join(constants.SOURCE_ROOT, 'src', 'third_party')
config['BOARD_OVERLAY'] = '\n'.join([o for o in overlay_list
if not o.startswith(prefix)])
config['MAKEOPTS'] = '-j%s' % str(multiprocessing.cpu_count())
config['BOARD_USE'] = board
config['ROOT'] = sysroot + '/'
config['PKG_CONFIG'] = 'pkg-config-%s' % board
header = "# Created by cros_sysroot_utils from --board=%s." % board
return '\n'.join((header, _DictToKeyValue(config)))
def GenerateBrickConfig(sysroot, brick):
"""Generate the sysroot configuration for a given brick.
Args:
sysroot: path to the sysroot.
brick: brick to generate the configuration for.
"""
config = {}
# TODO(bsimonnet): get toolchain from config.json.
toolchains = toolchain.GetToolchainsForBrick(brick.brick_locator)
config['CHOST'] = toolchain.FilterToolchains(toolchains, 'default',
True).keys()[0]
config['ARCH'] = toolchain.GetArchForTarget(config['CHOST'])
config['BOARD_OVERLAY'] = '\n'.join([b.OverlayDir()
for b in brick.BrickStack()])
config['MAKEOPTS'] = '-j%s' % str(multiprocessing.cpu_count())
config['ROOT'] = sysroot + '/'
config['PKG_CONFIG'] = 'pkg-config-%s' % brick.FriendlyName()
header = ("# Created by cros_sysroot_utils from --brick=%s."
% brick.brick_locator)
return '\n'.join((header, _DictToKeyValue(config)))
def WriteSysrootConfig(sysroot, config):
"""Writes the configuration in |sysroot|.
Args:
sysroot: path to the sysroot.
config: configuration to use.
"""
path = os.path.join(sysroot, _CONFIGURATION_PATH)
osutils.WriteFile(path, config, makedirs=True)