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