diff --git a/build-userland b/build-userland index 5f06511..d7545ea 100755 --- a/build-userland +++ b/build-userland @@ -40,14 +40,6 @@ Indicate that all packages from --has-package are available. help='''\ Place build output inside soure tree to conveniently run it, especially when building with the host toolchain. -''', - ) - self.add_argument( - '--target-relative-cwd', - default=False, - help='''\ -Treat targets as relative to the current working directory. If the current working -directory is outside of userland/, this has no effect. ''', ) self.add_argument( @@ -133,54 +125,35 @@ Default: build all examples that have their package dependencies met, e.g.: ) return ret - def _get_cwd(self): - cwd = os.path.abspath(os.getcwd()) - if cwd.startswith(self.env['userland_source_dir']): - return cwd - else: - return self.env['userland_source_dir'] + def _walk_targets(self, exts): + ''' + Resolve userland input targets, and walk them if directories. - def _get_targets(self): + Ignore the input extension of targets, and select only files + with the given extensions exts. + + An empty extension indicates that directories will also be chosen. ''' - Resolve target_relative_cwd and default targets. - ''' - if self.env['_args_given']['targets']: + if self.env['targets']: targets = self.env['targets'] - if self.env['target_relative_cwd']: - cwd = self._get_cwd() - for target in targets: - yield os.path.join(cwd, target) - else: - for target in targets: - yield target else: - if self.env['target_relative_cwd']: - yield self._get_cwd() - else: - yield self.env['userland_source_dir'] - - def _walk_targets(self): - ''' - Walk existing directories and files pointed to by the targets - from the command line from under the userland/ source tree. - - This may include outputs of in-tree builds. - - File extensions are ignored, e.g.: - - c/hello - - will find both: - - c/hello.c - c/hello.out - ''' - for target in self._get_targets(): - target = self.resolve_userland_source(target) - noext, ext = os.path.splitext(filename) - - for path, in_dirnames, in_filenames in self.sh.walk(target): - yield path, in_dirnames, in_filenames + targets = [self.env['userland_source_dir']] + for target in targets: + resolved_targets = self.resolve_source_tree( + target, + exts + [''], + self.env['userland_source_dir'] + ) + for resolved_target in resolved_targets: + for path, dirnames, filenames in self.sh.walk(resolved_target): + dirnames.sort() + filenames = [ + filename for filename in filenames + if os.path.splitext(filename)[1] in exts + ] + filenames.sort() + for filename in filenames: + yield path, dirnames, filenames def build(self): build_dir = self.get_build_dir() @@ -260,9 +233,9 @@ Default: build all examples that have their package dependencies met, e.g.: ) as thread_pool: class ExitLoop(Exception): pass try: - for path, in_dirnames, in_filenames in self._walk_targets(): - in_dirnames.sort() - in_filenames.sort() + for path, in_dirnames, in_filenames in self._walk_targets( + self.env['userland_in_exts'] + ): path_abs = os.path.abspath(path) dirpath_relative_root = path_abs[rootdir_abs_len + 1:] dirpath_relative_root_components = dirpath_relative_root.split(os.sep) @@ -377,6 +350,7 @@ Default: build all examples that have their package dependencies met, e.g.: raise ExitLoop() except ExitLoop: pass + error = thread_pool.get_error() if error is not None: print(error) return 1 @@ -390,15 +364,11 @@ Default: build all examples that have their package dependencies met, e.g.: def clean(self): if self.env['in_tree']: - for path, dirnames, filenames in self._walk_targets(): - filenames.sort() - dirnames.sort() + for path, dirnames, filenames in self._walk_targets( + self.env['userland_out_exts'] + ): for filename in filenames: - noext, ext = os.path.splitext(filename) - for out_ext in self.env['userland_out_exts']: - out_path = os.path.join(path, noext + out_ext) - if os.path.exists(out_path): - self.sh.rmrf(out_path) + self.sh.rmrf(os.path.join(path, filename)) else: self.sh.rmrf(self.get_build_dir()) diff --git a/build-userland-in-tree b/build-userland-in-tree index 3b1e619..754d3e1 100755 --- a/build-userland-in-tree +++ b/build-userland-in-tree @@ -24,7 +24,7 @@ https://github.com/cirosantilli/linux-kernel-module-cheat#userland-setup-getting 'gcc_which': 'host', 'has_all_packages': True, 'in_tree': True, - 'target_relative_cwd': True, + 'targets': ['.'], } ) diff --git a/common.py b/common.py index 2b1c9b3..3c561ba 100644 --- a/common.py +++ b/common.py @@ -12,6 +12,7 @@ import json import math import os import platform +import pathlib import re import shutil import signal @@ -1121,7 +1122,7 @@ lunch aosp_{}-eng ] ) - def resolve_source(self, in_path, magic_in_dir, exts): + def resolve_source_tree(self, in_path, exts, source_tree_root): ''' Convert a convenient shorthand user input string to paths of existing files in the source tree. @@ -1162,24 +1163,24 @@ lunch aosp_{}-eng files and directories: e.g. if you had both a file arch.c and a directory arch, and exts=['', '.c'], then both would get matched. ''' - if os.path.isabs(in_path): - return in_path - else: - paths = [ - os.path.join(magic_in_dir, in_path), - os.path.join( - magic_in_dir, - os.path.relpath(in_path, magic_in_dir), + in_path = os.path.abspath(in_path) + source_tree_root = os.path.abspath(source_tree_root) + if not in_path.startswith(source_tree_root): + raise Exception( + 'The input path {} is not inside the source directory {}'.format( + in_path, + source_tree_root ) - ] - for path in paths: - name, ext = os.path.splitext(path) - for try_ext in exts: - path = name + try_ext - if os.path.exists(path): - return path - if not self.env['dry_run']: - raise Exception('No file not found for input: ' + in_path) + ) + result = [] + name, ext = os.path.splitext(in_path) + for try_ext in exts: + try_path = name + try_ext + if os.path.exists(try_path): + result.append(try_path) + if not result: + raise Exception('No file not found for input: ' + in_path) + return result def resolve_executable(self, in_path, magic_in_dir, magic_out_dir, out_exts): if os.path.isabs(in_path): @@ -1212,13 +1213,6 @@ lunch aosp_{}-eng [self.env['userland_build_ext']], ) - def resolve_userland_source(self, path): - return self.resolve_source( - path, - self.env['userland_source_dir'], - self.env['userland_in_exts'] - ) - def setup(self): ''' Similar to timed_main, but gets run only once for all --arch and --emulator, diff --git a/test-build-userland b/test-build-userland index 1af5ae3..a248853 100755 --- a/test-build-userland +++ b/test-build-userland @@ -1,42 +1,52 @@ #!/usr/bin/env bash +# Quick sanity check that userland target resoltion at least does not blow up. + set -eux ./build-userland ./build-userland --clean -./build-userland c -./build-userland --clean ./build-userland userland/c -./build-userland --clean +./build-userland --clean userland/c ./build-userland userland/c/hello -./build-userland --clean +./build-userland --clean userland/c/hello +./build-userland userland/c/hello. +./build-userland --clean userland/c/hello. ./build-userland userland/c/hello.c -./build-userland --clean +./build-userland --clean userland/c/hello.c ./build-userland userland/c/hello.out -./build-userland --clean +./build-userland --clean userland/c/hello.out +./build-userland "$(pwd)/userland/c/hello.out" +./build-userland --clean "$(pwd)/userland/c/hello.out" ./build-userland --in-tree ./build-userland --in-tree --clean -./build-userland --in-tree c -./build-userland --in-tree --clean ./build-userland --in-tree userland/c -./build-userland --in-tree --clean +./build-userland --in-tree --clean userland/c ./build-userland --in-tree userland/c/hello -./build-userland --in-tree --clean +./build-userland --in-tree --clean userland/c/hello +./build-userland --in-tree userland/c/hello. +./build-userland --in-tree --clean userland/c/hello. ./build-userland --in-tree userland/c/hello.c -./build-userland --in-tree --clean +./build-userland --in-tree --clean userland/c/hello.c ./build-userland --in-tree userland/c/hello.out +./build-userland --in-tree --clean userland/c/hello.out +./build-userland --in-tree "$(pwd)/userland/c/hello.out" +./build-userland --in-tree --clean "$(pwd)/userland/c/hello.out" ./build-userland --in-tree --clean cd userland - -./build-userland --in-tree -./build-userland --in-tree --clean -./build-userland --in-tree c -./build-userland --in-tree --clean -./build-userland --in-tree c/hello -./build-userland --in-tree --clean -./build-userland --in-tree c/hello.c -./build-userland --in-tree --clean -./build-userland --in-tree c/hello.out -./build-userland --in-tree --clean +./build +./build --clean +./build c +./build --clean c +./build c/hello +./build --clean c/hello +./build c/hello. +./build --clean c/hello. +./build c/hello.c +./build --clean c/hello.c +./build c/hello.out +./build --clean c/hello.out +./build "$(pwd)/c/hello.out" +./build --clean "$(pwd)/c/hello.out" diff --git a/thread_pool.py b/thread_pool.py index 9f22e6a..8903ab9 100644 --- a/thread_pool.py +++ b/thread_pool.py @@ -84,6 +84,9 @@ class ThreadPool: def __exit__(self, type, value, traceback): self.join() + def get_error(self): + return self.error_output + def submit(self, work): ''' Submit work. Block if there is already enough work scheduled (~nthreads). @@ -117,6 +120,7 @@ class ThreadPool: out = self.func(**work) except Exception as e: exception = e + out = None try: handle_output_return = self.handle_output(work, out, exception) except Exception as e: