-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathcocoa-pack
executable file
·213 lines (180 loc) · 7.43 KB
/
cocoa-pack
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
#!/usr/bin/python
# Used to build Mac OS-X application bundles for mono applications.
from optparse import OptionParser
import os
import shutil
import stat
import string
import sys
def copyDebugFile(file, dst):
if os.path.exists(file):
shutil.copy(file, dst)
def copyXib(xib, dstPath):
dst = os.path.basename(xib)
dst = os.path.splitext(dst)[0] + ".nib"
dst = os.path.join(dstPath, dst)
os.system("ibtool %s --compile %s" % (xib, dst))
# There is a shutil.copytree, but it copies the .svn directories inside
# nib bundles.
def copyTree(src, dst):
if os.path.exists(src) and os.path.basename(src)[0] != '.':
dstPath = os.path.join(dst, os.path.basename(src))
os.mkdir(dstPath)
for root, dirs, files in os.walk(src):
for file in files:
shutil.copy(os.path.join(root, file), dstPath)
for dir in dirs:
copyTree(os.path.join(root, dir), dstPath)
break
def checkVersion(version):
parts = version.split('.')
return '"../MacOS/mono-version-check" "$NAME" %s %s || exit 1' % (parts[0], parts[1])
def getVersionScript():
return r'''#/bin/bash
# This is the same script MonoDevelop generates for monomac.
APPNAME=$1
REQUIRED_MAJOR=$2
REQUIRED_MINOR=$3
REQUIRED_POINT=0
if [ $# -gt 3 ]; then
REQUIRED_POINT=$4
fi
VERSION_TITLE="Cannot launch $APPNAME"
VERSION_NAME=$REQUIRED_MAJOR.$REQUIRED_MINOR
if [ "x" != "x$REQUIRED_POINT" ]; then
VERSION_NAME=$VERSION_NAME.$REQUIRED_POINT
fi
VERSION_MSG="$APPNAME requires the Mono Framework version $VERSION_NAME or later."
DOWNLOAD_URL="http://www.go-mono.com/mono-downloads/download.html"
MONO_VERSION="$(mono --version | grep "Mono JIT compiler version " | cut -f5 -d\ )"
MONO_VERSION_MAJOR="$(echo $MONO_VERSION | cut -f1 -d.)"
MONO_VERSION_MINOR="$(echo $MONO_VERSION | cut -f2 -d.)"
MONO_VERSION_POINT="$(echo $MONO_VERSION | cut -f3 -d.)"
if [ -z "$MONO_VERSION_POINT" ]; then MONO_VERSION_POINT=0; fi
if [ -z "$MONO_VERSION" ] \
|| [ $MONO_VERSION_MAJOR -lt $REQUIRED_MAJOR ] \
|| [ $MONO_VERSION_MAJOR -eq $REQUIRED_MAJOR -a $MONO_VERSION_MINOR -lt $REQUIRED_MINOR ] \
|| [ $MONO_VERSION_MAJOR -eq $REQUIRED_MAJOR -a $MONO_VERSION_MINOR -eq $REQUIRED_MINOR \
-a $REQUIRED_POINT -gt 0 -a $MONO_VERSION_POINT -lt $REQUIRED_POINT ]
then
osascript \
-e "set question to display dialog \"$VERSION_MSG\" with title \"$VERSION_TITLE\" buttons {\"Cancel\", \"Download...\"} default button 2" \
-e "if button returned of question is equal to \"Download...\" then open location \"$DOWNLOAD_URL\""
echo "$VERSION_TITLE"
echo "$VERSION_MSG"
exit 1
fi
'''
parser = OptionParser()
parser.add_option("--app", help="path to the bundle which will be created")
parser.add_option("--append-var", action="append", help="appends a value onto an environment variable")
parser.add_option("--exe", help="path to the executable assembly")
parser.add_option("--mono-flags", default="", help="flags to use with mono")
parser.add_option("--plist", help="path to the Info.plist to copy")
parser.add_option("--require-mono", default="2.6", help="required mono version")
parser.add_option("--resources", action="append", help="files to copy into the resources dir")
parser.add_option("--vars", help="{name}s to expand in the plist")
parser.add_option("--usage", action="store_true", default=False, help="prints usage info and exit")
(options, args) = parser.parse_args()
if options.usage:
print "Typical usage looks like this:"
print "python cocoa-pack --app=bin/CoolApp.app --mono-flags=--debug --exe=bin/cool-app.exe --plist=Info.plist --resources=English.lproj:MainMenu.nib,Document.nib --vars=VERSION:0.1,APP_NAME:CoolApp"
print "--resources may appear multiple times and the localization dir is optional"
print "--append-var may appear multiple times and should be written like --append-var=PATH:/some/path"
else:
appName = os.path.splitext(os.path.basename(options.app))[0] # doesn't include .nib
exeName = os.path.splitext(os.path.basename(options.exe))[0] # doesn't include .exe
contentsPath = options.app + "/Contents"
macOSPath = contentsPath + "/MacOS"
resourcesPath = contentsPath + "/Resources"
# Remove the old bundle.
if os.path.exists(options.app):
shutil.rmtree(options.app)
# Create the directories for the new bundle.
os.mkdir(options.app)
os.mkdir(contentsPath)
os.mkdir(macOSPath)
os.mkdir(resourcesPath)
# Copy the exe into the bundle.
shutil.copy(options.exe, resourcesPath)
if "--debug" in options.mono_flags:
copyDebugFile(options.exe + ".mdb", resourcesPath)
copyDebugFile(options.exe + ".xxx", resourcesPath)
# Add a PkgInfo file.
file = open(contentsPath + "/PkgInfo", "w")
file.write("APPL????")
file.close()
# Add a mono version check script.
path = macOSPath + "/mono-version-check"
file = open(path, "w")
file.write(getVersionScript())
file.close()
os.chmod(path, 0x1ED)
# Copy the resources into the bundle.
for resources in options.resources:
dstPath = resourcesPath
parts = resources.split(':')
if len(parts) == 2:
dstPath = resourcesPath + "/" + parts[0]
resources = parts[1]
if not os.path.exists(dstPath):
os.mkdir(dstPath)
for resource in resources.split(','):
if os.path.isfile(resource):
if resource.endswith(".xib"):
copyXib(resource, dstPath)
else:
shutil.copy(resource, dstPath)
if "--debug" in options.mono_flags:
copyDebugFile(resource + ".mdb", dstPath)
copyTree(resource + ".dSYM", dstPath)
else:
copyTree(resource, dstPath)
# Expand variables in the Info.plist file and write the new plist into the bundle.
file = open(options.plist, "r")
text = file.read()
for entry in options.vars.split(','):
name = entry.split(':')[0]
value = entry.split(':')[1]
text = text.replace("${" + name + "}", value)
file = open(contentsPath + "/Info.plist", "w")
file.write(text)
file.close()
# Create a little script to run our assembly using mono. Note that we can't simply
# run mono from its normal location or nibs won't load. Also we want to use a hard
# link if possible because it means that our process name will be something
# reasonable instead of "mono".
vars = ""
if options.append_var:
for entry in options.append_var:
i = entry.find(':')
name = entry[0:i]
value = entry[i+1:]
vars += 'export %s="$%s:%s"\n' % (name, name, value)
script = """#!/bin/sh
APP_PATH=`echo \x240 | awk '{split(\x240,patharr,\"/\"); idx=1; while(patharr[idx+3] != \"\") { if (patharr[idx] != \"/\") {printf(\"%s/\", patharr[idx]); idx++ }} }'`
NAME=`basename \"$APP_PATH\" .app`
cd \"${APP_PATH}/Contents/MacOS\"
if [ -f \"$NAME\" ]; then rm -f \"$NAME\" ; fi
if !(ln \x60which mono\x60 \"$NAME\"); then
ln -s \x60which mono\x60 \"$NAME\"
fi
MONO_FRAMEWORK_PATH=/Library/Frameworks/Mono.framework/Versions/Current
export DYLD_FALLBACK_LIBRARY_PATH="$MONO_FRAMEWORK_PATH/lib:$DYLD_FALLBACK_LIBRARY_PATH:/usr/lib:/usr/local/lib"
export PATH="$MONO_FRAMEWORK_PATH/bin:$PATH"
cd ../Resources
$(version-check)
$(vars)
\"../MacOS/$NAME\" $(mono-flags) $(exe-name).exe $@
"""
script = script.replace("$(app-name)", appName)
script = script.replace("$(mono-flags)", options.mono_flags)
script = script.replace("$(exe-name)", exeName)
script = script.replace("$(vars)", vars)
script = script.replace("$(version-check)", checkVersion(options.require_mono))
file = open(macOSPath + "/launcher", "w")
file.write(script)
file.close()
# Make the script executable/readable by everyone and writeable
# by the current user.
os.chmod(macOSPath + "/launcher", 0x1ED)