1
2
3
4
5 """MacOSX related tools
6
7 To compile an executable into a Mac application bundle (a .app), set its 'mac_app' attribute
8 obj.mac_app = True
9
10 To make a bundled shared library (a .bundle), set the 'mac_bundle' attribute:
11 obj.mac_bundle = True
12 """
13
14 import os, shutil, sys
15 import TaskGen, Task, Build, Options
16 from TaskGen import taskgen, feature, after, before
17 from Logs import error, debug
21 if self.type == 'program' and self.link_task:
22 apptask = self.create_task('macapp', self.env)
23 apptask.set_inputs(self.link_task.outputs)
24 apptask.set_outputs(self.link_task.outputs[0].change_ext('.app'))
25 self.apptask = apptask
26
27 @taskgen
28 @after('apply_link')
29 @feature('cc', 'cxx')
30 -def apply_link_osx(self):
31 """Use env['MACAPP'] to force *all* executables to be transformed into Mac applications
32 or use obj.mac_app = True to build specific targets as Mac apps"""
33 if self.env['MACAPP'] or getattr(self, 'mac_app', False):
34 self.create_task_macapp()
35 name = self.link_task.outputs[0].name
36 if self.vnum: name = name.replace('.dylib', '.%s.dylib' % self.vnum)
37
38
39 path = os.path.join(self.env['PREFIX'], lib, name)
40 path = '-install_name %s' % path
41 self.env.append_value('LINKFLAGS', path)
42
43 @taskgen
44 @before('apply_link')
45 @before('apply_lib_vars')
46 @feature('cc', 'cxx')
47 -def apply_bundle(self):
48 """the uselib system cannot modify a few things, use env['MACBUNDLE'] to force all shlibs into mac bundles
49 or use obj.mac_bundle = True for specific targets only"""
50 if not 'shlib' in self.features: return
51 if self.env['MACBUNDLE'] or getattr(self, 'mac_bundle', False):
52 self.env['shlib_PATTERN'] = '%s.bundle'
53 uselib = self.to_list(self.uselib)
54 if not 'MACBUNDLE' in uselib: uselib.append('MACBUNDLE')
55
60 if not 'shlib' in self.features: return
61 if self.env['MACBUNDLE'] or getattr(self, 'mac_bundle', False):
62 self.env["LINKFLAGS"].remove("-dynamiclib")
63 self.env.append_value("LINKFLAGS", "-bundle")
64
65
66
67 app_dirs = ['Contents', os.path.join('Contents','MacOS'), os.path.join('Contents','Resources')]
68
69 app_info = '''
70 <?xml version="1.0" encoding="UTF-8"?>
71 <!DOCTYPE plist SYSTEM "file://localhost/System/Library/DTDs/PropertyList.dtd">
72 <plist version="0.9">
73 <dict>
74 <key>CFBundlePackageType</key>
75 <string>APPL</string>
76 <key>CFBundleGetInfoString</key>
77 <string>Created by Waf</string>
78 <key>CFBundleSignature</key>
79 <string>????</string>
80 <key>NOTE</key>
81 <string>THIS IS A GENERATED FILE, DO NOT MODIFY</string>
82 <key>CFBundleExecutable</key>
83 <string>%s</string>
84 </dict>
85 </plist>
86 '''
89 global app_dirs
90 env = task.env
91
92 i = 0
93 for p in task.outputs:
94 srcfile = p.srcpath(env)
95
96 debug('osx: creating directories')
97 try:
98 os.mkdir(srcfile)
99 [os.makedirs(os.path.join(srcfile, d)) for d in app_dirs]
100 except (OSError, IOError):
101 pass
102
103
104 srcprg = task.inputs[i].srcpath(env)
105 dst = os.path.join(srcfile, 'Contents', 'MacOS')
106 debug('osx: copy %s to %s' % (srcprg, dst))
107 shutil.copy(srcprg, dst)
108
109
110 debug('osx: generate Info.plist')
111
112
113 f = file(os.path.join(srcfile, "Contents", "Info.plist"), "w")
114 f.write(app_info % os.path.basename(srcprg))
115 f.close()
116
117 i += 1
118
119 return 0
120
122 """see http://code.google.com/p/waf/issues/detail?id=173"""
123 nums = task.vnum.split('.')
124
125 path = self.install_path
126
127 libname = task.outputs[0].name
128
129 name3 = libname.replace('.dylib', '.%s.dylib' % task.vnum)
130 name2 = libname.replace('.dylib', '.%s.dylib' % nums[0])
131 name1 = libname
132
133 filename = task.outputs[0].abspath(task.env)
134 bld = Build.bld
135 bld.install_as(path + name3, filename, env=task.env)
136 bld.symlink_as(path + name2, name3)
137 bld.symlink_as(path + name1, name3)
138
146
147 Task.task_type_from_func('macapp', vars=[], func=app_build, after="cxx_link cc_link ar_link_static")
148