| Index: pylib/gyp/mac_tool.py
|
| diff --git a/pylib/gyp/mac_tool.py b/pylib/gyp/mac_tool.py
|
| index 60d4058208b98484bbfa4ce1913f8c460926bd50..6f35823c83c330db3704746a3a36ced0e1b1b6ab 100755
|
| --- a/pylib/gyp/mac_tool.py
|
| +++ b/pylib/gyp/mac_tool.py
|
| @@ -17,6 +17,7 @@ import plistlib
|
| import re
|
| import shutil
|
| import string
|
| +import struct
|
| import subprocess
|
| import sys
|
| import tempfile
|
| @@ -272,6 +273,23 @@ class MacTool(object):
|
| break
|
| return libtoolout.returncode
|
|
|
| + def ExecPackageIosFramework(self, framework):
|
| + # Find the name of the binary based on the part before the ".framework".
|
| + binary = os.path.basename(framework).split('.')[0]
|
| + module_path = os.path.join(framework, 'Modules');
|
| + if not os.path.exists(module_path):
|
| + os.mkdir(module_path)
|
| + module_template = 'framework module %s {\n' \
|
| + ' umbrella header "%s.h"\n' \
|
| + '\n' \
|
| + ' export *\n' \
|
| + ' module * { export * }\n' \
|
| + '}\n' % (binary, binary)
|
| +
|
| + module_file = open(os.path.join(module_path, 'module.modulemap'), "w")
|
| + module_file.write(module_template)
|
| + module_file.close()
|
| +
|
| def ExecPackageFramework(self, framework, version):
|
| """Takes a path to Something.framework and the Current version of that and
|
| sets up all the symlinks."""
|
| @@ -308,6 +326,23 @@ class MacTool(object):
|
| os.remove(link)
|
| os.symlink(dest, link)
|
|
|
| + def ExecCompileIosFrameworkHeaderMap(self, out, framework, *all_headers):
|
| + framework_name = os.path.basename(framework).split('.')[0]
|
| + all_headers = map(os.path.abspath, all_headers)
|
| + filelist = {}
|
| + for header in all_headers:
|
| + filename = os.path.basename(header)
|
| + filelist[filename] = header
|
| + filelist[os.path.join(framework_name, filename)] = header
|
| + WriteHmap(out, filelist)
|
| +
|
| + def ExecCopyIosFrameworkHeaders(self, framework, *copy_headers):
|
| + header_path = os.path.join(framework, 'Headers');
|
| + if not os.path.exists(header_path):
|
| + os.makedirs(header_path)
|
| + for header in copy_headers:
|
| + shutil.copy(header, os.path.join(header_path, os.path.basename(header)))
|
| +
|
| def ExecCompileXcassets(self, keys, *inputs):
|
| """Compiles multiple .xcassets files into a single .car file.
|
|
|
| @@ -601,5 +636,71 @@ class MacTool(object):
|
| return {k: self._ExpandVariables(data[k], substitutions) for k in data}
|
| return data
|
|
|
| +def NextGreaterPowerOf2(x):
|
| + return 2**(x-1).bit_length()
|
| +
|
| +def WriteHmap(output_name, filelist):
|
| + """Generates a header map based on |filelist|.
|
| +
|
| + Per Mark Mentovai:
|
| + A header map is structured essentially as a hash table, keyed by names used
|
| + in #includes, and providing pathnames to the actual files.
|
| +
|
| + The implementation below and the comment above comes from inspecting:
|
| + http://www.opensource.apple.com/source/distcc/distcc-2503/distcc_dist/include_server/headermap.py?txt
|
| + while also looking at the implementation in clang in:
|
| + https://llvm.org/svn/llvm-project/cfe/trunk/lib/Lex/HeaderMap.cpp
|
| + """
|
| + magic = 1751998832
|
| + version = 1
|
| + _reserved = 0
|
| + count = len(filelist)
|
| + capacity = NextGreaterPowerOf2(count)
|
| + strings_offset = 24 + (12 * capacity)
|
| + max_value_length = len(max(filelist.items(), key=lambda (k,v):len(v))[1])
|
| +
|
| + out = open(output_name, "wb")
|
| + out.write(struct.pack('<LHHLLLL', magic, version, _reserved, strings_offset,
|
| + count, capacity, max_value_length))
|
| +
|
| + # Create empty hashmap buckets.
|
| + buckets = [None] * capacity
|
| + for file, path in filelist.items():
|
| + key = 0
|
| + for c in file:
|
| + key += ord(c.lower()) * 13
|
| +
|
| + # Fill next empty bucket.
|
| + while buckets[key & capacity - 1] is not None:
|
| + key = key + 1
|
| + buckets[key & capacity - 1] = (file, path)
|
| +
|
| + next_offset = 1
|
| + for bucket in buckets:
|
| + if bucket is None:
|
| + out.write(struct.pack('<LLL', 0, 0, 0))
|
| + else:
|
| + (file, path) = bucket
|
| + key_offset = next_offset
|
| + prefix_offset = key_offset + len(file) + 1
|
| + suffix_offset = prefix_offset + len(os.path.dirname(path) + os.sep) + 1
|
| + next_offset = suffix_offset + len(os.path.basename(path)) + 1
|
| + out.write(struct.pack('<LLL', key_offset, prefix_offset, suffix_offset))
|
| +
|
| + # Pad byte since next offset starts at 1.
|
| + out.write(struct.pack('<x'))
|
| +
|
| + for bucket in buckets:
|
| + if bucket is not None:
|
| + (file, path) = bucket
|
| + out.write(struct.pack('<%ds' % len(file), file))
|
| + out.write(struct.pack('<s', '\0'))
|
| + base = os.path.dirname(path) + os.sep
|
| + out.write(struct.pack('<%ds' % len(base), base))
|
| + out.write(struct.pack('<s', '\0'))
|
| + path = os.path.basename(path)
|
| + out.write(struct.pack('<%ds' % len(path), path))
|
| + out.write(struct.pack('<s', '\0'))
|
| +
|
| if __name__ == '__main__':
|
| sys.exit(main(sys.argv[1:]))
|
|
|