Chromium Code Reviews| Index: syzygy/integration_tests/make_integration_tests_clang.py |
| diff --git a/syzygy/integration_tests/make_integration_tests_clang.py b/syzygy/integration_tests/make_integration_tests_clang.py |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..6fec0dd8b9d3c118f2c94aa6c6837e0a187bb805 |
| --- /dev/null |
| +++ b/syzygy/integration_tests/make_integration_tests_clang.py |
| @@ -0,0 +1,150 @@ |
| +#!/usr/bin/env python |
| +# Copyright 2017 The Chromium Authors. All rights reserved. |
| +# Use of this source code is governed by a BSD-style license that can be |
| +# found in the LICENSE file. |
| +"""A script to compile the integration tests with llvm's clang, |
| +instrument the code with llvm's Asan, and link it to the syzyasan_rtl |
| +runtime environment. |
| +""" |
| + |
| +import optparse |
| +import os |
| +import re |
| +import subprocess |
| +import sys |
| + |
| + |
| +_SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__)) |
| +_SRC_DIR = os.path.abspath(os.path.join(_SCRIPT_DIR, os.pardir, os.pardir)) |
| +_CLANG_CL_PATH = os.path.join(_SRC_DIR, |
| + "third_party", "llvm-build", "Release+Asserts", "bin", "clang-cl.exe") |
|
Sébastien Marchand
2017/07/06 15:41:35
Use ' rather than ". Both works but we tend to pre
|
| + |
| +def compile_with_asan(clang_path, source_files, src_dir, object_files, |
| + target_name): |
| + """Only compiles with clang but does not link. |
| + |
| + Only compiles the files and isntruments them with LLVM's Asan but does not |
| + link them. The linking is done separately in the method link. |
| + |
| + Args: |
| + clang_path: Path to the clang-cl compiler. |
| + source_files: The source files to be compiled. |
| + src_dir: The repository where the syzgy src is located. |
| + object_files: The path where each object file should be generated. |
| + target_name: The name of the target being build. |
| + """ |
| + |
| + compiler_flags = [ |
| + '-c', |
| + '-m32', |
| + '-fsanitize=address', |
| + '-mllvm', |
| + '-asan-instrumentation-with-call-threshold=0', |
| + '-mllvm', |
| + '-asan-stack=0', |
| + '-DUNICODE', |
| + '-D_UNICODE', |
| + '-DNOMINMAX', |
| + '-D_CRT_SECURE_NO_WARNINGS', |
| + '-I', |
| + src_dir, |
| + ] |
| + |
| + compile_command = [clang_path] |
| + compile_command.extend(compiler_flags) |
| + |
| + for source_file, object_file in zip(source_files, object_files): |
| + # Needed to get back the original list for each file that is being compiled. |
| + command_len = len(compile_command) |
|
Sébastien Marchand
2017/07/06 15:41:35
Add a new variable called compile_command_base (or
|
| + compile_command.append(source_file) |
| + compile_command.append('-o') |
| + compile_command.append(object_file) |
| + |
| + ret = subprocess.call(compile_command) |
| + if ret != 0: |
| + print ("ERROR: Failed compiling %s using clang-cl" % target_name) |
|
Sébastien Marchand
2017/07/06 15:41:34
The parenthesis aren't needed, use ' rather than "
|
| + return ret |
| + compile_command = compile_command[:command_len] |
| + return ret |
| + |
| +def link(clang_path, object_files, build_dir, target_name): |
| + """ Links the object files and produces the integration_tests_clang_dll.dll. |
| + |
| + |
| + Links the object files and produces the dll. The object files have to be |
| + produced by the compile method above. |
| + |
| + Args: |
| + clang_path: Path to the clang-cl compiler in the syzygy project. |
| + source_files: The source file names which are converted to obj filenames. |
| + build_dir: The directory where to produce the linked dll. |
| + target_name: The name of the target being build. |
| + """ |
| + |
| + linker_flags = [ |
| + '-o', |
| + os.path.join(build_dir, target_name + '.dll'), |
| + '/link', |
| + '/dll', |
| + build_dir + '\export_dll.dll.lib', |
| + build_dir + '\syzyasan_rtl.dll.lib', |
| + '-defaultlib:libcmt' |
| + ] |
| + |
| + linker_command = [clang_path, '-m32'] |
| + linker_command.extend(object_files) |
| + linker_command.extend(linker_flags) |
| + ret = subprocess.call(linker_command) |
| + |
| + if ret != 0: |
| + print ("ERROR: Failed to link %s using clang-cl" % target_name) |
|
Sébastien Marchand
2017/07/06 15:41:34
Ditto, no parenthesis and s/"/'/
|
| + return ret |
| + |
| + |
| +def main(): |
| + parser = optparse.OptionParser(usage='%prog [options]') |
| + parser.add_option('--output-dir', |
| + help='Path to the Syzygy Release directory.') |
| + parser.add_option('--input-files', help='files to be compiled and linked') |
|
Sébastien Marchand
2017/07/06 15:41:34
Use full sentences here, starting with an uppercas
|
| + parser.add_option('--target-name', help='name of the target to be compiled') |
|
Sébastien Marchand
2017/07/06 15:41:34
Ditto.
|
| + |
| + options, _ = parser.parse_args() |
| + |
| + if not options.output_dir: |
| + parser.error('--output-dir is required') |
|
Sébastien Marchand
2017/07/06 15:41:34
Ditto, add a period (here and below).
|
| + if not options.input_files: |
| + parser.error('--input-files is required') |
| + if not options.target_name: |
| + parser.error('--target-name is required') |
| + |
| + def get_object_file_location(source_file, |
| + output_dir, target_name): |
| + return os.path.join(output_dir, 'obj', |
| + os.path.split(os.path.relpath(source_file, |
| + _SRC_DIR))[0], |
| + target_name + '.%s.obj' % |
|
Sébastien Marchand
2017/07/06 15:41:34
Don't mix + and %, you could do: "%s.%s.obj' % (ta
|
| + os.path.splitext(os.path.basename(source_file))[0]) |
| + |
| + source_files = options.input_files.split() |
| + object_files = [] |
| + |
| + for source_file in source_files: |
| + object_files.append(get_object_file_location(source_file, |
| + options.output_dir, |
| + options.target_name)) |
| + |
| + ret = compile_with_asan(_CLANG_CL_PATH, source_files, _SRC_DIR, |
| + object_files, options.target_name) |
| + |
| + if ret == 0: |
| + ret = link(_CLANG_CL_PATH, object_files, options.output_dir, |
| + options.target_name) |
| + else: |
| + print ("ERROR: Compilation of %s failed, skipping link step." |
|
Sébastien Marchand
2017/07/06 15:41:35
Use ' rather than ".
|
| + % options.target_name) |
| + |
| + return ret |
| + |
| + |
| +if __name__ == '__main__': |
| + sys.exit(main()) |