X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Ftools%2Fmkbundle%2Fmkbundle.cs;h=9855bf47bd14c64fedc2d5c98bd17fcf21b2a5e2;hb=457c9722a4bc7ead4d13d62dd6c4c56dfa24d8c0;hp=0d4dc93797967121ff1e82cbeb5fd56e590c8292;hpb=de280aeb0573334181eb3be0f0b7da6bc9208695;p=mono.git diff --git a/mcs/tools/mkbundle/mkbundle.cs b/mcs/tools/mkbundle/mkbundle.cs index 0d4dc937979..9855bf47bd1 100644 --- a/mcs/tools/mkbundle/mkbundle.cs +++ b/mcs/tools/mkbundle/mkbundle.cs @@ -11,18 +11,22 @@ using System; using System.Diagnostics; using System.Xml; -using System.Collections; +using System.Collections.Generic; using System.Reflection; using System.IO; +using System.IO.Compression; using System.Runtime.InteropServices; using System.Text; -using Mono.Unix; -using ICSharpCode.SharpZipLib.Zip.Compression.Streams; + + +#if NET_4_5 +using System.Threading.Tasks; +#endif class MakeBundle { static string output = "a.out"; static string object_out = null; - static ArrayList link_paths = new ArrayList (); + static List link_paths = new List (); static bool autodeps = false; static bool keeptemp = false; static bool compile_only = false; @@ -36,7 +40,7 @@ class MakeBundle { static int Main (string [] args) { - ArrayList sources = new ArrayList (); + List sources = new List (); int top = args.Length; link_paths.Add ("."); @@ -88,10 +92,6 @@ class MakeBundle { keeptemp = true; break; case "--static": - if (style == "windows") { - Console.Error.WriteLine ("The option `{0}' is not supported on this platform.", args [i]); - return 1; - } static_link = true; Console.WriteLine ("Note that statically linking the LGPL Mono runtime has more licensing restrictions than dynamically linking."); Console.WriteLine ("See http://www.mono-project.com/Licensing for details on licensing."); @@ -127,11 +127,33 @@ class MakeBundle { break; case "--nomain": nomain = true; + break; + case "--style": + if (i+1 == top) { + Help (); + return 1; + } + style = args [++i]; + switch (style) { + case "windows": + case "mac": + case "linux": + break; + default: + Console.Error.WriteLine ("Invalid style '{0}' - only 'windows', 'mac' and 'linux' are supported for --style argument", style); + return 1; + } + break; default: sources.Add (args [i]); break; } + + if (static_link && style == "windows") { + Console.Error.WriteLine ("The option `{0}' is not supported on this platform.", args [i]); + return 1; + } } Console.WriteLine ("Sources: {0} Auto-dependencies: {1}", sources.Count, autodeps); @@ -140,10 +162,27 @@ class MakeBundle { Environment.Exit (1); } - ArrayList assemblies = LoadAssemblies (sources); - ArrayList files = new ArrayList (); + List assemblies = LoadAssemblies (sources); + List files = new List (); foreach (Assembly a in assemblies) QueueAssembly (files, a.CodeBase); + + // Special casing mscorlib.dll: any specified mscorlib.dll cannot be loaded + // by Assembly.ReflectionFromLoadFrom(). Instead the fx assembly which runs + // mkbundle.exe is loaded, which is not what we want. + // So, replace it with whatever actually specified. + foreach (string srcfile in sources) { + if (Path.GetFileName (srcfile) == "mscorlib.dll") { + foreach (string file in files) { + if (Path.GetFileName (new Uri (file).LocalPath) == "mscorlib.dll") { + files.Remove (file); + files.Add (new Uri (Path.GetFullPath (srcfile)).LocalPath); + break; + } + } + break; + } + } GenerateBundles (files); //GenerateJitWrapper (); @@ -159,7 +198,7 @@ class MakeBundle { ".globl {0}\n" + "\t.section .rodata\n" + "\t.p2align 5\n" + - "\t.type {0}, @object\n" + + "\t.type {0}, \"object\"\n" + "\t.size {0}, {1}\n" + "{0}:\n", name, size); @@ -167,7 +206,6 @@ class MakeBundle { case "osx": sw.WriteLine ( "\t.section __TEXT,__text,regular,pure_instructions\n" + - "\t.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32\n" + "\t.globl _{0}\n" + "\t.data\n" + "\t.align 4\n" + @@ -185,7 +223,35 @@ class MakeBundle { } } - static void GenerateBundles (ArrayList files) + static string [] chars = new string [256]; + + static void WriteBuffer (StreamWriter ts, Stream stream, byte[] buffer) + { + int n; + + // Preallocate the strings we need. + if (chars [0] == null) { + for (int i = 0; i < chars.Length; i++) + chars [i] = string.Format ("{0}", i.ToString ()); + } + + while ((n = stream.Read (buffer, 0, buffer.Length)) != 0) { + int count = 0; + for (int i = 0; i < n; i++) { + if (count % 32 == 0) { + ts.Write ("\n\t.byte "); + } else { + ts.Write (","); + } + ts.Write (chars [buffer [i]]); + count ++; + } + } + + ts.WriteLine (); + } + + static void GenerateBundles (List files) { string temp_s = "temp.s"; // Path.GetTempFileName (); string temp_c = "temp.c"; @@ -197,8 +263,8 @@ class MakeBundle { temp_o = object_out; try { - ArrayList c_bundle_names = new ArrayList (); - ArrayList config_names = new ArrayList (); + List c_bundle_names = new List (); + List config_names = new List (); byte [] buffer = new byte [8192]; using (StreamWriter ts = new StreamWriter (File.Create (temp_s))) { @@ -216,52 +282,73 @@ class MakeBundle { tc.WriteLine ("} CompressedAssembly;\n"); } - foreach (string url in files){ - string fname = new Uri (url).LocalPath; - string aname = Path.GetFileName (fname); - string encoded = aname.Replace ("-", "_").Replace (".", "_"); + object monitor = new object (); - if (prog == null) - prog = aname; - - Console.WriteLine (" embedding: " + fname); - + var streams = new Dictionary (); + var sizes = new Dictionary (); + + // Do the file reading and compression in parallel + Action body = delegate (string url) { + string fname = new Uri (url).LocalPath; Stream stream = File.OpenRead (fname); long real_size = stream.Length; int n; if (compress) { MemoryStream ms = new MemoryStream (); - DeflaterOutputStream deflate = new DeflaterOutputStream (ms); - while ((n = stream.Read (buffer, 0, 8192)) != 0){ + GZipStream deflate = new GZipStream (ms, CompressionMode.Compress, leaveOpen:true); + while ((n = stream.Read (buffer, 0, buffer.Length)) != 0){ deflate.Write (buffer, 0, n); } stream.Close (); - deflate.Finish (); + deflate.Close (); byte [] bytes = ms.GetBuffer (); stream = new MemoryStream (bytes, 0, (int) ms.Length, false, false); } - WriteSymbol (ts, "assembly_data_" + encoded, stream.Length); - - while ((n = stream.Read (buffer, 0, 8192)) != 0){ - for (int i = 0; i < n; i++){ - ts.Write ("\t.byte {0}\n", buffer [i]); - } + lock (monitor) { + streams [url] = stream; + sizes [url] = real_size; } - ts.WriteLine (); + }; + + //#if NET_4_5 +#if FALSE + Parallel.ForEach (files, body); +#else + foreach (var url in files) + body (url); +#endif + + // The non-parallel part + foreach (var url in files) { + string fname = new Uri (url).LocalPath; + string aname = Path.GetFileName (fname); + string encoded = aname.Replace ("-", "_").Replace (".", "_"); + + if (prog == null) + prog = aname; + + var stream = streams [url]; + var real_size = sizes [url]; + + Console.WriteLine (" embedding: " + fname); + + WriteSymbol (ts, "assembly_data_" + encoded, stream.Length); + + WriteBuffer (ts, stream, buffer); if (compress) { tc.WriteLine ("extern const unsigned char assembly_data_{0} [];", encoded); tc.WriteLine ("static CompressedAssembly assembly_bundle_{0} = {{{{\"{1}\"," + - " assembly_data_{0}, {2}}}, {3}}};", - encoded, aname, real_size, stream.Length); + " assembly_data_{0}, {2}}}, {3}}};", + encoded, aname, real_size, stream.Length); double ratio = ((double) stream.Length * 100) / real_size; Console.WriteLine (" compression ratio: {0:.00}%", ratio); } else { tc.WriteLine ("extern const unsigned char assembly_data_{0} [];", encoded); tc.WriteLine ("static const MonoBundledAssembly assembly_bundle_{0} = {{\"{1}\", assembly_data_{0}, {2}}};", - encoded, aname, real_size); + encoded, aname, real_size); } stream.Close (); @@ -272,18 +359,14 @@ class MakeBundle { Console.WriteLine (" config from: " + fname + ".config"); tc.WriteLine ("extern const unsigned char assembly_config_{0} [];", encoded); WriteSymbol (ts, "assembly_config_" + encoded, cf.Length); - while ((n = cf.Read (buffer, 0, 8192)) != 0){ - for (int i = 0; i < n; i++){ - ts.Write ("\t.byte {0}\n", buffer [i]); - } - } + WriteBuffer (ts, cf, buffer); ts.WriteLine (); config_names.Add (new string[] {aname, encoded}); } catch (FileNotFoundException) { /* we ignore if the config file doesn't exist */ } - } + if (config_file != null){ FileStream conf; try { @@ -293,15 +376,10 @@ class MakeBundle { return; } Console.WriteLine ("System config from: " + config_file); - tc.WriteLine ("extern const unsigned char system_config;"); + tc.WriteLine ("extern const char system_config;"); WriteSymbol (ts, "system_config", config_file.Length); - int n; - while ((n = conf.Read (buffer, 0, 8192)) != 0){ - for (int i = 0; i < n; i++){ - ts.Write ("\t.byte {0}\n", buffer [i]); - } - } + WriteBuffer (ts, conf, buffer); // null terminator ts.Write ("\t.byte 0\n"); ts.WriteLine (); @@ -316,16 +394,10 @@ class MakeBundle { return; } Console.WriteLine ("Machine config from: " + machine_config_file); - tc.WriteLine ("extern const unsigned char machine_config;"); + tc.WriteLine ("extern const char machine_config;"); WriteSymbol (ts, "machine_config", machine_config_file.Length); - int n; - while ((n = conf.Read (buffer, 0, 8192)) != 0){ - for (int i = 0; i < n; i++){ - ts.Write ("\t.byte {0}\n", buffer [i]); - } - } - // null terminator + WriteBuffer (ts, conf, buffer); ts.Write ("\t.byte 0\n"); ts.WriteLine (); } @@ -431,9 +503,9 @@ class MakeBundle { } } - static ArrayList LoadAssemblies (ArrayList sources) + static List LoadAssemblies (List sources) { - ArrayList assemblies = new ArrayList (); + List assemblies = new List (); bool error = false; foreach (string name in sources){ @@ -453,7 +525,7 @@ class MakeBundle { return assemblies; } - static void QueueAssembly (ArrayList files, string codebase) + static void QueueAssembly (List files, string codebase) { if (files.Contains (codebase)) return; @@ -553,10 +625,10 @@ class MakeBundle { return; } - IntPtr buf = UnixMarshal.AllocHeap(8192); + IntPtr buf = Marshal.AllocHGlobal (8192); if (uname (buf) != 0){ Console.WriteLine ("Warning: Unable to detect OS"); - UnixMarshal.FreeHeap(buf); + Marshal.FreeHGlobal (buf); return; } string os = Marshal.PtrToStringAnsi (buf); @@ -564,7 +636,7 @@ class MakeBundle { if (os == "Darwin") style = "osx"; - UnixMarshal.FreeHeap(buf); + Marshal.FreeHGlobal (buf); } static bool IsUnix {