Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright (c) 2012 Google Inc. All rights reserved. | 2 # Copyright (c) 2012 Google Inc. 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 """Utility functions to perform Xcode-style build steps. | 6 """Utility functions to perform Xcode-style build steps. |
| 7 | 7 |
| 8 These functions are executed via gyp-mac-tool when using the Makefile generator. | 8 These functions are executed via gyp-mac-tool when using the Makefile generator. |
| 9 """ | 9 """ |
| 10 | 10 |
| 11 import fcntl | 11 import fcntl |
| 12 import fnmatch | 12 import fnmatch |
| 13 import glob | 13 import glob |
| 14 import json | 14 import json |
| 15 import os | 15 import os |
| 16 import plistlib | 16 import plistlib |
| 17 import re | 17 import re |
| 18 import shutil | 18 import shutil |
| 19 import string | 19 import string |
| 20 import struct | |
| 20 import subprocess | 21 import subprocess |
| 21 import sys | 22 import sys |
| 22 import tempfile | 23 import tempfile |
| 23 | 24 |
| 24 | 25 |
| 25 def main(args): | 26 def main(args): |
| 26 executor = MacTool() | 27 executor = MacTool() |
| 27 exit_code = executor.Dispatch(args) | 28 exit_code = executor.Dispatch(args) |
| 28 if exit_code is not None: | 29 if exit_code is not None: |
| 29 sys.exit(exit_code) | 30 sys.exit(exit_code) |
| (...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 265 print >>sys.stderr, line | 266 print >>sys.stderr, line |
| 266 # Unconditionally touch the output .a file on the command line if present | 267 # Unconditionally touch the output .a file on the command line if present |
| 267 # and the command succeeded. A bit hacky. | 268 # and the command succeeded. A bit hacky. |
| 268 if not libtoolout.returncode: | 269 if not libtoolout.returncode: |
| 269 for i in range(len(cmd_list) - 1): | 270 for i in range(len(cmd_list) - 1): |
| 270 if cmd_list[i] == "-o" and cmd_list[i+1].endswith('.a'): | 271 if cmd_list[i] == "-o" and cmd_list[i+1].endswith('.a'): |
| 271 os.utime(cmd_list[i+1], None) | 272 os.utime(cmd_list[i+1], None) |
| 272 break | 273 break |
| 273 return libtoolout.returncode | 274 return libtoolout.returncode |
| 274 | 275 |
| 276 def ExecPackageIosFramework(self, framework): | |
| 277 # Find the name of the binary based on the part before the ".framework". | |
| 278 binary = os.path.basename(framework).split('.')[0] | |
| 279 module_path = os.path.join(framework, 'Modules'); | |
| 280 if not os.path.exists(module_path): | |
| 281 os.mkdir(module_path) | |
| 282 module_template = 'framework module %s {\n' \ | |
| 283 ' umbrella header "%s.h"\n' \ | |
| 284 '\n' \ | |
| 285 ' export *\n' \ | |
| 286 ' module * { export * }\n' \ | |
| 287 '}\n' % (binary, binary) | |
| 288 | |
| 289 module_file = open(os.path.join(module_path, 'module.modulemap'), "w") | |
| 290 module_file.write(module_template) | |
| 291 module_file.close() | |
| 292 | |
| 293 | |
| 275 def ExecPackageFramework(self, framework, version): | 294 def ExecPackageFramework(self, framework, version): |
| 276 """Takes a path to Something.framework and the Current version of that and | 295 """Takes a path to Something.framework and the Current version of that and |
| 277 sets up all the symlinks.""" | 296 sets up all the symlinks.""" |
| 278 # Find the name of the binary based on the part before the ".framework". | 297 # Find the name of the binary based on the part before the ".framework". |
| 279 binary = os.path.basename(framework).split('.')[0] | 298 binary = os.path.basename(framework).split('.')[0] |
| 280 | 299 |
| 281 CURRENT = 'Current' | 300 CURRENT = 'Current' |
| 282 RESOURCES = 'Resources' | 301 RESOURCES = 'Resources' |
| 283 VERSIONS = 'Versions' | 302 VERSIONS = 'Versions' |
| 284 | 303 |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 301 # Back to where we were before! | 320 # Back to where we were before! |
| 302 os.chdir(pwd) | 321 os.chdir(pwd) |
| 303 | 322 |
| 304 def _Relink(self, dest, link): | 323 def _Relink(self, dest, link): |
| 305 """Creates a symlink to |dest| named |link|. If |link| already exists, | 324 """Creates a symlink to |dest| named |link|. If |link| already exists, |
| 306 it is overwritten.""" | 325 it is overwritten.""" |
| 307 if os.path.lexists(link): | 326 if os.path.lexists(link): |
| 308 os.remove(link) | 327 os.remove(link) |
| 309 os.symlink(dest, link) | 328 os.symlink(dest, link) |
| 310 | 329 |
| 330 def ExecCompileIosFrameworkHeaderMap(self, out, framework, *all_headers): | |
| 331 framework_name = os.path.basename(framework).split('.')[0] | |
| 332 all_headers = map(os.path.abspath, all_headers) | |
| 333 filelist = {} | |
| 334 for header in all_headers: | |
| 335 filename = os.path.basename(header) | |
| 336 filelist[filename] = header | |
| 337 filelist[os.path.join(framework_name, filename)] = header | |
| 338 WriteHmap(out, filelist) | |
| 339 | |
| 340 def ExecCopyIosFrameworkHeaders(self, framework, *copy_headers): | |
| 341 header_path = os.path.join(framework, 'Headers'); | |
| 342 if not os.path.exists(header_path): | |
| 343 os.makedirs(header_path) | |
| 344 for header in copy_headers: | |
| 345 shutil.copy2(header, os.path.join(header_path, os.path.basename(header))) | |
|
sdefresne
2016/03/18 15:59:00
nit: why do you need copy2? Is it really important
justincohen
2016/03/19 03:57:00
Done.
| |
| 346 | |
| 311 def ExecCompileXcassets(self, keys, *inputs): | 347 def ExecCompileXcassets(self, keys, *inputs): |
| 312 """Compiles multiple .xcassets files into a single .car file. | 348 """Compiles multiple .xcassets files into a single .car file. |
| 313 | 349 |
| 314 This invokes 'actool' to compile all the inputs .xcassets files. The | 350 This invokes 'actool' to compile all the inputs .xcassets files. The |
| 315 |keys| arguments is a json-encoded dictionary of extra arguments to | 351 |keys| arguments is a json-encoded dictionary of extra arguments to |
| 316 pass to 'actool' when the asset catalogs contains an application icon | 352 pass to 'actool' when the asset catalogs contains an application icon |
| 317 or a launch image. | 353 or a launch image. |
| 318 | 354 |
| 319 Note that 'actool' does not create the Assets.car file if the asset | 355 Note that 'actool' does not create the Assets.car file if the asset |
| 320 catalogs does not contains imageset. | 356 catalogs does not contains imageset. |
| (...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 594 if isinstance(data, str): | 630 if isinstance(data, str): |
| 595 for key, value in substitutions.iteritems(): | 631 for key, value in substitutions.iteritems(): |
| 596 data = data.replace('$(%s)' % key, value) | 632 data = data.replace('$(%s)' % key, value) |
| 597 return data | 633 return data |
| 598 if isinstance(data, list): | 634 if isinstance(data, list): |
| 599 return [self._ExpandVariables(v, substitutions) for v in data] | 635 return [self._ExpandVariables(v, substitutions) for v in data] |
| 600 if isinstance(data, dict): | 636 if isinstance(data, dict): |
| 601 return {k: self._ExpandVariables(data[k], substitutions) for k in data} | 637 return {k: self._ExpandVariables(data[k], substitutions) for k in data} |
| 602 return data | 638 return data |
| 603 | 639 |
| 640 def NextGreaterPowerOf2(x): | |
| 641 return 2**(x-1).bit_length() | |
| 642 | |
| 643 def WriteHmap(output_name, filelist): | |
| 644 print "hi" | |
|
sdefresne
2016/03/18 15:59:00
Debug?
justincohen
2016/03/19 03:57:00
oooof.
| |
| 645 """Generates a header map based on |filelist|. | |
| 646 | |
| 647 Per Mark Mentovai: | |
| 648 A header map is structured essentially as a hash table, keyed by names used | |
| 649 in #includes, and providing pathnames to the actual files. | |
| 650 | |
| 651 The implementation below and the comment above comes from inspecting: | |
| 652 http://www.opensource.apple.com/source/distcc/distcc-2503/distcc_dist/includ e_server/headermap.py?txt | |
| 653 while also looking at the implementation in clang in: | |
| 654 https://llvm.org/svn/llvm-project/cfe/trunk/lib/Lex/HeaderMap.cpp | |
| 655 """ | |
| 656 magic = 1751998832 | |
| 657 version = 1 | |
| 658 _reserved = 0 | |
| 659 count = len(filelist) | |
| 660 capacity = NextGreaterPowerOf2(count) | |
| 661 strings_offset = 24 + (12 * capacity) | |
| 662 max_value_length = len(max(filelist.items(), key=lambda (k,v):len(v))[1]) | |
| 663 | |
| 664 out = open(output_name, "wb") | |
| 665 out.write(struct.pack('<LHHLLLL', magic, version, _reserved, strings_offset, | |
| 666 count, capacity, max_value_length)) | |
| 667 | |
| 668 # Create empty hashmap buckets. | |
| 669 buckets = [None] * capacity | |
| 670 for file, path in filelist.items(): | |
| 671 key = 0 | |
| 672 for c in file: | |
| 673 key += ord(c.lower()) * 13 | |
| 674 | |
| 675 # Fill next empty bucket. | |
| 676 while buckets[key & capacity - 1] is not None: | |
| 677 key = key + 1 | |
| 678 buckets[key & capacity - 1] = (file, path) | |
| 679 | |
| 680 next_offset = 1 | |
| 681 for bucket in buckets: | |
| 682 if bucket is None: | |
| 683 out.write(struct.pack('<LLL', 0, 0, 0)) | |
| 684 else: | |
| 685 (file, path) = bucket | |
| 686 key_offset = next_offset | |
| 687 prefix_offset = key_offset + len(file) + 1 | |
| 688 suffix_offset = prefix_offset + len(os.path.dirname(path) + os.sep) + 1 | |
| 689 next_offset = suffix_offset + len(os.path.basename(path)) + 1 | |
| 690 out.write(struct.pack('<LLL', key_offset, prefix_offset, suffix_offset)) | |
| 691 | |
| 692 # Pad byte since next offset starts at 1. | |
| 693 out.write(struct.pack('<x')) | |
| 694 | |
| 695 for bucket in buckets: | |
| 696 if bucket is not None: | |
| 697 (file, path) = bucket | |
| 698 out.write(struct.pack('<%ds' % len(file), file)) | |
| 699 out.write(struct.pack('<s', '\0')) | |
| 700 base = os.path.dirname(path) + os.sep | |
| 701 out.write(struct.pack('<%ds' % len(base), base)) | |
| 702 out.write(struct.pack('<s', '\0')) | |
| 703 path = os.path.basename(path) | |
| 704 out.write(struct.pack('<%ds' % len(path), path)) | |
| 705 out.write(struct.pack('<s', '\0')) | |
| 706 | |
| 604 if __name__ == '__main__': | 707 if __name__ == '__main__': |
| 605 sys.exit(main(sys.argv[1:])) | 708 sys.exit(main(sys.argv[1:])) |
| OLD | NEW |