1 # 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.
5 """Unittest-only utility functions library."""
7 from __future__ import print_function
11 from chromite.lib import cros_build_lib
12 from chromite.lib import osutils
15 class BuildELFError(Exception):
16 """Generic error building an ELF file."""
19 def BuildELF(filename, defined_symbols=None, undefined_symbols=None,
20 used_libs=None, executable=False, static=False):
21 """Builds a dynamic ELF with the provided import and exports.
23 Compiles and links a dynamic program that exports some functions, as libraries
24 do, and requires some symbols from other libraries. Dependencies shoud live
25 in the same directory as the result. This function
28 filename: The output filename where the ELF is created.
29 defined_symbols: The list of symbols this ELF exports.
30 undefined_symbols: The list of symbols this ELF requires from other ELFs.
31 used_libs: The list of libraries this ELF loads dynamically, including only
32 the name of the library. For example, 'bz2' rather than 'libbz2.so.1.0'.
33 executable: Whether the file has a main() function.
34 static: Whether the file is statically linked (implies executable=True).
36 if defined_symbols is None:
38 if undefined_symbols is None:
39 undefined_symbols = []
42 if static and not executable:
43 raise ValueError('static requires executable to be True.')
45 source = ''.join('void %s();\n' % sym for sym in undefined_symbols)
47 void __defined_symbols(const char*) __attribute__ ((visibility ("hidden")));
48 void __defined_symbols(const char* sym) {
51 """ % ('\n '.join('%s();' % sym for sym in undefined_symbols))
54 void %s() __attribute__ ((visibility ("default")));
55 void %s() { __defined_symbols("%s"); }
56 """ % (sym, sym, sym) for sym in defined_symbols)
61 __defined_symbols("main");
65 source_fn = filename + '_tmp.c'
66 osutils.WriteFile(source_fn, source)
68 outdir = os.path.dirname(filename)
69 cmd = ['gcc', '-o', filename, source_fn]
71 cmd += ['-shared', '-fPIC']
74 cmd += ['-L.', '-Wl,-rpath=./']
75 cmd += ['-l%s' % lib for lib in used_libs]
77 cros_build_lib.RunCommand(
78 cmd, cwd=outdir, redirect_stdout=True, redirect_stderr=True,
80 except cros_build_lib.RunCommandError, e:
81 raise BuildELFError('%s\n%s' % (e.message, e.result.error))