#!/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( '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 self.env['copy_overlay']: 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()