waf

FORK: waf with some random patches
git clone https://git.neptards.moe/neptards/waf.git
Log | Files | Refs | README

c_osx.py (5846B)


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