1#!/usr/bin/env python 2import subprocess 3import re 4import os 5import errno 6import collections 7import sys 8 9class Platform(object): 10 pass 11 12sdk_re = re.compile(r'.*-sdk ([a-zA-Z0-9.]*)') 13 14def sdkinfo(sdkname): 15 ret = {} 16 for line in subprocess.Popen(['xcodebuild', '-sdk', sdkname, '-version'], stdout=subprocess.PIPE).stdout: 17 kv = line.strip().split(': ', 1) 18 if len(kv) == 2: 19 k,v = kv 20 ret[k] = v 21 return ret 22 23desktop_sdk_info = sdkinfo('macosx') 24 25def latest_sdks(): 26 latest_desktop = None 27 for line in subprocess.Popen(['xcodebuild', '-showsdks'], stdout=subprocess.PIPE).stdout: 28 match = sdk_re.match(line) 29 if match: 30 if 'OS X' in line: 31 latest_desktop = match.group(1) 32 33 return latest_desktop 34 35desktop_sdk = latest_sdks() 36 37class desktop_platform_32(Platform): 38 sdk='macosx' 39 arch = 'i386' 40 name = 'mac32' 41 triple = 'i386-apple-darwin10' 42 sdkroot = desktop_sdk_info['Path'] 43 44 prefix = "#if defined(__i386__) && !defined(__x86_64__)\n\n" 45 suffix = "\n\n#endif" 46 47class desktop_platform_64(Platform): 48 sdk='macosx' 49 arch = 'x86_64' 50 name = 'mac' 51 triple = 'x86_64-apple-darwin10' 52 sdkroot = desktop_sdk_info['Path'] 53 54 prefix = "#if !defined(__i386__) && defined(__x86_64__)\n\n" 55 suffix = "\n\n#endif" 56 57def move_file(src_dir, dst_dir, filename, file_suffix=None, prefix='', suffix=''): 58 if not os.path.exists(dst_dir): 59 os.makedirs(dst_dir) 60 61 out_filename = filename 62 63 if file_suffix: 64 split_name = os.path.splitext(filename) 65 out_filename = "%s_%s%s" % (split_name[0], file_suffix, split_name[1]) 66 67 with open(os.path.join(src_dir, filename)) as in_file: 68 with open(os.path.join(dst_dir, out_filename), 'w') as out_file: 69 if prefix: 70 out_file.write(prefix) 71 72 out_file.write(in_file.read()) 73 74 if suffix: 75 out_file.write(suffix) 76 77headers_seen = collections.defaultdict(set) 78 79def move_source_tree(src_dir, dest_dir, dest_include_dir, arch=None, prefix=None, suffix=None): 80 for root, dirs, files in os.walk(src_dir, followlinks=True): 81 relroot = os.path.relpath(root,src_dir) 82 83 def move_dir(arch, prefix='', suffix='', files=[]): 84 for file in files: 85 file_suffix = None 86 if file.endswith('.h'): 87 if dest_include_dir: 88 file_suffix = arch 89 if arch: 90 headers_seen[file].add(arch) 91 move_file(root, dest_include_dir, file, arch, prefix=prefix, suffix=suffix) 92 93 elif dest_dir: 94 outroot = os.path.join(dest_dir, relroot) 95 move_file(root, outroot, file, prefix=prefix, suffix=suffix) 96 97 if relroot == '.': 98 move_dir(arch=arch, 99 files=files, 100 prefix=prefix, 101 suffix=suffix) 102 elif relroot == 'x86': 103 move_dir(arch='i386', 104 prefix="#if defined(__i386__) && !defined(__x86_64__)\n\n", 105 suffix="\n\n#endif", 106 files=files) 107 move_dir(arch='x86_64', 108 prefix="#if !defined(__i386__) && defined(__x86_64__)\n\n", 109 suffix="\n\n#endif", 110 files=files) 111 112def build_target(platform): 113 def xcrun_cmd(cmd): 114 return subprocess.check_output(['xcrun', '-sdk', platform.sdkroot, '-find', cmd]).strip() 115 116 build_dir = 'build_' + platform.name 117 if not os.path.exists(build_dir): 118 os.makedirs(build_dir) 119 env = dict(CC=xcrun_cmd('clang'), 120 LD=xcrun_cmd('ld'), 121 CFLAGS='-arch %s -isysroot %s -mmacosx-version-min=10.6' % (platform.arch, platform.sdkroot)) 122 working_dir=os.getcwd() 123 try: 124 os.chdir(build_dir) 125 subprocess.check_call(['../configure', '-host', platform.triple], env=env) 126 move_source_tree('.', None, '../osx/include', 127 arch=platform.arch, 128 prefix=platform.prefix, 129 suffix=platform.suffix) 130 move_source_tree('./include', None, '../osx/include', 131 arch=platform.arch, 132 prefix=platform.prefix, 133 suffix=platform.suffix) 134 finally: 135 os.chdir(working_dir) 136 137 for header_name, archs in headers_seen.iteritems(): 138 basename, suffix = os.path.splitext(header_name) 139 140def main(): 141 move_source_tree('src', 'osx/src', 'osx/include') 142 move_source_tree('include', None, 'osx/include') 143 build_target(desktop_platform_32) 144 build_target(desktop_platform_64) 145 146 for header_name, archs in headers_seen.iteritems(): 147 basename, suffix = os.path.splitext(header_name) 148 with open(os.path.join('osx/include', header_name), 'w') as header: 149 for arch in archs: 150 header.write('#include <%s_%s%s>\n' % (basename, arch, suffix)) 151 152if __name__ == '__main__': 153 main() 154