2 // mkbundle: tool to create bundles.
4 // Based on the `make-bundle' Perl script written by Paolo Molaro (lupus@debian.org)
9 // (C) Novell, Inc 2004
13 using System.Collections;
14 using System.Reflection;
16 using System.Runtime.InteropServices;
20 static string output = "a.out";
21 static string object_out = null;
22 static ArrayList link_paths = new ArrayList ();
23 static bool autodeps = false;
24 static bool keeptemp = false;
25 static bool compile_only = false;
27 static int Main (string [] args)
29 ArrayList sources = new ArrayList ();
30 int top = args.Length;
33 for (int i = 0; i < top; i++){
56 object_out = args [++i];
64 link_paths.Add (args [i]);
80 sources.Add (args [i]);
85 Console.WriteLine ("Sources: {0} Auto-dependencies: {1}", sources.Count, autodeps);
86 if (sources.Count == 0 || output == null) {
91 ArrayList assemblies = LoadAssemblies (sources);
92 ArrayList files = new ArrayList ();
93 foreach (Assembly a in assemblies)
94 QueueAssembly (files, a.CodeBase);
96 GenerateBundles (files);
97 //GenerateJitWrapper ();
102 static void GenerateBundles (ArrayList files)
104 string temp_s = "temp.s"; // Path.GetTempFileName ();
105 string temp_c = "temp.c";
106 string temp_o = Path.GetTempFileName () + ".o";
110 if (object_out != null)
114 ArrayList c_bundle_names = new ArrayList ();
115 byte [] buffer = new byte [8192];
117 StreamWriter ts = new StreamWriter (File.Create (temp_s));
118 StreamWriter tc = new StreamWriter (File.Create (temp_c));
121 tc.WriteLine ("/* This source code was produced by mkbundle, do not edit */");
122 tc.WriteLine ("#include <mono/metadata/assembly.h>\n");
123 foreach (string url in files){
124 string fname = url.Substring (7);
125 string aname = fname.Substring (fname.LastIndexOf ("/") + 1);
126 string encoded = aname.Replace ("-", "_").Replace (".", "_");
131 Console.WriteLine (" embedding: " + fname);
133 FileInfo fi = new FileInfo (fname);
134 FileStream fs = File.OpenRead (fname);
137 ".globl assembly_data_{0}\n" +
138 "\t.section .rodata\n" +
140 "\t.type assembly_data_{0}, @object\n" +
141 "\t.size assembly_data_{0}, {1}\n" +
142 "assembly_data_{0}:\n",
147 while ((n = fs.Read (buffer, 0, 8192)) != 0){
148 for (int i = 0; i < n; i++){
149 ts.Write ("\t.byte {0}\n", buffer [i]);
154 tc.WriteLine ("extern const unsigned char assembly_data_{0} [];", encoded);
155 tc.WriteLine ("static const MonoBundledAssembly assembly_bundle_{0} = {{\"{1}\", assembly_data_{0}, {2}}};",
156 encoded, aname, fi.Length);
158 c_bundle_names.Add ("assembly_bundle_" + encoded);
161 Console.WriteLine ("Compiling:");
162 string cmd = String.Format ("as -o {0} {1} ", temp_o, temp_s);
163 Console.WriteLine (cmd);
164 int ret = system (cmd);
170 tc.WriteLine ("\nstatic const MonoBundledAssembly *bundled [] = {");
171 foreach (string c in c_bundle_names){
172 tc.WriteLine ("\t&{0},", c);
174 tc.WriteLine ("\tNULL\n};\n");
175 tc.WriteLine ("static char *image_name = \"{0}\";", prog);
177 StreamReader s = new StreamReader (Assembly.GetAssembly (typeof(MakeBundle)).GetManifestResourceStream ("template.c"));
178 tc.Write (s.ReadToEnd ());
184 cmd = String.Format ("cc -o {2} -Wall {0} `pkg-config --cflags --libs mono` {1}",
185 temp_c, temp_o, output);
186 Console.WriteLine (cmd);
192 Console.WriteLine ("Done");
195 if (object_out == null){
196 File.Delete (temp_o);
199 File.Delete (temp_c);
201 File.Delete (temp_s);
206 static ArrayList LoadAssemblies (ArrayList sources)
208 ArrayList assemblies = new ArrayList ();
211 foreach (string name in sources){
212 Assembly a = LoadAssembly (name);
223 Environment.Exit (1);
228 static void QueueAssembly (ArrayList files, string codebase)
230 if (files.Contains (codebase))
233 files.Add (codebase);
234 Assembly a = Assembly.LoadFrom (codebase);
239 foreach (AssemblyName an in a.GetReferencedAssemblies ())
240 QueueAssembly (files, an.CodeBase);
243 static Assembly LoadAssembly (string assembly)
248 char[] path_chars = { '/', '\\' };
250 if (assembly.IndexOfAny (path_chars) != -1) {
251 a = Assembly.LoadFrom (assembly);
253 string ass = assembly;
254 if (ass.EndsWith (".dll"))
255 ass = assembly.Substring (0, assembly.Length - 4);
256 a = Assembly.Load (ass);
259 } catch (FileNotFoundException){
260 string total_log = "";
262 foreach (string dir in link_paths){
263 string full_path = Path.Combine (dir, assembly);
264 if (!assembly.EndsWith (".dll") && !assembly.EndsWith (".exe"))
268 a = Assembly.LoadFrom (full_path);
270 } catch (FileNotFoundException ff) {
271 total_log += ff.FusionLog;
275 Error ("Cannot find assembly `" + assembly + "'" );
276 Console.WriteLine ("Log: \n" + total_log);
277 } catch (BadImageFormatException f) {
278 Error ("Cannot load assembly (bad file format)" + f.FusionLog);
279 } catch (FileLoadException f){
280 Error ("Cannot load assembly " + f.FusionLog);
281 } catch (ArgumentNullException){
282 Error("Cannot load assembly (null argument)");
287 static void Error (string msg)
289 Console.Error.WriteLine (msg);
290 Environment.Exit (1);
295 Console.WriteLine ("Usage is: mkbundle [options] assembly1 [assembly2...]\n\n" +
297 " -c Produce stub only, do not compile\n" +
298 " -o out Specifies output filename\n" +
299 " -oo obj Specifies output filename for helper object file" +
300 " -L path Adds `path' to the search path for assemblies\n" +
301 " --nodeps Turns off automatic dependency embedding (default)\n" +
302 " --deps Turns on automatic dependency embedding\n" +
303 " --keeptemp Keeps the temporary files\n");
307 static extern int system (string s);