s4:lib/messaging: terminate the irpc_servers_byname() result with server_id_set_disco...
[Samba/gebeck_regimport.git] / buildtools / wafadmin / Tools / osx.py
blob561eca487dedf329513d59d8a95b780f5874bc8f
1 #!/usr/bin/env python
2 # encoding: utf-8
3 # Thomas Nagy 2008
5 """MacOSX related tools
7 To compile an executable into a Mac application bundle (a .app), set its 'mac_app' attribute
8 obj.mac_app = True
10 To make a bundled shared library (a .bundle), set the 'mac_bundle' attribute:
11 obj.mac_bundle = True
12 """
14 import os, shutil, sys, platform
15 import TaskGen, Task, Build, Options, Utils
16 from TaskGen import taskgen, feature, after, before
17 from Logs import error, debug
19 # plist template
20 app_info = '''
21 <?xml version="1.0" encoding="UTF-8"?>
22 <!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
23 <plist version="0.9">
24 <dict>
25 <key>CFBundlePackageType</key>
26 <string>APPL</string>
27 <key>CFBundleGetInfoString</key>
28 <string>Created by Waf</string>
29 <key>CFBundleSignature</key>
30 <string>????</string>
31 <key>NOTE</key>
32 <string>THIS IS A GENERATED FILE, DO NOT MODIFY</string>
33 <key>CFBundleExecutable</key>
34 <string>%s</string>
35 </dict>
36 </plist>
37 '''
39 # see WAF issue 285
40 # and also http://trac.macports.org/ticket/17059
41 @feature('cc', 'cxx')
42 @before('apply_lib_vars')
43 def set_macosx_deployment_target(self):
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 sys.platform == 'darwin':
48 os.environ['MACOSX_DEPLOYMENT_TARGET'] = '.'.join(platform.mac_ver()[0].split('.')[:2])
50 @feature('cc', 'cxx')
51 @after('apply_lib_vars')
52 def apply_framework(self):
53 for x in self.to_list(self.env['FRAMEWORKPATH']):
54 frameworkpath_st = '-F%s'
55 self.env.append_unique('CXXFLAGS', frameworkpath_st % x)
56 self.env.append_unique('CCFLAGS', frameworkpath_st % x)
57 self.env.append_unique('LINKFLAGS', frameworkpath_st % x)
59 for x in self.to_list(self.env['FRAMEWORK']):
60 self.env.append_value('LINKFLAGS', ['-framework', x])
62 @taskgen
63 def create_bundle_dirs(self, name, out):
64 bld = self.bld
65 dir = out.parent.get_dir(name)
67 if not dir:
68 dir = out.__class__(name, out.parent, 1)
69 bld.rescan(dir)
70 contents = out.__class__('Contents', dir, 1)
71 bld.rescan(contents)
72 macos = out.__class__('MacOS', contents, 1)
73 bld.rescan(macos)
74 return dir
76 def bundle_name_for_output(out):
77 name = out.name
78 k = name.rfind('.')
79 if k >= 0:
80 name = name[:k] + '.app'
81 else:
82 name = name + '.app'
83 return name
85 @taskgen
86 @after('apply_link')
87 @feature('cprogram')
88 def create_task_macapp(self):
89 """Use env['MACAPP'] to force *all* executables to be transformed into Mac applications
90 or use obj.mac_app = True to build specific targets as Mac apps"""
91 if self.env['MACAPP'] or getattr(self, 'mac_app', False):
92 apptask = self.create_task('macapp')
93 apptask.set_inputs(self.link_task.outputs)
95 out = self.link_task.outputs[0]
97 name = bundle_name_for_output(out)
98 dir = self.create_bundle_dirs(name, out)
100 n1 = dir.find_or_declare(['Contents', 'MacOS', out.name])
102 apptask.set_outputs([n1])
103 apptask.chmod = 0755
104 apptask.install_path = os.path.join(self.install_path, name, 'Contents', 'MacOS')
105 self.apptask = apptask
107 @after('apply_link')
108 @feature('cprogram')
109 def create_task_macplist(self):
110 """Use env['MACAPP'] to force *all* executables to be transformed into Mac applications
111 or use obj.mac_app = True to build specific targets as Mac apps"""
112 if self.env['MACAPP'] or getattr(self, 'mac_app', False):
113 # check if the user specified a plist before using our template
114 if not getattr(self, 'mac_plist', False):
115 self.mac_plist = app_info
117 plisttask = self.create_task('macplist')
118 plisttask.set_inputs(self.link_task.outputs)
120 out = self.link_task.outputs[0]
121 self.mac_plist = self.mac_plist % (out.name)
123 name = bundle_name_for_output(out)
124 dir = self.create_bundle_dirs(name, out)
126 n1 = dir.find_or_declare(['Contents', 'Info.plist'])
128 plisttask.set_outputs([n1])
129 plisttask.mac_plist = self.mac_plist
130 plisttask.install_path = os.path.join(self.install_path, name, 'Contents')
131 self.plisttask = plisttask
133 @after('apply_link')
134 @feature('cshlib')
135 def apply_link_osx(self):
136 name = self.link_task.outputs[0].name
137 if not self.install_path:
138 return
139 if getattr(self, 'vnum', None):
140 name = name.replace('.dylib', '.%s.dylib' % self.vnum)
142 path = os.path.join(Utils.subst_vars(self.install_path, self.env), name)
143 if '-dynamiclib' in self.env['LINKFLAGS']:
144 self.env.append_value('LINKFLAGS', '-install_name')
145 self.env.append_value('LINKFLAGS', path)
147 @before('apply_link', 'apply_lib_vars')
148 @feature('cc', 'cxx')
149 def apply_bundle(self):
150 """use env['MACBUNDLE'] to force all shlibs into mac bundles
151 or use obj.mac_bundle = True for specific targets only"""
152 if not ('cshlib' in self.features or 'shlib' in self.features): return
153 if self.env['MACBUNDLE'] or getattr(self, 'mac_bundle', False):
154 self.env['shlib_PATTERN'] = self.env['macbundle_PATTERN']
155 uselib = self.uselib = self.to_list(self.uselib)
156 if not 'MACBUNDLE' in uselib: uselib.append('MACBUNDLE')
158 @after('apply_link')
159 @feature('cshlib')
160 def apply_bundle_remove_dynamiclib(self):
161 if self.env['MACBUNDLE'] or getattr(self, 'mac_bundle', False):
162 if not getattr(self, 'vnum', None):
163 try:
164 self.env['LINKFLAGS'].remove('-dynamiclib')
165 self.env['LINKFLAGS'].remove('-single_module')
166 except ValueError:
167 pass
169 # TODO REMOVE IN 1.6 (global variable)
170 app_dirs = ['Contents', 'Contents/MacOS', 'Contents/Resources']
172 def app_build(task):
173 env = task.env
174 shutil.copy2(task.inputs[0].srcpath(env), task.outputs[0].abspath(env))
176 return 0
178 def plist_build(task):
179 env = task.env
180 f = open(task.outputs[0].abspath(env), "w")
181 f.write(task.mac_plist)
182 f.close()
184 return 0
186 Task.task_type_from_func('macapp', vars=[], func=app_build, after="cxx_link cc_link static_link")
187 Task.task_type_from_func('macplist', vars=[], func=plist_build, after="cxx_link cc_link static_link")