Files
linux-kernel-module-cheat/build-userland
Ciro Santilli 六四事件 法轮功 6936bd6ba9 how to update gcc
Automatically add extra remotes from ./build.
2019-10-31 00:00:00 +00:00

136 lines
4.9 KiB
Python
Executable File

#!/usr/bin/env python3
import os
import shlex
import subprocess
import threading
from shell_helpers import LF
import common
import thread_pool
class Main(common.BuildCliFunction):
def __init__(self, *args, **kwargs):
if not 'description' in kwargs:
kwargs['description'] = '''\
Build our compiled userland examples.
'''
if not 'defaults' in kwargs:
kwargs['defaults'] = {}
if not 'mode' in kwargs['defaults']:
kwargs['defaults']['mode'] = 'userland'
super().__init__(*args, **kwargs)
self._add_argument('--ccflags')
self._add_argument('--force-rebuild')
self._add_argument('--optimization-level')
self.add_argument(
'--out-rootfs-overlay-dir-prefix',
default='',
help='''\
Place the output files inside the image within this additional prefix.
This is mostly useful to place different versions of binaries with different
build parameters inside image to compare them. See:
* https://cirosantilli.com/linux-kernel-module-cheat#update-the-toolchain
* https://cirosantilli.com/linux-kernel-module-cheat#out_rootfs_overlay_dir
'''
)
self.add_argument(
'targets',
default=[],
help='''\
Select to build only the given userland programs, or all programs under
the given directories.
Default: build all.
Must point to either sources or directories under userland/, or to LKMC
toplevel which is a synonym for userland/.
Default: build all examples that have their package dependencies met, e.g.:
- userland/arch/ programs only build if the target arch matches
- an OpenBLAS example can only be built if the target root filesystem
has the OpenBLAS libraries and headers installed, which you must inform
with --package
''',
nargs='*',
)
def build(self):
build_dir = self.get_build_dir()
cc_flags = [
'-I', self.env['root_dir'], LF,
'-O{}'.format(self.env['optimization_level']), LF,
] + self.sh.shlex_split(self.env['ccflags'])
if self.env['static']:
cc_flags.extend(['-static', LF])
extra_obj_lkmc_common = os.path.join(
build_dir,
self.env['common_basename_noext'] + self.env['obj_ext']
)
self._build_one(
in_path=self.env['common_c'],
out_path=extra_obj_lkmc_common,
cc_flags=cc_flags,
extra_deps=[self.env['common_h']],
link=False,
)
with thread_pool.ThreadPool(
self._build_one,
nthreads=self.env['nproc'],
submit_raise_exit=self.env['quit_on_fail'],
) as my_thread_pool:
for target in self.env['targets']:
for path, in_dirnames, in_filenames in self.sh.walk(target):
for in_filename in in_filenames:
in_ext = os.path.splitext(in_filename)[1]
if not in_ext in self.env['build_in_exts']:
continue
in_path = os.path.join(path, in_filename)
my_thread_pool.submit({
'cc_flags': cc_flags,
'extra_objs_lkmc_common': [extra_obj_lkmc_common],
'in_path': in_path,
'out_path': self.resolve_userland_executable(in_path),
})
exit_status = self._handle_thread_pool_errors(my_thread_pool)
if exit_status != 0:
return exit_status
if not self.env['in_tree']:
self.sh.copy_dir_if_update(
srcdir=build_dir,
destdir=os.path.join(
self.env['out_rootfs_overlay_lkmc_dir'],
self.env['out_rootfs_overlay_dir_prefix']
),
filter_ext=self.env['userland_executable_ext'],
)
return exit_status
def clean(self):
if self.env['in_tree']:
for target in self.env['targets']:
if os.path.exists(target):
if os.path.isfile(target):
self.sh.rmrf(self.resolve_userland_executable(target))
else:
for path, dirnames, filenames in self.sh.walk(target):
for filename in filenames:
if os.path.splitext(filename)[1] in self.env['userland_out_exts']:
self.sh.rmrf(os.path.join(path, filename))
else:
for target in self.env['targets']:
self.sh.rmrf(self.resolve_userland_executable(target))
def get_build_dir(self):
return self.env['userland_build_dir']
def setup_one(self):
self.env['targets'] = self.resolve_targets(
[self.env['userland_source_dir']],
self.env['targets']
)
if __name__ == '__main__':
Main().cli()