2 // Author: Geoff Norton
3 // de-MonoOptionification: miguel.
5 // Copyright (C) 2004-2005 Geoff Norton.
7 // Permission is hereby granted, free of charge, to any person obtaining
8 // a copy of this software and associated documentation files (the
9 // "Software"), to deal in the Software without restriction, including
10 // without limitation the rights to use, copy, modify, merge, publish,
11 // distribute, sublicense, and/or sell copies of the Software, and to
12 // permit persons to whom the Software is furnished to do so, subject to
13 // the following conditions:
15 // The above copyright notice and this permission notice shall be
16 // included in all copies or substantial portions of the Software.
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 using System
.Collections
;
31 using System
.Reflection
;
32 using System
.Runtime
.InteropServices
;
36 public class PackOptions
{
37 public string appname
;
39 public string assembly
;
41 public string[] resource
;
46 private PackOptions opts
;
50 public Pack (PackOptions opts
) {
54 public bool Generate () {
55 if (opts
.output
== null){
59 if (opts
.assembly
== null){
60 Console
.Error
.WriteLine ("Error: No assembly to macpack was specified");
65 if (opts
.appname
== null){
66 string t
= Path
.ChangeExtension (opts
.assembly
, null);
67 int p
= t
.IndexOf (Path
.DirectorySeparatorChar
);
69 t
= t
.Substring (p
+1);
74 if (Directory
.Exists (Path
.Combine (opts
.output
, String
.Format ("{0}.app", opts
.appname
)))) {
75 Console
.WriteLine ("ERROR: That application already exists. Please delete it first");
78 Directory
.CreateDirectory (Path
.Combine (opts
.output
, String
.Format ("{0}.app", opts
.appname
)));
79 Directory
.CreateDirectory (Path
.Combine (opts
.output
, String
.Format ("{0}.app/Contents", opts
.appname
)));
80 Directory
.CreateDirectory (Path
.Combine (opts
.output
, String
.Format ("{0}.app/Contents/MacOS", opts
.appname
)));
81 Directory
.CreateDirectory (Path
.Combine (opts
.output
, String
.Format ("{0}.app/Contents/Resources", opts
.appname
)));
82 if (opts
.resource
!= null) {
83 foreach (string res
in opts
.resource
) {
85 if (Directory
.Exists (res
)) {
86 CopyDirectory (res
, Path
.Combine (opts
.output
, String
.Format ("{0}.app/Contents/Resources/{1}", opts
.appname
, Path
.GetFileName (res
))));
88 File
.Copy (res
, Path
.Combine (opts
.output
, String
.Format ("{0}.app/Contents/Resources/{1}", opts
.appname
, Path
.GetFileName (res
))));
90 } catch (Exception e
){
91 Console
.Error
.WriteLine ("Error while processing {0} (Details: {1})", res
, e
.GetType ());
95 if (opts
.icon
!= null)
96 File
.Copy (opts
.icon
, Path
.Combine (opts
.output
, String
.Format ("{0}.app/Contents/Resources/{1}", opts
.appname
, Path
.GetFileName (opts
.icon
))));
98 File
.Copy (opts
.assembly
, Path
.Combine (opts
.output
, String
.Format ("{0}.app/Contents/Resources/{0}.exe", opts
.appname
)));
100 File
.Copy (opts
.assembly
, Path
.Combine (opts
.output
, String
.Format ("{0}.app/Contents/Resources/{0}", opts
.appname
)));
103 Stream s
= Assembly
.GetEntryAssembly ().GetManifestResourceStream ("LOADER");
104 BinaryReader reader
= new BinaryReader (s
);
105 byte[] data
= reader
.ReadBytes ((int)s
.Length
);
107 BinaryWriter writer
= new BinaryWriter (File
.Create (Path
.Combine (opts
.output
, String
.Format ("{0}.app/Contents/MacOS/{0}", opts
.appname
))));
108 string script
= Encoding
.ASCII
.GetString (data
);
112 script
= script
.Replace ("%MWF_MODE%", "0");
113 script
= script
.Replace ("%COCOASHARP_MODE%", "0");
114 script
= script
.Replace ("%X11_MODE%", "0");
117 script
= script
.Replace ("%MWF_MODE%", "1");
118 script
= script
.Replace ("%COCOASHARP_MODE%", "0");
119 script
= script
.Replace ("%X11_MODE%", "0");
122 script
= script
.Replace ("%MWF_MODE%", "0");
123 script
= script
.Replace ("%COCOASHARP_MODE%", "1");
124 script
= script
.Replace ("%X11_MODE%", "0");
127 script
= script
.Replace ("%MWF_MODE%", "0");
128 script
= script
.Replace ("%COCOASHARP_MODE%", "0");
129 script
= script
.Replace ("%X11_MODE%", "1");
132 data
= Encoding
.ASCII
.GetBytes (script
);
133 writer
.Write (data
, 0, data
.Length
);
136 chmod (Path
.Combine (opts
.output
,
137 String
.Format ("{0}.app/Contents/MacOS/{0}", opts
.appname
)),
138 Convert
.ToUInt32 ("755", 8));
140 Console
.WriteLine ("WARNING: It was not possible to set the executable permissions on\n" +
141 "the file {0}.app/Contents/MacOS/{0}, the bundle might not work", opts
.appname
);
144 s
= Assembly
.GetEntryAssembly ().GetManifestResourceStream ("PLIST");
145 reader
= new BinaryReader (s
);
146 data
= reader
.ReadBytes ((int)s
.Length
);
148 writer
= new BinaryWriter (File
.Create (Path
.Combine (opts
.output
, String
.Format ("{0}.app/Contents/Info.plist", opts
.appname
))));
149 string plist
= Encoding
.UTF8
.GetString (data
);
150 plist
= plist
.Replace ("%APPNAME%", opts
.appname
);
151 plist
= plist
.Replace ("%ICONFILE%", Path
.GetFileName (opts
.icon
));
152 data
= Encoding
.UTF8
.GetBytes (plist
);
153 writer
.Write (data
, 0, data
.Length
);
159 public static void CopyDirectory (string src
, string dest
) {
162 if (dest
[dest
.Length
-1] != Path
.DirectorySeparatorChar
) {
163 dest
+= Path
.DirectorySeparatorChar
;
166 if (!Directory
.Exists (dest
)) {
167 Directory
.CreateDirectory (dest
);
170 files
= Directory
.GetFileSystemEntries (src
);
172 foreach (string file
in files
) {
173 if (Directory
.Exists (file
)) {
174 CopyDirectory (file
, dest
+ Path
.GetFileName (file
));
176 File
.Copy (file
, dest
+ Path
.GetFileName (file
), true);
183 Console
.WriteLine ("\n" +
185 "macpack [options] assembly\n" +
186 " -n appname -appname:appname Application Name\n" +
187 " -o output -output:OUTPUT Output directory\n" +
188 " -a assembly Assembly to pack\n" +
189 " -i file -icon file Icon filename\n" +
190 " -r resource1,resource2 Additional files to bundle\n" +
191 " -m [winforms|cocoa|x11|console] The mode for the application");
194 static int Main (string [] args
) {
195 PackOptions options
= new PackOptions ();
196 ArrayList resources
= new ArrayList ();
198 for (int i
= 0; i
< args
.Length
; i
++){
203 int p
= s
.IndexOf (':');
205 key
= s
.Substring (0, p
);
206 value = s
.Substring (p
+ 1);
213 if (i
+1 < args
.Length
)
220 case "-n": case "-appname":
221 options
.appname
= value;
223 case "-o": case "-output":
224 options
.output
= value;
226 case "-a": case "-assembly":
227 options
.assembly
= value;
229 case "-i": case "-icon":
230 options
.icon
= value;
232 case "-r": case "-resource":
233 foreach (string ss
in value.Split (new char [] {','}
))
237 Console
.WriteLine ("MacPack 1.0 by Geoff Norton\n");
240 case "-m": case "-mode":
256 options
.mode
= Int32
.Parse (value);
258 Console
.Error
.WriteLine ("Could not recognize option {0} as the mode", value);
264 case "-h": case "-help":
269 options
.assembly
= key
;
274 options
.resource
= (string [])resources
.ToArray (typeof (string));
275 Pack pack
= new Pack (options
);
276 if (pack
.Generate ())
282 static extern int chmod (string path
, uint mode
);