jack2 codebase
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

189 lines
5.4KB

  1. #!/usr/bin/env python
  2. # encoding: utf-8
  3. # Thomas Nagy 2008-2010
  4. """
  5. MacOSX related tools
  6. """
  7. import os, shutil, sys, platform
  8. from waflib import TaskGen, Task, Build, Options, Utils, Errors
  9. from waflib.TaskGen import taskgen_method, feature, after_method, before_method
  10. app_info = '''
  11. <?xml version="1.0" encoding="UTF-8"?>
  12. <!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
  13. <plist version="0.9">
  14. <dict>
  15. <key>CFBundlePackageType</key>
  16. <string>APPL</string>
  17. <key>CFBundleGetInfoString</key>
  18. <string>Created by Waf</string>
  19. <key>CFBundleSignature</key>
  20. <string>????</string>
  21. <key>NOTE</key>
  22. <string>THIS IS A GENERATED FILE, DO NOT MODIFY</string>
  23. <key>CFBundleExecutable</key>
  24. <string>%s</string>
  25. </dict>
  26. </plist>
  27. '''
  28. """
  29. plist template
  30. """
  31. @feature('c', 'cxx')
  32. def set_macosx_deployment_target(self):
  33. """
  34. see WAF issue 285 and also and also http://trac.macports.org/ticket/17059
  35. """
  36. if self.env['MACOSX_DEPLOYMENT_TARGET']:
  37. os.environ['MACOSX_DEPLOYMENT_TARGET'] = self.env['MACOSX_DEPLOYMENT_TARGET']
  38. elif 'MACOSX_DEPLOYMENT_TARGET' not in os.environ:
  39. if Utils.unversioned_sys_platform() == 'darwin':
  40. os.environ['MACOSX_DEPLOYMENT_TARGET'] = '.'.join(platform.mac_ver()[0].split('.')[:2])
  41. @taskgen_method
  42. def create_bundle_dirs(self, name, out):
  43. """
  44. Create bundle folders, used by :py:func:`create_task_macplist` and :py:func:`create_task_macapp`
  45. """
  46. bld = self.bld
  47. dir = out.parent.find_or_declare(name)
  48. dir.mkdir()
  49. macos = dir.find_or_declare(['Contents', 'MacOS'])
  50. macos.mkdir()
  51. return dir
  52. def bundle_name_for_output(out):
  53. name = out.name
  54. k = name.rfind('.')
  55. if k >= 0:
  56. name = name[:k] + '.app'
  57. else:
  58. name = name + '.app'
  59. return name
  60. @feature('cprogram', 'cxxprogram')
  61. @after_method('apply_link')
  62. def create_task_macapp(self):
  63. """
  64. To compile an executable into a Mac application (a .app), set its *mac_app* attribute::
  65. def build(bld):
  66. bld.shlib(source='a.c', target='foo', mac_app = True)
  67. To force *all* executables to be transformed into Mac applications::
  68. def build(bld):
  69. bld.env.MACAPP = True
  70. bld.shlib(source='a.c', target='foo')
  71. """
  72. if self.env['MACAPP'] or getattr(self, 'mac_app', False):
  73. out = self.link_task.outputs[0]
  74. name = bundle_name_for_output(out)
  75. dir = self.create_bundle_dirs(name, out)
  76. n1 = dir.find_or_declare(['Contents', 'MacOS', out.name])
  77. self.apptask = self.create_task('macapp', self.link_task.outputs, n1)
  78. inst_to = getattr(self, 'install_path', '/Applications') + '/%s/Contents/MacOS/' % name
  79. self.bld.install_files(inst_to, n1, chmod=Utils.O755)
  80. if getattr(self, 'mac_resources', None):
  81. res_dir = n1.parent.parent.make_node('Resources')
  82. inst_to = getattr(self, 'install_path', '/Applications') + '/%s/Resources' % name
  83. for x in self.to_list(self.mac_resources):
  84. node = self.path.find_node(x)
  85. if not node:
  86. raise Errors.WafError('Missing mac_resource %r in %r' % (x, self))
  87. parent = node.parent
  88. if os.path.isdir(node.abspath()):
  89. nodes = node.ant_glob('**')
  90. else:
  91. nodes = [node]
  92. for node in nodes:
  93. rel = node.path_from(parent)
  94. tsk = self.create_task('macapp', node, res_dir.make_node(rel))
  95. self.bld.install_as(inst_to + '/%s' % rel, node)
  96. if getattr(self.bld, 'is_install', None):
  97. # disable the normal binary installation
  98. self.install_task.hasrun = Task.SKIP_ME
  99. @feature('cprogram', 'cxxprogram')
  100. @after_method('apply_link')
  101. def create_task_macplist(self):
  102. """
  103. Create a :py:class:`waflib.Tools.c_osx.macplist` instance.
  104. """
  105. if self.env['MACAPP'] or getattr(self, 'mac_app', False):
  106. out = self.link_task.outputs[0]
  107. name = bundle_name_for_output(out)
  108. dir = self.create_bundle_dirs(name, out)
  109. n1 = dir.find_or_declare(['Contents', 'Info.plist'])
  110. self.plisttask = plisttask = self.create_task('macplist', [], n1)
  111. if getattr(self, 'mac_plist', False):
  112. node = self.path.find_resource(self.mac_plist)
  113. if node:
  114. plisttask.inputs.append(node)
  115. else:
  116. plisttask.code = self.mac_plist
  117. else:
  118. plisttask.code = app_info % self.link_task.outputs[0].name
  119. inst_to = getattr(self, 'install_path', '/Applications') + '/%s/Contents/' % name
  120. self.bld.install_files(inst_to, n1)
  121. @feature('cshlib', 'cxxshlib')
  122. @before_method('apply_link', 'propagate_uselib_vars')
  123. def apply_bundle(self):
  124. """
  125. To make a bundled shared library (a ``.bundle``), set the *mac_bundle* attribute::
  126. def build(bld):
  127. bld.shlib(source='a.c', target='foo', mac_bundle = True)
  128. To force *all* executables to be transformed into bundles::
  129. def build(bld):
  130. bld.env.MACBUNDLE = True
  131. bld.shlib(source='a.c', target='foo')
  132. """
  133. if self.env['MACBUNDLE'] or getattr(self, 'mac_bundle', False):
  134. self.env['LINKFLAGS_cshlib'] = self.env['LINKFLAGS_cxxshlib'] = [] # disable the '-dynamiclib' flag
  135. self.env['cshlib_PATTERN'] = self.env['cxxshlib_PATTERN'] = self.env['macbundle_PATTERN']
  136. use = self.use = self.to_list(getattr(self, 'use', []))
  137. if not 'MACBUNDLE' in use:
  138. use.append('MACBUNDLE')
  139. app_dirs = ['Contents', 'Contents/MacOS', 'Contents/Resources']
  140. class macapp(Task.Task):
  141. """
  142. Create mac applications
  143. """
  144. color = 'PINK'
  145. def run(self):
  146. self.outputs[0].parent.mkdir()
  147. shutil.copy2(self.inputs[0].srcpath(), self.outputs[0].abspath())
  148. class macplist(Task.Task):
  149. """
  150. Create plist files
  151. """
  152. color = 'PINK'
  153. ext_in = ['.bin']
  154. def run(self):
  155. if getattr(self, 'code', None):
  156. txt = self.code
  157. else:
  158. txt = self.inputs[0].read()
  159. self.outputs[0].write(txt)