|
OLD | NEW |
---|---|
(Empty) | |
1 #!/usr/bin/python | |
2 # Copyright 2013 The Chromium Authors. All rights reserved. | |
3 # Use of this source code is governed by a BSD-style license that can be | |
4 # found in the LICENSE file. | |
5 | |
6 # Downloads, builds (with instrumentation) and installs shared libraries. | |
7 | |
8 import argparse | |
9 import os | |
10 import shutil | |
11 import subprocess | |
12 import sys | |
13 | |
14 # Should be a dict from 'sanitizer type' to 'compiler flag'. | |
15 SUPPORTED_SANITIZERS = {"asan": "address"} | |
Alexander Potapenko
2013/11/15 10:32:19
"Be consistent with your choice of string quote ch
alextaran1
2013/11/15 12:00:51
Done.
| |
16 | |
17 | |
18 class ScopedChangeDirectory(object): | |
19 "Changes current working directory and restores it back automatically." | |
Alexander Potapenko
2013/11/15 10:32:19
Doc strings should use """.
alextaran1
2013/11/15 12:00:51
Done.
| |
20 def __init__(self, path): | |
21 self.path = path | |
22 self.old_path = "" | |
23 | |
24 def __enter__(self): | |
25 self.old_path = os.getcwd() | |
26 os.chdir(self.path) | |
27 | |
28 def __exit__(self, exc_type, exc_value, traceback): | |
29 os.chdir(self.old_path) | |
30 | |
31 | |
32 def get_script_absolute_path(): | |
33 return os.path.dirname(os.path.abspath(__file__)) | |
34 | |
35 | |
36 def get_library_build_dependencies(library): | |
37 command = 'apt-get -s build-dep {0} | grep Inst | cut -d " " -f 2'.format( | |
Alexander Potapenko
2013/11/15 10:32:19
It's more readable to split the string somewhere i
Alexander Potapenko
2013/11/15 10:32:19
Also consider using the % operator instead of the
alextaran1
2013/11/15 12:00:51
After replacing "format" to "%" wrapping isn't nee
| |
38 library) | |
39 command_result = subprocess.Popen(command, stdout = subprocess.PIPE, | |
Alexander Potapenko
2013/11/15 10:32:19
"Don't use spaces around the '=' sign when used to
alextaran1
2013/11/15 12:00:51
Done.
| |
40 shell = True) | |
41 build_dependencies = [l.strip() for l in command_result.stdout] | |
42 return build_dependencies | |
43 | |
44 | |
45 def download_build_install(parsed_arguments): | |
46 sanitizer_flag = SUPPORTED_SANITIZERS[parsed_arguments.sanitizer_type] | |
47 | |
48 os.putenv("CFLAGS", "-fsanitize={0} -g -fPIC -w".format(sanitizer_flag)) | |
Alexander Potapenko
2013/11/15 10:32:19
You don't need to change the actual environment of
alextaran1
2013/11/15 12:00:51
Done.
| |
49 os.putenv("CXXFLAGS", "-fsanitize={0} -g -fPIC -w".format(sanitizer_flag)) | |
50 # We use XORIGIN as RPATH and after building library replace it to $ORIGIN | |
51 # The reason: this flag goes through configure script and makefiles | |
52 # differently for different libraries. So the dollar sign "$" should be | |
53 # differently escaped. Instead of having problems with that it just | |
54 # uses XORIGIN to build library and after that replaces it to $ORIGIN | |
55 # directly in .so file. | |
56 os.putenv("LDFLAGS", "-Wl,-z,origin -Wl,-R,XORIGIN/.") | |
57 | |
58 library_directory = "{0}/{1}".format(parsed_arguments.intermediate_directory, | |
59 parsed_arguments.library) | |
60 | |
61 install_prefix = "{0}/{1}/instrumented_libraries/{2}".format( | |
62 get_script_absolute_path(), | |
63 parsed_arguments.product_directory, | |
64 parsed_arguments.sanitizer_type) | |
65 | |
66 if not os.path.exists(library_directory): | |
67 os.makedirs(library_directory) | |
68 | |
69 with ScopedChangeDirectory(library_directory), open(os.devnull, "w") as dev_nu ll: | |
Alexander Potapenko
2013/11/15 10:32:19
Please wrap this line.
alextaran1
2013/11/15 12:00:51
Done.
| |
70 subprocess.call("apt-get source {0}".format(parsed_arguments.library), | |
71 stdout = dev_null, stderr = dev_null, shell = True) | |
72 # There should be only one subdirectory after downloading a package. | |
73 subdirectories = [d for d in os.listdir(".") if os.path.isdir(d)] | |
74 if len(subdirectories) != 1: | |
75 raise Exception("There was not one directory after downloading " \ | |
76 "a package {0}".format(parsed_arguments.library)) | |
77 with ScopedChangeDirectory(subdirectories[0]): | |
Alexander Potapenko
2013/11/15 10:32:19
You're assuming len(subdirectories) > 0. If this s
alextaran1
2013/11/15 12:00:51
Done.
| |
78 # Now we are in the package directory. | |
79 configure_command = "./configure {0} --prefix={1}".format( | |
80 parsed_arguments.custom_configure_flags, install_prefix) | |
81 subprocess.call(configure_command, stdout = dev_null, stderr = dev_null, | |
82 shell = True) | |
83 subprocess.call("make -j{0}".format(parsed_arguments.jobs), | |
84 stdout = dev_null, stderr = dev_null, shell = True) | |
85 subprocess.call("make -j{0} install".format(parsed_arguments.jobs), | |
86 stdout = dev_null, stderr = dev_null, shell = True) | |
87 | |
88 # Touch a txt file to indicate library is installed. | |
89 open("{0}/{1}.txt".format(install_prefix, parsed_arguments.library), "w") \ | |
90 .close() | |
91 # Remove downloaded package and generated temporary build files. | |
92 shutil.rmtree(library_directory) | |
93 | |
94 | |
95 def main(): | |
96 argument_parser = argparse.ArgumentParser( | |
97 description = "Download, build and install instrumented library") | |
98 | |
99 argument_parser.add_argument("-j", "--jobs", type = int, default = 1) | |
100 argument_parser.add_argument("-l", "--library", required = True) | |
101 argument_parser.add_argument("-i", "--product-directory", default = ".", | |
102 help = "Relative path to the directory with chrome binaries") | |
103 argument_parser.add_argument("-m", "--intermediate-directory", default = ".", | |
104 help = "Relative path to the directory for temporary build files") | |
105 argument_parser.add_argument("-c", "--custom-configure-flags", default = "") | |
106 argument_parser.add_argument("-s", "--sanitizer-type", required = True, | |
107 choices = SUPPORTED_SANITIZERS.keys()) | |
108 | |
109 parsed_arguments = argument_parser.parse_args() | |
110 # Ensure current working directory is this script directory | |
111 os.chdir(get_script_absolute_path()) | |
112 # Ensure all build dependencies are installed | |
113 build_dependencies = get_library_build_dependencies(parsed_arguments.library) | |
114 if len(build_dependencies) != 0: | |
Alexander Potapenko
2013/11/15 10:32:19
That's just 'if len(build_dependencies)'.
Overall,
alextaran1
2013/11/15 12:00:51
Done.
| |
115 print >> sys.stderr, "Please, install build-dependencies for {0}".format( | |
116 parsed_arguments.library) | |
117 print >> sys.stderr, "One-liner for APT:" | |
118 print >> sys.stderr, "sudo apt-get -y --no-remove build-dep {0}".format( | |
119 parsed_arguments.library) | |
120 sys.exit(1) | |
121 | |
122 download_build_install(parsed_arguments) | |
123 | |
124 | |
125 if __name__ == "__main__": | |
126 main() | |
OLD | NEW |