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