| OLD | NEW |
| 1 #!/usr/bin/python | 1 #!/usr/bin/python |
| 2 # Copyright (c) 2012 The Native Client Authors. All rights reserved. | 2 # Copyright (c) 2012 The Native Client Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 from optparse import OptionParser | 6 from optparse import OptionParser |
| 7 import os | 7 import os |
| 8 import subprocess | 8 import subprocess |
| 9 import sys | 9 import sys |
| 10 | 10 |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 74 elif sys.platform.startswith('darwin'): | 74 elif sys.platform.startswith('darwin'): |
| 75 self.osname = 'mac' | 75 self.osname = 'mac' |
| 76 else: | 76 else: |
| 77 ErrOut('Toolchain OS %s not supported.' % sys.platform) | 77 ErrOut('Toolchain OS %s not supported.' % sys.platform) |
| 78 | 78 |
| 79 if arch in ['x86-32', 'x86-64']: | 79 if arch in ['x86-32', 'x86-64']: |
| 80 self.arch = arch | 80 self.arch = arch |
| 81 self.mainarch = 'x86' | 81 self.mainarch = 'x86' |
| 82 self.subarch = arch.split('-')[1] | 82 self.subarch = arch.split('-')[1] |
| 83 tool_subdir = 'x86_64-nacl' | 83 tool_subdir = 'x86_64-nacl' |
| 84 self.pnacl = False |
| 85 elif arch == 'arm': |
| 86 self.arch = arch |
| 87 self.mainarch = 'arm' |
| 88 self.subarch = '' |
| 89 self.pnacl = True |
| 84 else: | 90 else: |
| 85 ErrOut('Toolchain architecture %s not supported.' % arch) | 91 ErrOut('Toolchain architecture %s not supported.' % arch) |
| 86 | 92 |
| 93 if arch == 'arm' and toolname == 'glibc': |
| 94 ErrOut('arm/glibc not yet supported.') |
| 95 |
| 87 if toolname == 'newlib': | 96 if toolname == 'newlib': |
| 88 toolchain = '%s_%s_newlib' % (self.osname, self.mainarch) | 97 toolchain = '%s_%s_newlib' % (self.osname, self.mainarch) |
| 89 self.toolname = 'newlib' | 98 self.toolname = 'newlib' |
| 90 elif toolname == 'glibc': | 99 elif toolname == 'glibc': |
| 91 toolchain = '%s_%s' % (self.osname, self.mainarch) | 100 toolchain = '%s_%s' % (self.osname, self.mainarch) |
| 92 self.toolname = 'glibc' | 101 self.toolname = 'glibc' |
| 93 else: | 102 else: |
| 94 ErrOut('Toolchain of type %s not supported.' % toolname) | 103 ErrOut('Toolchain of type %s not supported.' % toolname) |
| 95 | 104 |
| 96 self.root_path = options.root | 105 self.root_path = options.root |
| 97 self.nacl_path = os.path.join(self.root_path, 'native_client') | 106 self.nacl_path = os.path.join(self.root_path, 'native_client') |
| 98 | 107 |
| 99 project_path, project_name = os.path.split(options.name) | 108 project_path, project_name = os.path.split(options.name) |
| 100 self.outdir = options.objdir | 109 self.outdir = options.objdir |
| 101 | 110 |
| 102 # Set the toolchain directories | 111 # Set the toolchain directories |
| 103 self.toolchain = self.GenNaClPath(os.path.join('toolchain', toolchain)) | 112 if self.pnacl: |
| 104 self.toolbin = os.path.join(self.toolchain, tool_subdir, 'bin') | 113 pnacldir = 'pnacl_%s_x86_64' % self.osname |
| 105 self.toollib = os.path.join(self.toolchain, tool_subdir, 'lib'+self.subarch) | 114 self.toolchain = self.GenNaClPath(os.path.join('toolchain', |
| 106 self.toolinc = os.path.join(self.toolchain, tool_subdir, 'include') | 115 pnacldir, |
| 116 self.toolname)) |
| 117 self.toolbin = os.path.join(self.toolchain, 'bin') |
| 118 self.toollib = os.path.join(self.toolchain, 'lib') |
| 119 self.toolinc = os.path.join(self.toolchain, 'sysroot', 'include') |
| 120 else: |
| 121 self.toolchain = self.GenNaClPath(os.path.join('toolchain', |
| 122 toolchain)) |
| 123 self.toolbin = os.path.join(self.toolchain, tool_subdir, 'bin') |
| 124 self.toollib = os.path.join(self.toolchain, |
| 125 tool_subdir, |
| 126 'lib' + self.subarch) |
| 127 self.toolinc = os.path.join(self.toolchain, tool_subdir, 'include') |
| 107 | 128 |
| 108 self.inc_paths = ArgToList(options.incdirs) | 129 self.inc_paths = ArgToList(options.incdirs) |
| 109 self.lib_paths = ArgToList(options.libdirs) | 130 self.lib_paths = ArgToList(options.libdirs) |
| 110 | 131 |
| 111 self.name = options.name | 132 self.name = options.name |
| 112 self.BuildCompileOptions(options.compile_flags, options.defines) | 133 self.BuildCompileOptions(options.compile_flags, options.defines) |
| 113 self.BuildLinkOptions(options.link_flags) | 134 self.BuildLinkOptions(options.link_flags) |
| 114 self.BuildArchiveOptions() | 135 self.BuildArchiveOptions() |
| 115 self.verbose = options.verbose | 136 self.verbose = options.verbose |
| 116 self.suffix = options.suffix | 137 self.suffix = options.suffix |
| 117 self.strip = options.strip | 138 self.strip = options.strip |
| 118 self.empty = options.empty | 139 self.empty = options.empty |
| 119 self.strip_debug = options.strip_debug | 140 self.strip_debug = options.strip_debug |
| 120 | 141 |
| 121 if self.verbose: | 142 if self.verbose: |
| 122 print 'Compile options: %s' % self.compile_options | 143 print 'Compile options: %s' % self.compile_options |
| 123 print 'Linker options: %s' % self.link_options | 144 print 'Linker options: %s' % self.link_options |
| 124 | 145 |
| 125 def GenNaClPath(self, path): | 146 def GenNaClPath(self, path): |
| 126 """Helper which prepends path with the native client source directory.""" | 147 """Helper which prepends path with the native client source directory.""" |
| 127 return os.path.join(self.root_path, 'native_client', path) | 148 return os.path.join(self.root_path, 'native_client', path) |
| 128 | 149 |
| 129 def GetBinName(self, name): | 150 def GetBinName(self, name): |
| 130 """Helper which prepends executable with the toolchain bin directory.""" | 151 """Helper which prepends executable with the toolchain bin directory.""" |
| 131 return os.path.join(self.toolbin, name) | 152 return os.path.join(self.toolbin, name) |
| 132 | 153 |
| 154 def GetCCompiler(self): |
| 155 """Helper which returns C compiler path.""" |
| 156 if self.pnacl: |
| 157 return self.GetBinName('pnacl-clang') |
| 158 else: |
| 159 return self.GetBinName('gcc') |
| 160 |
| 161 def GetCXXCompiler(self): |
| 162 """Helper which returns C++ compiler path.""" |
| 163 if self.pnacl: |
| 164 return self.GetBinName('pnacl-clang++') |
| 165 else: |
| 166 return self.GetBinName('g++') |
| 167 |
| 168 def GetAr(self): |
| 169 """Helper which returns ar path.""" |
| 170 if self.pnacl: |
| 171 return self.GetBinName('pnacl-ar') |
| 172 else: |
| 173 return self.GetBinName('ar') |
| 174 |
| 175 def GetStrip(self): |
| 176 """Helper which returns strip path.""" |
| 177 if self.pnacl: |
| 178 return self.GetBinName('pnacl-strip') |
| 179 else: |
| 180 return self.GetBinName('strip') |
| 181 |
| 133 def BuildAssembleOptions(self, options): | 182 def BuildAssembleOptions(self, options): |
| 134 options = ArgToList(options) | 183 options = ArgToList(options) |
| 135 self.assemble_options = options + ['-I' + name for name in self.inc_paths] | 184 self.assemble_options = options + ['-I' + name for name in self.inc_paths] |
| 136 | 185 |
| 137 def BuildCompileOptions(self, options, defines): | 186 def BuildCompileOptions(self, options, defines): |
| 138 """Generates compile options, called once by __init__.""" | 187 """Generates compile options, called once by __init__.""" |
| 139 options = ArgToList(options) | 188 options = ArgToList(options) |
| 140 options += ['-D' + define for define in defines] | 189 options += ['-D' + define for define in defines] |
| 141 self.compile_options = options + ['-I' + name for name in self.inc_paths] | 190 self.compile_options = options + ['-I' + name for name in self.inc_paths] |
| 142 | 191 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 181 | 230 |
| 182 def CleanOutput(self, out): | 231 def CleanOutput(self, out): |
| 183 if os.path.isfile(out): | 232 if os.path.isfile(out): |
| 184 os.remove(out) | 233 os.remove(out) |
| 185 | 234 |
| 186 def Compile(self, src): | 235 def Compile(self, src): |
| 187 """Compile the source with pre-determined options.""" | 236 """Compile the source with pre-determined options.""" |
| 188 | 237 |
| 189 filename, ext = os.path.splitext(src) | 238 filename, ext = os.path.splitext(src) |
| 190 if ext == '.c' or ext == '.S': | 239 if ext == '.c' or ext == '.S': |
| 191 bin_name = self.GetBinName('gcc') | 240 bin_name = self.GetCCompiler() |
| 192 extra = ['-std=gnu99'] | 241 extra = ['-std=gnu99'] |
| 242 if self.pnacl and ext == '.S': |
| 243 extra.append('-arch') |
| 244 extra.append(self.arch) |
| 193 elif ext == '.cc': | 245 elif ext == '.cc': |
| 194 bin_name = self.GetBinName('g++') | 246 bin_name = self.GetCXXCompiler() |
| 195 extra = [] | 247 extra = [] |
| 196 else: | 248 else: |
| 197 if self.verbose and ext != '.h': | 249 if self.verbose and ext != '.h': |
| 198 print 'Skipping unknown type %s for %s.' % (ext, src) | 250 print 'Skipping unknown type %s for %s.' % (ext, src) |
| 199 return None | 251 return None |
| 200 | 252 |
| 201 if self.verbose: | 253 if self.verbose: |
| 202 print '\nCompile %s' % src | 254 print '\nCompile %s' % src |
| 203 | 255 |
| 204 out = self.GetObjectName(src) | 256 out = self.GetObjectName(src) |
| 205 MakeDir(os.path.dirname(out)) | 257 MakeDir(os.path.dirname(out)) |
| 206 self.CleanOutput(out) | 258 self.CleanOutput(out) |
| 207 cmd_line = [bin_name, '-c', src, '-o', out] + extra + self.compile_options | 259 cmd_line = [bin_name, '-c', src, '-o', out] + extra + self.compile_options |
| 208 err = self.Run(cmd_line, out) | 260 err = self.Run(cmd_line, out) |
| 209 if sys.platform.startswith('win') and err == 5: | 261 if sys.platform.startswith('win') and err == 5: |
| 210 # Try again on mystery windows failure. | 262 # Try again on mystery windows failure. |
| 211 err = self.Run(cmd_line, out) | 263 err = self.Run(cmd_line, out) |
| 212 if err: | 264 if err: |
| 213 ErrOut('\nFAILED with %d: %s\n\n' % (err, ' '.join(cmd_line))) | 265 ErrOut('\nFAILED with %d: %s\n\n' % (err, ' '.join(cmd_line))) |
| 214 return out | 266 return out |
| 215 | 267 |
| 216 def Link(self, srcs): | 268 def Link(self, srcs): |
| 217 """Link these objects with predetermined options and output name.""" | 269 """Link these objects with predetermined options and output name.""" |
| 218 out = self.name | 270 out = self.name |
| 219 if self.verbose: | 271 if self.verbose: |
| 220 print '\nLink %s' % out | 272 print '\nLink %s' % out |
| 221 bin_name = self.GetBinName('g++') | 273 bin_name = self.GetCXXCompiler() |
| 222 MakeDir(os.path.dirname(out)) | 274 MakeDir(os.path.dirname(out)) |
| 223 self.CleanOutput(out) | 275 self.CleanOutput(out) |
| 224 | 276 |
| 225 cmd_line = [bin_name, '-o', out, '-Wl,--as-needed'] | 277 cmd_line = [bin_name, '-o', out, '-Wl,--as-needed'] |
| 226 if not self.empty: | 278 if not self.empty: |
| 227 cmd_line += srcs | 279 cmd_line += srcs |
| 228 cmd_line += self.link_options | 280 cmd_line += self.link_options |
| 229 | 281 |
| 230 err = self.Run(cmd_line, out) | 282 err = self.Run(cmd_line, out) |
| 231 # TODO( Retry on windows | 283 # TODO( Retry on windows |
| 232 if sys.platform.startswith('win') and err == 5: | 284 if sys.platform.startswith('win') and err == 5: |
| 233 # Try again on mystery windows failure. | 285 # Try again on mystery windows failure. |
| 234 err = self.Run(cmd_line, out) | 286 err = self.Run(cmd_line, out) |
| 235 if err: | 287 if err: |
| 236 ErrOut('\nFAILED with %d: %s\n\n' % (err, ' '.join(cmd_line))) | 288 ErrOut('\nFAILED with %d: %s\n\n' % (err, ' '.join(cmd_line))) |
| 237 return out | 289 return out |
| 238 | 290 |
| 239 def Archive(self, srcs): | 291 def Archive(self, srcs): |
| 240 """Archive these objects with predetermined options and output name.""" | 292 """Archive these objects with predetermined options and output name.""" |
| 241 out = self.name | 293 out = self.name |
| 242 if self.verbose: | 294 if self.verbose: |
| 243 print '\nArchive %s' % out | 295 print '\nArchive %s' % out |
| 244 | 296 |
| 245 | 297 |
| 246 if '-r' in self.link_options: | 298 if '-r' in self.link_options: |
| 247 bin_name = self.GetBinName('g++') | 299 bin_name = self.GetCXXCompiler() |
| 248 cmd_line = [bin_name, '-o', out, '-Wl,--as-needed'] | 300 cmd_line = [bin_name, '-o', out, '-Wl,--as-needed'] |
| 249 if not self.empty: | 301 if not self.empty: |
| 250 cmd_line += srcs | 302 cmd_line += srcs |
| 251 cmd_line += self.link_options | 303 cmd_line += self.link_options |
| 252 else: | 304 else: |
| 253 bin_name = self.GetBinName('ar') | 305 bin_name = self.GetAr() |
| 254 cmd_line = [bin_name, '-rc', out] | 306 cmd_line = [bin_name, '-rc', out] |
| 255 if not self.empty: | 307 if not self.empty: |
| 256 cmd_line += srcs | 308 cmd_line += srcs |
| 257 | 309 |
| 258 MakeDir(os.path.dirname(out)) | 310 MakeDir(os.path.dirname(out)) |
| 259 self.CleanOutput(out) | 311 self.CleanOutput(out) |
| 260 err = self.Run(cmd_line, out) | 312 err = self.Run(cmd_line, out) |
| 261 if sys.platform.startswith('win') and err == 5: | 313 if sys.platform.startswith('win') and err == 5: |
| 262 # Try again on mystery windows failure. | 314 # Try again on mystery windows failure. |
| 263 err = self.Run(cmd_line, out) | 315 err = self.Run(cmd_line, out) |
| 264 if err: | 316 if err: |
| 265 ErrOut('\nFAILED with %d: %s\n\n' % (err, ' '.join(cmd_line))) | 317 ErrOut('\nFAILED with %d: %s\n\n' % (err, ' '.join(cmd_line))) |
| 266 return out | 318 return out |
| 267 | 319 |
| 268 def Strip(self, out): | 320 def Strip(self, out): |
| 269 """Strip the NEXE""" | 321 """Strip the NEXE""" |
| 270 if self.verbose: | 322 if self.verbose: |
| 271 print '\nStrip %s' % out | 323 print '\nStrip %s' % out |
| 272 | 324 |
| 273 tmp = out + '.tmp' | 325 tmp = out + '.tmp' |
| 274 self.CleanOutput(tmp) | 326 self.CleanOutput(tmp) |
| 275 os.rename(out, tmp) | 327 os.rename(out, tmp) |
| 276 bin_name = self.GetBinName('strip') | 328 bin_name = self.GetStrip() |
| 277 cmd_line = [bin_name, '--strip-debug', tmp, '-o', out] | 329 cmd_line = [bin_name, '--strip-debug', tmp, '-o', out] |
| 278 err = self.Run(cmd_line, out) | 330 err = self.Run(cmd_line, out) |
| 279 if sys.platform.startswith('win') and err == 5: | 331 if sys.platform.startswith('win') and err == 5: |
| 280 # Try again on mystery windows failure. | 332 # Try again on mystery windows failure. |
| 281 err = self.Run(cmd_line, out) | 333 err = self.Run(cmd_line, out) |
| 282 if err: | 334 if err: |
| 283 ErrOut('\nFAILED with %d: %s\n\n' % (err, ' '.join(cmd_line))) | 335 ErrOut('\nFAILED with %d: %s\n\n' % (err, ' '.join(cmd_line))) |
| 284 return out | 336 return out |
| 285 | 337 |
| 286 def Generate(self, srcs): | 338 def Generate(self, srcs): |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 343 out = build.Compile(filename) | 395 out = build.Compile(filename) |
| 344 if out: | 396 if out: |
| 345 objs.append(out) | 397 objs.append(out) |
| 346 # Do not link if building an object | 398 # Do not link if building an object |
| 347 if not options.compile_only: | 399 if not options.compile_only: |
| 348 build.Generate(objs) | 400 build.Generate(objs) |
| 349 return 0 | 401 return 0 |
| 350 | 402 |
| 351 if __name__ == '__main__': | 403 if __name__ == '__main__': |
| 352 sys.exit(Main(sys.argv)) | 404 sys.exit(Main(sys.argv)) |
| 353 | |
| OLD | NEW |