|
#!/usr/bin/env python |
|
|
|
import os |
|
|
|
local_base_dir = os.path.dirname(os.path.abspath(__file__)) |
|
source_map_path = 'build/swift_gyb_processed' |
|
|
|
def _walk(top, sub='', topdown=True, onerror=None, followlinks=False): |
|
'''Tweaked version of os.walk |
|
Changed from os.walk to returning subpath based on top instead top itself. |
|
''' |
|
|
|
try: |
|
names = os.listdir(os.path.join(top, sub)) |
|
except os.error as err: |
|
if onerror is not None: |
|
onerror(err) |
|
return |
|
|
|
dirs, nondirs = [], [] |
|
for name in names: |
|
if os.path.isdir(os.path.join(os.path.join(top, sub), name)): |
|
dirs.append(name) |
|
else: |
|
nondirs.append(name) |
|
|
|
if topdown: |
|
yield sub, dirs, nondirs |
|
for name in dirs: |
|
if followlinks or not os.path.islink(os.path.join(top, sub, name)): |
|
for x in _walk(top, os.path.join(sub, name), topdown, onerror, followlinks): |
|
yield x |
|
if not topdown: |
|
yield sub, dirs, nondirs |
|
|
|
def create_symbol_map_entries(directories, symbol_map_path): |
|
import fnmatch |
|
import re |
|
import subprocess |
|
symbol_map_path_expanded = os.path.expanduser(symbol_map_path) |
|
|
|
created = False |
|
prog = re.compile('^UUID: (?P<uuid>[-0-9A-Z]{36}) \(.*\) (?P<path>.*)$') |
|
for directory in directories: |
|
if os.path.islink(directory): continue |
|
for sub_dirpath, dirnames, filenames in _walk(directory, topdown=False): |
|
for dirname in fnmatch.filter(dirnames, '*.dSYM'): |
|
output = subprocess.check_output(['dwarfdump', '-u', os.path.join(directory, sub_dirpath, dirname)]) |
|
match = prog.match(output) |
|
if not match: continue |
|
|
|
uuid = match.group('uuid').replace('-','') |
|
uuid_components = [uuid[0:4], uuid[4:8], uuid[8:12], uuid[12:16], uuid[16:20], uuid[20:]] |
|
symlink_dir = os.path.join(symbol_map_path_expanded, *uuid_components[:-1]) |
|
if not os.path.exists(symlink_dir): os.makedirs(symlink_dir) |
|
|
|
dsym_path = match.group('path') |
|
symlink_path = os.path.join(symbol_map_path_expanded, *uuid_components) |
|
|
|
should_create = False |
|
if os.path.exists(symlink_path): |
|
if os.path.islink(symlink_path) and os.path.realpath(symlink_path) != dsym_path: |
|
os.remove(symlink_path) |
|
should_create = True |
|
else: |
|
should_create = True |
|
|
|
if should_create: |
|
created = True |
|
os.symlink(dsym_path, symlink_path) |
|
print('create map: {} -> {}'.format(os.path.join(symbol_map_path, *uuid_components), dsym_path)) |
|
return created |
|
|
|
def remove_orphan_symbol_map_entries(symbol_map_path): |
|
symbol_map_path_expanded = os.path.expanduser(symbol_map_path) |
|
for sub_dirpath, dirnames, filenames in _walk(symbol_map_path_expanded, topdown=False): |
|
for filename in filenames: |
|
target = os.path.join(symbol_map_path_expanded, sub_dirpath, filename) |
|
if os.path.islink(target) and not os.path.exists(target): |
|
print('remove deadlink: {} -> {}'.format(os.path.join(symbol_map_path, sub_dirpath, filename), os.path.realpath(target))) |
|
os.remove(target) |
|
|
|
def cleanup_symbol_map(symbol_map_path): |
|
symbol_map_path_expanded = os.path.expanduser(symbol_map_path) |
|
for sub_dirpath, dirnames, filenames in _walk(symbol_map_path_expanded, topdown=False): |
|
if len(dirnames) == 0 and len(filenames) == 0: |
|
try: os.removedirs(os.path.join(symbol_map_path_expanded, sub_dirpath)) |
|
except: continue |
|
|
|
def update_symbol_map(args): |
|
import string |
|
|
|
directories = ['/Library/Developer/Toolchains', '~/Library/Developer/Toolchains'] |
|
symbol_map_path = '~/Library/Developer/SymbolMap/uuids' |
|
|
|
remove_orphan_symbol_map_entries(symbol_map_path) |
|
created = create_symbol_map_entries(directories, symbol_map_path) |
|
cleanup_symbol_map(symbol_map_path) |
|
|
|
if created: |
|
defaults_write_args = ['defaults', 'write', 'com.apple.DebugSymbols', 'DBGFileMappedPaths', symbol_map_path] |
|
print('\nYou need to enable symbol map by following command:\n```\n{}\n```'.format(string.join(defaults_write_args, ' ')) ) |
|
|
|
def source_map(args): |
|
import lldb |
|
remote_base_dirs = ['/Users/buildnode/jenkins/workspace/oss-swift-package-osx'] |
|
for version in args.versions: |
|
remote_base_dirs.append('/Users/buildnode/jenkins/workspace/oss-swift-{}-package-osx'.format(version)) |
|
|
|
remote_local_subdir_map = [ |
|
('build/buildbot_osx', source_map_path), |
|
('clang', 'clang'), |
|
('cmark', 'cmark'), |
|
('compiler-rt', 'compiler-rt'), |
|
('llbuild', 'llbuild'), |
|
('lldb', 'lldb'), |
|
('llvm', 'llvm'), |
|
('swift', 'swift'), |
|
('swift-corelibs-foundation', 'swift-corelibs-foundation'), |
|
('swift-corelibs-libdispatch', 'swift-corelibs-libdispatch'), |
|
('swift-corelibs-xctest', 'swift-corelibs-xctest'), |
|
('swift-integration-tests', 'swift-integration-tests'), |
|
('swift-xcode-playground-support', 'swift-xcode-playground-support'), |
|
('swiftpm', 'swiftpm') |
|
] |
|
for remote_base_dir in remote_base_dirs: |
|
for remote_sub_dir, local_sub_dir in remote_local_subdir_map: |
|
remote_path = os.path.join(remote_base_dir, remote_sub_dir) |
|
local_path = os.path.join(local_base_dir, local_sub_dir) |
|
if os.path.exists(local_path): |
|
args.debugger.HandleCommand('settings append target.source-map {} {}'.format(remote_path, local_path)) |
|
|
|
def process_gyb(args): |
|
import fnmatch |
|
import subprocess |
|
|
|
gyb = 'swift/utils/gyb' |
|
stdlib_path = 'swift/stdlib' |
|
output_base_path = os.path.join(source_map_path, 'swift-macosx-x86_64/stdlib') |
|
|
|
if os.getcwd() != args.swift_source_root: |
|
gyb = os.path.join(args.swift_source_root, gyb) |
|
stdlib_path = os.path.join(args.swift_source_root, stdlib_path) |
|
output_base_path = os.path.join(args.swift_source_root, output_base_path) |
|
|
|
for sub_dirpath, dirnames, filenames in _walk(stdlib_path, topdown=False): |
|
for filename in fnmatch.filter(filenames, '*.swift.gyb'): |
|
for size in ['4', '8']: |
|
gyb_path = os.path.join(stdlib_path, sub_dirpath, filename) |
|
target_dir = os.path.join(output_base_path, sub_dirpath, size) |
|
if not os.path.exists(target_dir): os.makedirs(target_dir) |
|
target_path = os.path.join(target_dir, os.path.splitext(filename)[0]) |
|
print('{} -> {}'.format(gyb_path, target_path)) |
|
subprocess.call( |
|
[gyb, '-D', 'CMAKE_SIZEOF_VOID_P={}'.format(size), '-o', target_path, gyb_path] |
|
) |
|
|
|
def create_options(): |
|
import argparse |
|
import sys |
|
parser = argparse.ArgumentParser(prog='swift_oss_helper') |
|
subparsers = parser.add_subparsers(dest='cmd') |
|
parser_update_symbol_map = subparsers.add_parser( |
|
'update-symbol-map', |
|
help ='update symbol map from paths containing `.dSYMs`') |
|
parser_update_symbol_map.set_defaults(func=update_symbol_map) |
|
|
|
parser_process_gyb = subparsers.add_parser( |
|
'process-gyb', |
|
help='process `*.swift.gyb` files in `swift/stdlib`') |
|
parser_process_gyb.add_argument( |
|
'-s', |
|
default=local_base_dir, |
|
help='(default: {})'.format(local_base_dir), |
|
dest='swift_source_root') |
|
parser_process_gyb.set_defaults(func=process_gyb) |
|
|
|
if sys.modules.has_key('lldb'): |
|
parser_source_map = subparsers.add_parser( |
|
'source-map', |
|
help='set `target.source-map` setting for using source files of Swift') |
|
parser_source_map.add_argument('versions', default=[], nargs='*') |
|
parser_source_map.set_defaults(func=source_map) |
|
|
|
parser.set_defaults(cmd='process-gyb') |
|
return parser |
|
|
|
def lldbmain(debugger, command, result, internal_dict): |
|
import shlex |
|
parser = create_options() |
|
args = parser.parse_args(shlex.split(command)) |
|
args.debugger=debugger |
|
args.func(args) |
|
|
|
def __lldb_init_module(debugger,internal_dict): |
|
parser = create_options() |
|
lldbmain.__doc__ = parser.format_help() |
|
debugger.HandleCommand('command script add -f swift_oss_helper.lldbmain swift_oss_helper') |
|
print('swift_oss_helper command enabled.') |
|
|
|
def main(): |
|
parser = create_options() |
|
args = parser.parse_args() |
|
args.func(args) |
|
|
|
if __name__ == '__main__': |
|
main() |