PageRenderTime 25ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/custompopover/mobile/ios/build.py

https://bitbucket.org/plepic/titanium_modules
Python | 217 lines | 199 code | 13 blank | 5 comment | 14 complexity | 78e7071ce59be76f7e1e29dcd690c690 MD5 | raw file
  1. #!/usr/bin/env python
  2. #
  3. # Appcelerator Titanium Module Packager
  4. #
  5. #
  6. import os, subprocess, sys, glob, string
  7. import zipfile
  8. from datetime import date
  9. cwd = os.path.abspath(os.path.dirname(sys._getframe(0).f_code.co_filename))
  10. os.chdir(cwd)
  11. required_module_keys = ['name','version','moduleid','description','copyright','license','copyright','platform','minsdk']
  12. module_defaults = {
  13. 'description':'My module',
  14. 'author': 'Your Name',
  15. 'license' : 'Specify your license',
  16. 'copyright' : 'Copyright (c) %s by Your Company' % str(date.today().year),
  17. }
  18. module_license_default = "TODO: place your license here and we'll include it in the module distribution"
  19. def find_sdk(config):
  20. sdk = config['TITANIUM_SDK']
  21. return os.path.expandvars(os.path.expanduser(sdk))
  22. def replace_vars(config,token):
  23. idx = token.find('$(')
  24. while idx != -1:
  25. idx2 = token.find(')',idx+2)
  26. if idx2 == -1: break
  27. key = token[idx+2:idx2]
  28. if not config.has_key(key): break
  29. token = token.replace('$(%s)' % key, config[key])
  30. idx = token.find('$(')
  31. return token
  32. def read_ti_xcconfig():
  33. contents = open(os.path.join(cwd,'titanium.xcconfig')).read()
  34. config = {}
  35. for line in contents.splitlines(False):
  36. line = line.strip()
  37. if line[0:2]=='//': continue
  38. idx = line.find('=')
  39. if idx > 0:
  40. key = line[0:idx].strip()
  41. value = line[idx+1:].strip()
  42. config[key] = replace_vars(config,value)
  43. return config
  44. def generate_doc(config):
  45. docdir = os.path.join(cwd,'documentation')
  46. if not os.path.exists(docdir):
  47. print "Couldn't find documentation file at: %s" % docdir
  48. return None
  49. try:
  50. import markdown2 as markdown
  51. except ImportError:
  52. import markdown
  53. documentation = []
  54. for file in os.listdir(docdir):
  55. if file in ignoreFiles or os.path.isdir(os.path.join(docdir, file)):
  56. continue
  57. md = open(os.path.join(docdir,file)).read()
  58. html = markdown.markdown(md)
  59. documentation.append({file:html});
  60. return documentation
  61. def compile_js(manifest,config):
  62. js_file = os.path.join(cwd,'assets','ti.custompopover.js')
  63. if not os.path.exists(js_file): return
  64. from compiler import Compiler
  65. try:
  66. import json
  67. except:
  68. import simplejson as json
  69. path = os.path.basename(js_file)
  70. compiler = Compiler(cwd, manifest['moduleid'], manifest['name'], 'commonjs')
  71. metadata = compiler.make_function_from_file(path,js_file)
  72. exports = open('metadata.json','w')
  73. json.dump({'exports':compiler.exports }, exports)
  74. exports.close()
  75. method = metadata['method']
  76. eq = path.replace('.','_')
  77. method = ' return filterData(%s, @"%s");' % (method, manifest['moduleid'])
  78. f = os.path.join(cwd,'Classes','TiCustompopoverModuleAssets.mm')
  79. c = open(f).read()
  80. idx = c.find('return ')
  81. before = c[0:idx]
  82. after = """
  83. }
  84. @end
  85. """
  86. newc = before + method + after
  87. if newc!=c:
  88. x = open(f,'w')
  89. x.write(newc)
  90. x.close()
  91. def die(msg):
  92. print msg
  93. sys.exit(1)
  94. def warn(msg):
  95. print "[WARN] %s" % msg
  96. def validate_license():
  97. c = open(os.path.join(cwd,'LICENSE')).read()
  98. if c.find(module_license_default)!=-1:
  99. warn('please update the LICENSE file with your license text before distributing')
  100. def validate_manifest():
  101. path = os.path.join(cwd,'manifest')
  102. f = open(path)
  103. if not os.path.exists(path): die("missing %s" % path)
  104. manifest = {}
  105. for line in f.readlines():
  106. line = line.strip()
  107. if line[0:1]=='#': continue
  108. if line.find(':') < 0: continue
  109. key,value = line.split(':')
  110. manifest[key.strip()]=value.strip()
  111. for key in required_module_keys:
  112. if not manifest.has_key(key): die("missing required manifest key '%s'" % key)
  113. if module_defaults.has_key(key):
  114. defvalue = module_defaults[key]
  115. curvalue = manifest[key]
  116. if curvalue==defvalue: warn("please update the manifest key: '%s' to a non-default value" % key)
  117. return manifest,path
  118. ignoreFiles = ['.DS_Store','.gitignore','libTitanium.a','titanium.jar','README','ti.custompopover.js']
  119. ignoreDirs = ['.DS_Store','.svn','.git','CVSROOT']
  120. def zip_dir(zf,dir,basepath,ignore=[]):
  121. for root, dirs, files in os.walk(dir):
  122. for name in ignoreDirs:
  123. if name in dirs:
  124. dirs.remove(name) # don't visit ignored directories
  125. for file in files:
  126. if file in ignoreFiles: continue
  127. e = os.path.splitext(file)
  128. if len(e)==2 and e[1]=='.pyc':continue
  129. from_ = os.path.join(root, file)
  130. to_ = from_.replace(dir, basepath, 1)
  131. zf.write(from_, to_)
  132. def glob_libfiles():
  133. files = []
  134. for libfile in glob.glob('build/**/*.a'):
  135. if libfile.find('Release-')!=-1:
  136. files.append(libfile)
  137. return files
  138. def build_module(manifest,config):
  139. rc = os.system("xcodebuild -sdk iphoneos -configuration Release")
  140. if rc != 0:
  141. die("xcodebuild failed")
  142. rc = os.system("xcodebuild -sdk iphonesimulator -configuration Release")
  143. if rc != 0:
  144. die("xcodebuild failed")
  145. # build the merged library using lipo
  146. moduleid = manifest['moduleid']
  147. libpaths = ''
  148. for libfile in glob_libfiles():
  149. libpaths+='%s ' % libfile
  150. os.system("lipo %s -create -output build/lib%s.a" %(libpaths,moduleid))
  151. def package_module(manifest,mf,config):
  152. name = manifest['name'].lower()
  153. moduleid = manifest['moduleid'].lower()
  154. version = manifest['version']
  155. modulezip = '%s-iphone-%s.zip' % (moduleid,version)
  156. if os.path.exists(modulezip): os.remove(modulezip)
  157. zf = zipfile.ZipFile(modulezip, 'w', zipfile.ZIP_DEFLATED)
  158. modulepath = 'modules/iphone/%s/%s' % (moduleid,version)
  159. zf.write(mf,'%s/manifest' % modulepath)
  160. libname = 'lib%s.a' % moduleid
  161. zf.write('build/%s' % libname, '%s/%s' % (modulepath,libname))
  162. docs = generate_doc(config)
  163. if docs!=None:
  164. for doc in docs:
  165. for file, html in doc.iteritems():
  166. filename = string.replace(file,'.md','.html')
  167. zf.writestr('%s/documentation/%s'%(modulepath,filename),html)
  168. for dn in ('assets','example','platform'):
  169. if os.path.exists(dn):
  170. zip_dir(zf,dn,'%s/%s' % (modulepath,dn),['README'])
  171. zf.write('LICENSE','%s/LICENSE' % modulepath)
  172. zf.write('module.xcconfig','%s/module.xcconfig' % modulepath)
  173. exports_file = 'metadata.json'
  174. if os.path.exists(exports_file):
  175. zf.write(exports_file, '%s/%s' % (modulepath, exports_file))
  176. zf.close()
  177. if __name__ == '__main__':
  178. manifest,mf = validate_manifest()
  179. validate_license()
  180. config = read_ti_xcconfig()
  181. sdk = find_sdk(config)
  182. sys.path.insert(0,os.path.join(sdk,'iphone'))
  183. sys.path.append(os.path.join(sdk, "common"))
  184. compile_js(manifest,config)
  185. build_module(manifest,config)
  186. package_module(manifest,mf,config)
  187. sys.exit(0)