userland: maybe it really works

This commit is contained in:
Ciro Santilli 六四事件 法轮功
2019-05-05 00:00:00 +00:00
parent 0c9afcf9b6
commit bbdf6cdc06
5 changed files with 89 additions and 111 deletions

View File

@@ -40,14 +40,6 @@ Indicate that all packages from --has-package are available.
help='''\ help='''\
Place build output inside soure tree to conveniently run it, especially when Place build output inside soure tree to conveniently run it, especially when
building with the host toolchain. 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( self.add_argument(
@@ -133,54 +125,35 @@ Default: build all examples that have their package dependencies met, e.g.:
) )
return ret return ret
def _get_cwd(self): def _walk_targets(self, exts):
cwd = os.path.abspath(os.getcwd()) '''
if cwd.startswith(self.env['userland_source_dir']): Resolve userland input targets, and walk them if directories.
return cwd
else:
return self.env['userland_source_dir']
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['targets']:
'''
if self.env['_args_given']['targets']:
targets = 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: else:
if self.env['target_relative_cwd']: targets = [self.env['userland_source_dir']]
yield self._get_cwd() for target in targets:
else: resolved_targets = self.resolve_source_tree(
yield self.env['userland_source_dir'] target,
exts + [''],
def _walk_targets(self): self.env['userland_source_dir']
''' )
Walk existing directories and files pointed to by the targets for resolved_target in resolved_targets:
from the command line from under the userland/ source tree. for path, dirnames, filenames in self.sh.walk(resolved_target):
dirnames.sort()
This may include outputs of in-tree builds. filenames = [
filename for filename in filenames
File extensions are ignored, e.g.: if os.path.splitext(filename)[1] in exts
]
c/hello filenames.sort()
for filename in filenames:
will find both: yield path, dirnames, filenames
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
def build(self): def build(self):
build_dir = self.get_build_dir() 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: ) as thread_pool:
class ExitLoop(Exception): pass class ExitLoop(Exception): pass
try: try:
for path, in_dirnames, in_filenames in self._walk_targets(): for path, in_dirnames, in_filenames in self._walk_targets(
in_dirnames.sort() self.env['userland_in_exts']
in_filenames.sort() ):
path_abs = os.path.abspath(path) path_abs = os.path.abspath(path)
dirpath_relative_root = path_abs[rootdir_abs_len + 1:] dirpath_relative_root = path_abs[rootdir_abs_len + 1:]
dirpath_relative_root_components = dirpath_relative_root.split(os.sep) 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() raise ExitLoop()
except ExitLoop: except ExitLoop:
pass pass
error = thread_pool.get_error()
if error is not None: if error is not None:
print(error) print(error)
return 1 return 1
@@ -390,15 +364,11 @@ Default: build all examples that have their package dependencies met, e.g.:
def clean(self): def clean(self):
if self.env['in_tree']: if self.env['in_tree']:
for path, dirnames, filenames in self._walk_targets(): for path, dirnames, filenames in self._walk_targets(
filenames.sort() self.env['userland_out_exts']
dirnames.sort() ):
for filename in filenames: for filename in filenames:
noext, ext = os.path.splitext(filename) self.sh.rmrf(os.path.join(path, 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)
else: else:
self.sh.rmrf(self.get_build_dir()) self.sh.rmrf(self.get_build_dir())

View File

@@ -24,7 +24,7 @@ https://github.com/cirosantilli/linux-kernel-module-cheat#userland-setup-getting
'gcc_which': 'host', 'gcc_which': 'host',
'has_all_packages': True, 'has_all_packages': True,
'in_tree': True, 'in_tree': True,
'target_relative_cwd': True, 'targets': ['.'],
} }
) )

View File

@@ -12,6 +12,7 @@ import json
import math import math
import os import os
import platform import platform
import pathlib
import re import re
import shutil import shutil
import signal 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 Convert a convenient shorthand user input string to paths of existing files
in the source tree. 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, 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. and exts=['', '.c'], then both would get matched.
''' '''
if os.path.isabs(in_path): in_path = os.path.abspath(in_path)
return in_path source_tree_root = os.path.abspath(source_tree_root)
else: if not in_path.startswith(source_tree_root):
paths = [ raise Exception(
os.path.join(magic_in_dir, in_path), 'The input path {} is not inside the source directory {}'.format(
os.path.join( in_path,
magic_in_dir, source_tree_root
os.path.relpath(in_path, magic_in_dir),
) )
] )
for path in paths: result = []
name, ext = os.path.splitext(path) name, ext = os.path.splitext(in_path)
for try_ext in exts: for try_ext in exts:
path = name + try_ext try_path = name + try_ext
if os.path.exists(path): if os.path.exists(try_path):
return path result.append(try_path)
if not self.env['dry_run']: if not result:
raise Exception('No file not found for input: ' + in_path) 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): def resolve_executable(self, in_path, magic_in_dir, magic_out_dir, out_exts):
if os.path.isabs(in_path): if os.path.isabs(in_path):
@@ -1212,13 +1213,6 @@ lunch aosp_{}-eng
[self.env['userland_build_ext']], [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): def setup(self):
''' '''
Similar to timed_main, but gets run only once for all --arch and --emulator, Similar to timed_main, but gets run only once for all --arch and --emulator,

View File

@@ -1,42 +1,52 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# Quick sanity check that userland target resoltion at least does not blow up.
set -eux set -eux
./build-userland ./build-userland
./build-userland --clean ./build-userland --clean
./build-userland c
./build-userland --clean
./build-userland userland/c ./build-userland userland/c
./build-userland --clean ./build-userland --clean userland/c
./build-userland userland/c/hello ./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 userland/c/hello.c
./build-userland --clean ./build-userland --clean userland/c/hello.c
./build-userland userland/c/hello.out ./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
./build-userland --in-tree --clean ./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 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 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 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 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 ./build-userland --in-tree --clean
cd userland cd userland
./build
./build-userland --in-tree ./build --clean
./build-userland --in-tree --clean ./build c
./build-userland --in-tree c ./build --clean c
./build-userland --in-tree --clean ./build c/hello
./build-userland --in-tree c/hello ./build --clean c/hello
./build-userland --in-tree --clean ./build c/hello.
./build-userland --in-tree c/hello.c ./build --clean c/hello.
./build-userland --in-tree --clean ./build c/hello.c
./build-userland --in-tree c/hello.out ./build --clean c/hello.c
./build-userland --in-tree --clean ./build c/hello.out
./build --clean c/hello.out
./build "$(pwd)/c/hello.out"
./build --clean "$(pwd)/c/hello.out"

View File

@@ -84,6 +84,9 @@ class ThreadPool:
def __exit__(self, type, value, traceback): def __exit__(self, type, value, traceback):
self.join() self.join()
def get_error(self):
return self.error_output
def submit(self, work): def submit(self, work):
''' '''
Submit work. Block if there is already enough work scheduled (~nthreads). Submit work. Block if there is already enough work scheduled (~nthreads).
@@ -117,6 +120,7 @@ class ThreadPool:
out = self.func(**work) out = self.func(**work)
except Exception as e: except Exception as e:
exception = e exception = e
out = None
try: try:
handle_output_return = self.handle_output(work, out, exception) handle_output_return = self.handle_output(work, out, exception)
except Exception as e: except Exception as e: