Commit 1e4687aa authored by Alper Nebi Yasak's avatar Alper Nebi Yasak Committed by Simon Glass
Browse files

binman: Use target-specific tools when cross-compiling

Currently, binman always runs the compile tools like cc, objcopy, strip,
etc. using their literal name. Instead, this patch makes it use the
target-specific versions by default, derived from the tool-specific
environment variables (CC, OBJCOPY, STRIP, etc.) or from the
CROSS_COMPILE environment variable.

For example, the u-boot-elf etype directly uses 'strip'. Trying to run
the tests with 'CROSS_COMPILE=i686-linux-gnu- binman test' on an arm64
host results in the '097_elf_strip.dts' test to fail as the arm64
version of 'strip' can't understand the format of the x86 ELF file.

This also adjusts some command.Output() calls that caused test errors or
failures to use the target versions of the tools they call. After this,
patch, an arm64 host can run all tests with no errors or failures using
a correct CROSS_COMPILE value.
Signed-off-by: default avatarAlper Nebi Yasak <>
Reviewed-by: Simon Glass's avatarSimon Glass <>
parent 5ac76878
......@@ -234,8 +234,10 @@ SECTIONS
# text section at the start
# -m32: Build for 32-bit x86
# -T...: Specifies the link script, which sets the start address
stdout = command.Output('cc', '-static', '-nostdlib', '-Wl,--build-id=none',
'-m32','-T', lds_file, '-o', elf_fname, s_file)
cc, args = tools.GetTargetCompileTool('cc')
args += ['-static', '-nostdlib', '-Wl,--build-id=none', '-m32', '-T',
lds_file, '-o', elf_fname, s_file]
stdout = command.Output(cc, *args)
def DecodeElf(data, location):
......@@ -186,7 +186,9 @@ class TestElf(unittest.TestCase):
# Make an Elf file and then convert it to a fkat binary file. This
# should produce the original data.
elf.MakeElf(elf_fname, expected_text, expected_data)
stdout = command.Output('objcopy', '-O', 'binary', elf_fname, bin_fname)
objcopy, args = tools.GetTargetCompileTool('objcopy')
args += ['-O', 'binary', elf_fname, bin_fname]
stdout = command.Output(objcopy, *args)
with open(bin_fname, 'rb') as fd:
data =
self.assertEqual(expected_text + expected_data, data)
......@@ -68,22 +68,23 @@ def EnsureCompiled(fname, tmpdir=None, capture_stderr=False):
search_paths = [os.path.join(os.getcwd(), 'include')]
root, _ = os.path.splitext(fname)
args = ['-E', '-P', '-x', 'assembler-with-cpp', '-D__ASSEMBLY__']
cc, args = tools.GetTargetCompileTool('cc')
args += ['-E', '-P', '-x', 'assembler-with-cpp', '-D__ASSEMBLY__']
args += ['-Ulinux']
for path in search_paths:
args.extend(['-I', path])
args += ['-o', dts_input, fname]
command.Run('cc', *args)
command.Run(cc, *args)
# If we don't have a directory, put it in the tools tempdir
search_list = []
for path in search_paths:
search_list.extend(['-i', path])
args = ['-I', 'dts', '-o', dtb_output, '-O', 'dtb',
dtc, args = tools.GetTargetCompileTool('dtc')
args += ['-I', 'dts', '-o', dtb_output, '-O', 'dtb',
'-W', 'no-unit_address_vs_reg']
dtc = os.environ.get('DTC') or 'dtc'
command.Run(dtc, *args, capture_stderr=capture_stderr)
return dtb_output
......@@ -188,6 +188,77 @@ def PathHasFile(path_spec, fname):
return True
return False
def GetTargetCompileTool(name, cross_compile=None):
"""Get the target-specific version for a compile tool
This first checks the environment variables that specify which
version of the tool should be used (e.g. ${CC}). If those aren't
specified, it checks the CROSS_COMPILE variable as a prefix for the
tool with some substitutions (e.g. "${CROSS_COMPILE}gcc" for cc).
The following table lists the target-specific versions of the tools
this function resolves to:
Compile Tool | First choice | Second choice
as | ${AS} | ${CROSS_COMPILE}as
ld | ${LD} | ${CROSS_COMPILE}ld.bfd
| | or ${CROSS_COMPILE}ld
cc | ${CC} | ${CROSS_COMPILE}gcc
cpp | ${CPP} | ${CROSS_COMPILE}gcc -E
c++ | ${CXX} | ${CROSS_COMPILE}g++
ar | ${AR} | ${CROSS_COMPILE}ar
nm | ${NM} | ${CROSS_COMPILE}nm
ldr | ${LDR} | ${CROSS_COMPILE}ldr
strip | ${STRIP} | ${CROSS_COMPILE}strip
objcopy | ${OBJCOPY} | ${CROSS_COMPILE}objcopy
objdump | ${OBJDUMP} | ${CROSS_COMPILE}objdump
dtc | ${DTC} | (no CROSS_COMPILE version)
name: Command name to run
target_name: Exact command name to run instead
extra_args: List of extra arguments to pass
env = dict(os.environ)
target_name = None
extra_args = []
if name in ('as', 'ld', 'cc', 'cpp', 'ar', 'nm', 'ldr', 'strip',
'objcopy', 'objdump', 'dtc'):
target_name, *extra_args = env.get(name.upper(), '').split(' ')
elif name == 'c++':
target_name, *extra_args = env.get('CXX', '').split(' ')
if target_name:
return target_name, extra_args
if cross_compile is None:
cross_compile = env.get('CROSS_COMPILE', '')
if not cross_compile:
return name, []
if name in ('as', 'ar', 'nm', 'ldr', 'strip', 'objcopy', 'objdump'):
target_name = cross_compile + name
elif name == 'ld':
if Run(cross_compile + 'ld.bfd', '-v'):
target_name = cross_compile + 'ld.bfd'
target_name = cross_compile + 'ld'
elif name == 'cc':
target_name = cross_compile + 'gcc'
elif name == 'cpp':
target_name = cross_compile + 'gcc'
extra_args = ['-E']
elif name == 'c++':
target_name = cross_compile + 'g++'
target_name = name
return target_name, extra_args
def Run(name, *args, **kwargs):
"""Run a tool with some arguments
......@@ -198,16 +269,22 @@ def Run(name, *args, **kwargs):
name: Command name to run
args: Arguments to the tool
for_target: False to run the command as-is, without resolving it
to the version for the compile target
CommandResult object
binary = kwargs.get('binary')
for_target = kwargs.get('for_target', True)
env = None
if tool_search_paths:
env = dict(os.environ)
env['PATH'] = ':'.join(tool_search_paths) + ':' + env['PATH']
if for_target:
name, extra_args = GetTargetCompileTool(name)
args = tuple(extra_args) + args
all_args = (name,) + args
result = command.RunPipe([all_args], capture=True, capture_stderr=True,
env=env, raise_on_error=False, binary=binary)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment