zturner created this revision. zturner added reviewers: labath, stella.stamenova, aleksandr.urakov. Herald added a subscriber: mgorny.
This patch introduces two improvements to the `build.py` script. First, it supports multiple build inputs and outputs. This is helpful if you want to run with `mode=compile` but you want to compile many source files at once. Now, you can specify an output directory and it will write all of them to that location. Second, it changes the default architecture of test executables to be whatever the system is. Both of these will help with porting DIA PDB tests over to the new build script, but are also generally useful features that most tests will probably want anyway. https://reviews.llvm.org/D55230 Files: lldb/lit/BuildScript/modes.test lldb/lit/BuildScript/script-args.test lldb/lit/BuildScript/toolchain-clang-cl.test lldb/lit/BuildScript/toolchain-msvc.test lldb/lit/CMakeLists.txt lldb/lit/helper/build.py lldb/lit/helper/toolchain.py lldb/lit/lit.site.cfg.py.in
Index: lldb/lit/lit.site.cfg.py.in =================================================================== --- lldb/lit/lit.site.cfg.py.in +++ lldb/lit/lit.site.cfg.py.in @@ -16,6 +16,7 @@ config.python_executable = "@PYTHON_EXECUTABLE@" config.have_zlib = @LLVM_ENABLE_ZLIB@ config.host_triple = "@LLVM_HOST_TRIPLE@" +config.lldb_bitness = 64 if @LLDB_IS_64_BITS@ else 32 # Support substitution of the tools and libs dirs with user parameters. This is # used when we can't determine the tool dir at configuration time. Index: lldb/lit/helper/toolchain.py =================================================================== --- lldb/lit/helper/toolchain.py +++ lldb/lit/helper/toolchain.py @@ -20,15 +20,18 @@ command=FindTool('lldb-mi'), extra_args=['--synchronous'], unresolved='ignore') + + build_script = os.path.dirname(__file__) build_script = os.path.join(build_script, 'build.py') build_script_args = [build_script, '--compiler=any', # Default to best compiler - '--arch=64'] # Default to 64-bit, user can override + '--arch=' + str(config.lldb_bitness)] if config.lldb_lit_tools_dir: build_script_args.append('--tools-dir={0}'.format(config.lldb_lit_tools_dir)) if config.lldb_tools_dir: build_script_args.append('--tools-dir={0}'.format(config.lldb_tools_dir)) + primary_tools = [ ToolSubst('%lldb', command=FindTool('lldb'), Index: lldb/lit/helper/build.py =================================================================== --- lldb/lit/helper/build.py +++ lldb/lit/helper/build.py @@ -23,7 +23,9 @@ metavar='arch', dest='arch', required=True, - help='Specify the architecture to target. Valid values=[32,64]') + default='host', + choices=['32', '64', 'host'], + help='Specify the architecture to target.') parser.add_argument('--compiler', metavar='compiler', @@ -48,9 +50,16 @@ parser.add_argument('--output', '-o', dest='output', metavar='file', - required=True, + required=False, + default='', help='Path to output file') +parser.add_argument('--outdir', '-d', + dest='outdir', + metavar='directory', + required=False, + help='Directory for output files') + parser.add_argument('--nodefaultlib', dest='nodefaultlib', action='store_true', @@ -81,9 +90,16 @@ default=False, help='Print verbose output') -parser.add_argument('input', +parser.add_argument('-n', '--dry-run', + dest='dry', + action='store_true', + default=False, + help='Print the commands that would run, but dont actually run them') + +parser.add_argument('inputs', metavar='file', - help='Source file to compile / object file to link') + nargs='+', + help='Source file(s) to compile / object file(s) to link') args = parser.parse_args(args=sys.argv[1:]) @@ -128,14 +144,18 @@ except AttributeError: raise TypeError('not sure how to convert %s to %s' % (type(b), str)) +def format_text(lines, indent_0, indent_n): + result = ' ' * indent_0 + lines[0] + for next in lines[1:]: + result = result + '\n{0}{1}'.format(' ' * indent_n, next) + return result + def print_environment(env): for e in env: value = env[e] - split = value.split(os.pathsep) - print(' {0} = {1}'.format(e, split[0])) - prefix_width = 3 + len(e) - for next in split[1:]: - print(' {0}{1}'.format(' ' * prefix_width, next)) + lines = value.split(os.pathsep) + formatted_value = format_text(lines, 0, 7 + len(e)) + print(' {0} = {1}'.format(e, formatted_value)) def find_executable(binary_name, search_paths): if sys.platform == 'win32': @@ -189,9 +209,10 @@ class Builder(object): def __init__(self, toolchain_type, args): self.toolchain_type = toolchain_type - self.input = args.input + self.inputs = args.inputs self.arch = args.arch self.opt = args.opt + self.outdir = args.outdir self.compiler = args.compiler self.clean = args.clean self.output = args.output @@ -465,15 +486,26 @@ linkenv.update(defaultenv) return (compileenv, linkenv) - def _ilk_file_name(self): + def _output_name(self, input, extension): + basename = os.path.basename(input) + basename = os.path.splitext(basename)[0] + extension + output = os.path.join(self.outdir, basename) + return os.path.normpath(output) + + def _ilk_file_names(self): if self.mode == 'link': - return None - return os.path.splitext(self.output)[0] + '.ilk' + return [] - def _obj_file_name(self): - if self.mode == 'compile': - return self.output - return os.path.splitext(self.output)[0] + '.obj' + return [self._output_name(x, '.ilk') for x in self.inputs] + + def _obj_file_names(self): + if self.mode == 'link': + return self.inputs + + if self.mode == 'compile' and self.output: + return [self.output] + + return [self._output_name(x, '.obj') for x in self.inputs] def _pdb_file_name(self): if self.mode == 'compile': @@ -485,7 +517,7 @@ return None return self.output - def _get_compilation_command(self): + def _get_compilation_command(self, source, obj): args = [] args.append(self.compiler) @@ -511,11 +543,10 @@ args.append('-fkeep-static-consts') args.append('/c') - args.append('/Fo' + self._obj_file_name()) - args.append(self.input) - input = os.path.basename(self.input) - output = os.path.basename(self._obj_file_name()) - return ('compiling {0} -> {1}'.format(input, output), + args.append('/Fo' + obj) + args.append(source) + + return ('compiling', [source], obj, self.compile_env, args) @@ -529,18 +560,17 @@ args.append('/entry:main') args.append('/PDB:' + self._pdb_file_name()) args.append('/OUT:' + self._exe_file_name()) - args.append(self._obj_file_name()) + args.extend(self._obj_file_names()) - input = os.path.basename(self._obj_file_name()) - output = os.path.basename(self._exe_file_name()) - return ('linking {0} -> {1}'.format(input, output), + return ('linking', self._obj_file_names(), self._exe_file_name(), self.link_env, args) def build_commands(self): commands = [] if self.mode == 'compile' or self.mode == 'compile-and-link': - commands.append(self._get_compilation_command()) + for input, output in zip(self.inputs, self._obj_file_names()): + commands.append(self._get_compilation_command(input, output)) if self.mode == 'link' or self.mode == 'compile-and-link': commands.append(self._get_link_command()) return commands @@ -552,8 +582,8 @@ outputs = [] if self.mode == 'compile' or self.mode == 'compile-and-link': - outputs.append(self._ilk_file_name()) - outputs.append(self._obj_file_name()) + outputs.extend(self._ilk_file_names()) + outputs.extend(self._obj_file_names()) if self.mode == 'link' or self.mode == 'compile-and-link': outputs.append(self._pdb_file_name()) outputs.append(self._exe_file_name()) @@ -579,13 +609,20 @@ def build(commands): global args - for (status, env, child_args) in commands: + for (status, inputs, output, env, child_args) in commands: print('\n\n') - print(status) + if not args.verbose: + inputs = [os.path.basename(x) for x in inputs] + output = os.path.basename(output) + print(status + ' {0} -> {1}'.format('+'.join(inputs), output)) + if args.verbose: print(' Command Line: ' + ' '.join(child_args)) print(' Env:') print_environment(env) + if args.dry: + continue + popen = subprocess.Popen(child_args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, @@ -609,7 +646,8 @@ print('Cleaning {0}'.format(file)) try: if os.path.exists(o): - os.remove(o) + if not args.dry: + os.remove(o) if args.verbose: print(' The file was successfully cleaned.') elif args.verbose: @@ -618,17 +656,57 @@ if args.verbose: print(' The file could not be removed.') +def fix_arguments(args): + if not args.inputs: + raise ValueError('No input files specified') + + if args.output and args.mode == 'compile' and len(args.inputs) > 1: + raise ValueError('Cannot specify -o with mode=compile and multiple source files. Use --outdir instead.') + + if not args.dry: + args.inputs = [os.path.abspath(x) for x in args.inputs] + + # If user didn't specify the outdir, use the directory of the first input. + if not args.outdir: + if args.output: + args.outdir = os.path.dirname(args.output) + else: + args.outdir = os.path.dirname(args.inputs[0]) + args.outdir = os.path.abspath(args.outdir) + args.outdir = os.path.normpath(args.outdir) + + # If user specified a non-absolute path for the output file, append the + # output directory to it. + if args.output: + if not os.path.isabs(args.output): + args.output = os.path.join(args.outdir, args.output) + args.output = os.path.normpath(args.output) + +fix_arguments(args) + (toolchain_type, toolchain_path) = find_toolchain(args.compiler, args.tools_dir) if not toolchain_path or not toolchain_type: print('Unable to find toolchain {0}'.format(args.compiler)) sys.exit(1) if args.verbose: - print("Script Environment:") + print('Script Arguments:') + print(' Arch: ' + args.arch) + print(' Compiler: ' + args.compiler) + print(' Outdir: ' + args.outdir) + print(' Output: ' + args.output) + print(' Nodefaultlib: ' + str(args.nodefaultlib)) + print(' Opt: ' + args.opt) + print(' Mode: ' + args.mode) + print(' Clean: ' + str(args.clean)) + print(' Verbose: ' + str(args.verbose)) + print(' Dryrun: ' + str(args.dry)) + print(' Inputs: ' + format_text(args.inputs, 0, 10)) + print('Script Environment:') print_environment(os.environ) args.compiler = toolchain_path -if not os.path.exists(args.compiler): +if not os.path.exists(args.compiler) and not args.dry: raise ValueError('The toolchain {} does not exist.'.format(args.compiler)) if toolchain_type == 'msvc' or toolchain_type=='clang-cl': Index: lldb/lit/CMakeLists.txt =================================================================== --- lldb/lit/CMakeLists.txt +++ lldb/lit/CMakeLists.txt @@ -7,6 +7,10 @@ set(LLVM_BUILD_MODE "%(build_mode)s") endif () +if (CMAKE_SIZEOF_VOID_P EQUAL 8) + set(LLDB_IS_64_BITS 1) +endif() + if (NOT LLDB_TEST_USE_CUSTOM_C_COMPILER) string(REPLACE ${CMAKE_CFG_INTDIR} ${LLVM_BUILD_MODE} LLDB_TEST_C_COMPILER ${LLDB_TEST_C_COMPILER}) endif () @@ -49,7 +53,8 @@ # the value is not canonicalized within LLVM llvm_canonicalize_cmake_booleans( LLDB_DISABLE_PYTHON - LLVM_ENABLE_ZLIB) + LLVM_ENABLE_ZLIB + LLDB_IS_64_BITS) configure_lit_site_cfg( ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.py.in Index: lldb/lit/BuildScript/toolchain-msvc.test =================================================================== --- /dev/null +++ lldb/lit/BuildScript/toolchain-msvc.test @@ -0,0 +1,62 @@ +REQUIRES: system-windows, msvc + +RUN: %build -n --verbose --arch=32 --compiler=msvc --mode=compile-and-link -o %t/foo.exe foobar.c \ +RUN: | FileCheck --check-prefix=X86 %s + +RUN: %build -n --verbose --arch=64 --compiler=msvc --mode=compile-and-link -o %t/foo.exe foobar.c \ +RUN: | FileCheck --check-prefix=X64 %s + +X86: Script Arguments: +X86: Arch: 32 +X86: Compiler: msvc +X86: Outdir: {{.*}} +X86: Output: {{.*}}toolchain-msvc.test.tmp\foo.exe +X86: Nodefaultlib: False +X86: Opt: none +X86: Mode: compile +X86: Clean: True +X86: Verbose: True +X86: Dryrun: True +X86: Inputs: foobar.c +X86: Cleaning {{.*}}toolchain-msvc.test.tmp\foobar.ilk +X86: Cleaning {{.*}}toolchain-msvc.test.tmp\foobar.obj +X86: Cleaning {{.*}}toolchain-msvc.test.tmp\foo.pdb +X86: Cleaning {{.*}}toolchain-msvc.test.tmp\foo.exe +X86: compiling foobar.c -> foobar.obj +X86: Command Line: {{.*}}\{{[Hh]ost[Xx]64}}\x86\cl.exe +X86: linking foobar.obj -> foo.exe +X86: Command Line: {{.*}}\{{[Hh]ost[Xx]64}}\x86\link.exe +X86: Env +X86: LIB = {{.*}}\ATLMFC\lib\x86 +X86: {{.*}}\lib\x86 +X86: {{.*}}\ucrt\x86 +X86: {{.*}}\um\x86 +X86: PATH = {{.*}}\bin\{{[Hh]ost[Xx]64}}\x64 + + +X64: Script Arguments: +X64: Arch: 64 +X64: Compiler: msvc +X64: Outdir: {{.*}} +X64: Output: {{.*}}toolchain-msvc.test.tmp\foo.exe +X64: Nodefaultlib: False +X64: Opt: none +X64: Mode: compile +X64: Clean: True +X64: Verbose: True +X64: Dryrun: True +X64: Inputs: foobar.c +X64: Cleaning {{.*}}toolchain-msvc.test.tmp\foobar.ilk +X64: Cleaning {{.*}}toolchain-msvc.test.tmp\foobar.obj +X64: Cleaning {{.*}}toolchain-msvc.test.tmp\foo.pdb +X64: Cleaning {{.*}}toolchain-msvc.test.tmp\foo.exe +X64: compiling foobar.c -> foobar.obj +X64: Command Line: {{.*}}\{{[Hh]ost[Xx]64}}\x64\cl.exe +X64: linking foobar.obj -> foo.exe +X64: Command Line: {{.*}}\{{[Hh]ost[Xx]64}}\x64\link.exe +X64: Env +X64: LIB = {{.*}}\ATLMFC\lib\x64 +X64: {{.*}}\lib\x64 +X64: {{.*}}\ucrt\x64 +X64: {{.*}}\um\x64 +X64: PATH = {{.*}}\bin\{{[Hh]ost[Xx]64}}\x64 Index: lldb/lit/BuildScript/toolchain-clang-cl.test =================================================================== --- /dev/null +++ lldb/lit/BuildScript/toolchain-clang-cl.test @@ -0,0 +1,49 @@ +REQUIRES: lld + +RUN: %build -n --verbose --arch=32 --compiler=clang-cl --mode=compile-and-link -o %t/foo.exe foobar.c \ +RUN: | FileCheck --check-prefix=CHECK-32 %s + +RUN: %build -n --verbose --arch=64 --compiler=clang-cl --mode=compile-and-link -o %t/foo.exe foobar.c \ +RUN: | FileCheck --check-prefix=CHECK-64 %s + +CHECK-32: Script Arguments: +CHECK-32: Arch: 32 +CHECK-32: Compiler: clang-cl +CHECK-32: Outdir: {{.*}} +CHECK-32: Output: {{.*}}toolchain-clang-cl.test.tmp\foo.exe +CHECK-32: Nodefaultlib: False +CHECK-32: Opt: none +CHECK-32: Mode: compile +CHECK-32: Clean: True +CHECK-32: Verbose: True +CHECK-32: Dryrun: True +CHECK-32: Inputs: foobar.c +CHECK-32: Cleaning {{.*}}toolchain-clang-cl.test.tmp{{.}}foobar.ilk +CHECK-32: Cleaning {{.*}}toolchain-clang-cl.test.tmp{{.}}foobar.obj +CHECK-32: Cleaning {{.*}}toolchain-clang-cl.test.tmp{{.}}foo.pdb +CHECK-32: Cleaning {{.*}}toolchain-clang-cl.test.tmp{{.}}foo.exe +CHECK-32: compiling foobar.c -> foobar.obj +CHECK-32: {{.*}}clang-cl{{(.exe)?}} -m32 +CHECK-32: linking foobar.obj -> foo.exe +CHECK-32: {{.*}}lld-link + +CHECK-64: Script Arguments: +CHECK-64: Arch: 64 +CHECK-64: Compiler: clang-cl +CHECK-64: Outdir: {{.*}} +CHECK-64: Output: {{.*}}toolchain-clang-cl.test.tmp\foo.exe +CHECK-64: Nodefaultlib: False +CHECK-64: Opt: none +CHECK-64: Mode: compile +CHECK-64: Clean: True +CHECK-64: Verbose: True +CHECK-64: Dryrun: True +CHECK-64: Inputs: foobar.c +CHECK-64: Cleaning {{.*}}toolchain-clang-cl.test.tmp{{.}}foobar.ilk +CHECK-64: Cleaning {{.*}}toolchain-clang-cl.test.tmp{{.}}foobar.obj +CHECK-64: Cleaning {{.*}}toolchain-clang-cl.test.tmp{{.}}foo.pdb +CHECK-64: Cleaning {{.*}}toolchain-clang-cl.test.tmp{{.}}foo.exe +CHECK-64: compiling foobar.c -> foobar.obj +CHECK-64: {{.*}}clang-cl{{(.exe)?}} -m64 +CHECK-64: linking foobar.obj -> foo.exe +CHECK-64: {{.*}}lld-link{{(.exe)?}} Index: lldb/lit/BuildScript/script-args.test =================================================================== --- /dev/null +++ lldb/lit/BuildScript/script-args.test @@ -0,0 +1,32 @@ +RUN: %build -n --verbose --arch=32 --mode=compile --compiler=any -o %t/foo.out foobar.c \ +RUN: | FileCheck %s +RUN: %build -n --verbose --arch=32 --mode=compile --compiler=any --outdir %t foo.c bar.c \ +RUN: | FileCheck --check-prefix=MULTI-INPUT %s + + +CHECK: Script Arguments: +CHECK-NEXT: Arch: 32 +CHECK: Compiler: any +CHECK: Outdir: {{.*}}script-args.test.tmp +CHECK: Output: {{.*}}script-args.test.tmp{{.}}foo.out +CHECK: Nodefaultlib: False +CHECK: Opt: none +CHECK: Mode: compile +CHECK: Clean: True +CHECK: Verbose: True +CHECK: Dryrun: True +CHECK: Inputs: foobar.c + +MULTI-INPUT: Script Arguments: +MULTI-INPUT-NEXT: Arch: 32 +MULTI-INPUT-NEXT: Compiler: any +MULTI-INPUT-NEXT: Outdir: {{.*}}script-args.test.tmp +MULTI-INPUT-NEXT: Output: +MULTI-INPUT-NEXT: Nodefaultlib: False +MULTI-INPUT-NEXT: Opt: none +MULTI-INPUT-NEXT: Mode: compile +MULTI-INPUT-NEXT: Clean: True +MULTI-INPUT-NEXT: Verbose: True +MULTI-INPUT-NEXT: Dryrun: True +MULTI-INPUT-NEXT: Inputs: foo.c +MULTI-INPUT-NEXT: bar.c \ No newline at end of file Index: lldb/lit/BuildScript/modes.test =================================================================== --- /dev/null +++ lldb/lit/BuildScript/modes.test @@ -0,0 +1,35 @@ +RUN: %build -n --verbose --arch=32 --mode=compile --compiler=any -o %t/foo.out foobar.c \ +RUN: | FileCheck --check-prefix=COMPILE %s + +RUN: %build -n --verbose --arch=32 --mode=compile --compiler=any --outdir %t foo.c bar.c \ +RUN: | FileCheck --check-prefix=COMPILE-MULTI %s + +RUN: %build -n --verbose --arch=32 --mode=link --compiler=any -o %t/foo.exe foobar.obj \ +RUN: | FileCheck --check-prefix=LINK %s + +RUN: %build -n --verbose --arch=32 --mode=link --compiler=any -o %t/foobar.exe foo.obj bar.obj \ +RUN: | FileCheck --check-prefix=LINK-MULTI %s + +RUN: %build -n --verbose --arch=32 --mode=compile-and-link --compiler=any -o %t/foobar.exe foobar.c \ +RUN: | FileCheck --check-prefix=BOTH %s + +RUN: %build -n --verbose --arch=32 --mode=compile-and-link --compiler=any -o %t/foobar.exe foo.c bar.c \ +RUN: | FileCheck --check-prefix=BOTH-MULTI %s + + +COMPILE: compiling foobar.c -> foo.out + +COMPILE-MULTI: compiling foo.c -> foo.obj +COMPILE-MULTI: compiling bar.c -> bar.obj + + +LINK: linking foobar.obj -> foo.exe + +LINK-MULTI: linking foo.obj+bar.obj -> foobar.exe + +BOTH: compiling foobar.c -> foobar.obj +BOTH: linking foobar.obj -> foobar.exe + +BOTH-MULTI: compiling foo.c -> foo.obj +BOTH-MULTI: compiling bar.c -> bar.obj +BOTH-MULTI: linking foo.obj+bar.obj -> foobar.exe
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits