Merge pull request #249 from pcc/xgetinputfocus
[mono.git] / mcs / tools / mkbundle / mkbundle.cs
index f8c65c53f04b81e341d0e636e9bc2c8fa5c02217..0e565c6a59165809d6aca91f156536361cc3ed26 100644 (file)
@@ -15,6 +15,7 @@ using System.Collections;
 using System.Reflection;
 using System.IO;
 using System.Runtime.InteropServices;
+using System.Text;
 using Mono.Unix;
 using ICSharpCode.SharpZipLib.Zip.Compression.Streams;
 
@@ -27,9 +28,11 @@ class MakeBundle {
        static bool compile_only = false;
        static bool static_link = false;
        static string config_file = null;
+       static string machine_config_file = null;
        static string config_dir = null;
        static string style = "linux";
        static bool compress;
+       static bool nomain;
        
        static int Main (string [] args)
        {
@@ -101,6 +104,16 @@ class MakeBundle {
 
                                config_file = args [++i];
                                break;
+                       case "--machine-config":
+                               if (i+1 == top) {
+                                       Help ();
+                                       return 1;
+                               }
+
+                               machine_config_file = args [++i];
+
+                               Console.WriteLine ("WARNING:\n  Check that the machine.config file you are bundling\n  doesn't contain sensitive information specific to this machine.");
+                               break;
                        case "--config-dir":
                                if (i+1 == top) {
                                        Help ();
@@ -112,6 +125,9 @@ class MakeBundle {
                        case "-z":
                                compress = true;
                                break;
+                       case "--nomain":
+                               nomain = true;
+                               break;
                        default:
                                sources.Add (args [i]);
                                break;
@@ -142,7 +158,7 @@ class MakeBundle {
                        sw.WriteLine (
                                ".globl {0}\n" +
                                "\t.section .rodata\n" +
-                               "\t.align 32\n" +
+                               "\t.p2align 5\n" +
                                "\t.type {0}, @object\n" +
                                "\t.size {0}, {1}\n" +
                                "{0}:\n",
@@ -185,11 +201,12 @@ class MakeBundle {
                        ArrayList config_names = new ArrayList ();
                        byte [] buffer = new byte [8192];
 
-                       StreamWriter ts = new StreamWriter (File.Create (temp_s));
-                       StreamWriter tc = new StreamWriter (File.Create (temp_c));
+                       using (StreamWriter ts = new StreamWriter (File.Create (temp_s))) {
+                       using (StreamWriter tc = new StreamWriter (File.Create (temp_c))) {
                        string prog = null;
 
                        tc.WriteLine ("/* This source code was produced by mkbundle, do not edit */");
+                       tc.WriteLine ("#include <mono/metadata/mono-config.h>");
                        tc.WriteLine ("#include <mono/metadata/assembly.h>\n");
 
                        if (compress) {
@@ -276,7 +293,7 @@ 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;
@@ -289,6 +306,29 @@ class MakeBundle {
                                ts.Write ("\t.byte 0\n");
                                ts.WriteLine ();
                        }
+
+                       if (machine_config_file != null){
+                               FileStream conf;
+                               try {
+                                       conf = File.OpenRead (machine_config_file);
+                               } catch {
+                                       Error (String.Format ("Failure to open {0}", machine_config_file));
+                                       return;
+                               }
+                               Console.WriteLine ("Machine config from: " + machine_config_file);
+                               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
+                               ts.Write ("\t.byte 0\n");
+                               ts.WriteLine ();
+                       }
                        ts.Close ();
                        
                        Console.WriteLine ("Compiling:");
@@ -316,6 +356,8 @@ class MakeBundle {
                        }
                        if (config_file != null)
                                tc.WriteLine ("\tmono_config_parse_memory (&system_config);\n");
+                       if (machine_config_file != null)
+                               tc.WriteLine ("\tmono_register_machine_config (&machine_config);\n");
                        tc.WriteLine ("}\n");
 
                        if (config_dir != null)
@@ -333,8 +375,16 @@ class MakeBundle {
                        StreamReader s = new StreamReader (template_stream);
                        string template = s.ReadToEnd ();
                        tc.Write (template);
-                       tc.Close ();
+
+                       if (!nomain) {
+                               Stream template_main_stream = Assembly.GetAssembly (typeof(MakeBundle)).GetManifestResourceStream ("template_main.c");
+                               StreamReader st = new StreamReader (template_main_stream);
+                               string maintemplate = st.ReadToEnd ();
+                               tc.Write (maintemplate);
+                       }
                        
+                       tc.Close ();
+
                        if (compile_only)
                                return;
 
@@ -347,16 +397,16 @@ class MakeBundle {
                        if (static_link) {
                                string smonolib;
                                if (style == "osx")
-                                       smonolib = "`pkg-config --variable=libdir mono`/libmono.a ";
+                                       smonolib = "`pkg-config --variable=libdir mono-2`/libmono-2.0.a ";
                                else
-                                       smonolib = "-Wl,-Bstatic -lmono -Wl,-Bdynamic ";
-                               cmd = String.Format ("{4} -o {2} -Wall `pkg-config --cflags mono` {0} {3} " +
-                                                    "`pkg-config --libs-only-L mono` " + smonolib +
-                                                    "`pkg-config --libs-only-l mono | sed -e \"s/\\-lmono //\"` {1}",
+                                       smonolib = "-Wl,-Bstatic -lmono-2.0 -Wl,-Bdynamic ";
+                               cmd = String.Format ("{4} -o {2} -Wall `pkg-config --cflags mono-2` {0} {3} " +
+                                                    "`pkg-config --libs-only-L mono-2` " + smonolib +
+                                                    "`pkg-config --libs-only-l mono-2 | sed -e \"s/\\-lmono-2.0 //\"` {1}",
                                                     temp_c, temp_o, output, zlib, cc);
                        } else {
                                
-                               cmd = String.Format ("{4} " + debugging + " -o {2} -Wall {0} `pkg-config --cflags --libs mono` {3} {1}",
+                               cmd = String.Format ("{4} " + debugging + " -o {2} -Wall {0} `pkg-config --cflags --libs mono-2` {3} {1}",
                                                     temp_c, temp_o, output, zlib, cc);
                        }
                             
@@ -366,6 +416,8 @@ class MakeBundle {
                                return;
                        }
                        Console.WriteLine ("Done");
+                       }
+                       }
                } finally {
                        if (!keeptemp){
                                if (object_out == null){
@@ -472,17 +524,20 @@ class MakeBundle {
        {
                Console.WriteLine ("Usage is: mkbundle [options] assembly1 [assembly2...]\n\n" +
                                   "Options:\n" +
-                                  "    -c              Produce stub only, do not compile\n" +
-                                  "    -o out          Specifies output filename\n" +
-                                  "    -oo obj         Specifies output filename for helper object file\n" +
-                                  "    -L path         Adds `path' to the search path for assemblies\n" +
-                                  "    --nodeps        Turns off automatic dependency embedding (default)\n" +
-                                  "    --deps          Turns on automatic dependency embedding\n" +
-                                  "    --keeptemp      Keeps the temporary files\n" +
-                                  "    --config F      Bundle system config file `F'\n" +
-                                  "    --config-dir D  Set MONO_CFG_DIR to `D'\n" +
-                                  "    --static        Statically link to mono libs\n" +
-                                  "    -z              Compress the assemblies before embedding.\n");
+                                  "    -c                  Produce stub only, do not compile\n" +
+                                  "    -o out              Specifies output filename\n" +
+                                  "    -oo obj             Specifies output filename for helper object file\n" +
+                                  "    -L path             Adds `path' to the search path for assemblies\n" +
+                                  "    --nodeps            Turns off automatic dependency embedding (default)\n" +
+                                  "    --deps              Turns on automatic dependency embedding\n" +
+                                  "    --keeptemp          Keeps the temporary files\n" +
+                                  "    --config F          Bundle system config file `F'\n" +
+                                  "    --config-dir D      Set MONO_CFG_DIR to `D'\n" +
+                                  "    --machine-config F  Use the given file as the machine.config for the application.\n" +
+                                  "    --static            Statically link to mono libs\n" +
+                                  "    --nomain            Don't include a main() function, for libraries\n" +
+                                  "    -z                  Compress the assemblies before embedding.\n" +
+                                  "                        You need zlib development headers and libraries.\n");
        }
 
        [DllImport ("libc")]
@@ -501,6 +556,7 @@ class MakeBundle {
                IntPtr buf = UnixMarshal.AllocHeap(8192);
                if (uname (buf) != 0){
                        Console.WriteLine ("Warning: Unable to detect OS");
+                       UnixMarshal.FreeHeap(buf);
                        return;
                }
                string os = Marshal.PtrToStringAnsi (buf);
@@ -514,17 +570,41 @@ class MakeBundle {
        static bool IsUnix {
                get {
                        int p = (int) Environment.OSVersion.Platform;
-                       return ((p == 4) || (p == 128));
+                       return ((p == 4) || (p == 128) || (p == 6));
                }
        }
 
        static int Execute (string cmdLine)
        {
-               Console.WriteLine (cmdLine);
                if (IsUnix) {
+                       Console.WriteLine (cmdLine);
                        return system (cmdLine);
-               } else {
-                       Process p = Process.Start ("sh", String.Format ("-c \"{0}\"", cmdLine));
+               }
+
+               // on Windows, we have to pipe the output of a
+               // `cmd` interpolation to dos2unix, because the shell does not
+               // strip the CRLFs generated by the native pkg-config distributed
+               // with Mono.
+               StringBuilder b = new StringBuilder ();
+               int count = 0;
+               for (int i = 0; i < cmdLine.Length; i++) {
+                       if (cmdLine [i] == '`') {
+                               if (count % 2 != 0) {
+                                       b.Append ("|dos2unix");
+                               }
+                               count++;
+                       }
+                       b.Append (cmdLine [i]);
+               }
+               cmdLine = b.ToString ();
+               Console.WriteLine (cmdLine);
+                       
+               ProcessStartInfo psi = new ProcessStartInfo ();
+               psi.UseShellExecute = false;
+               psi.FileName = "sh";
+               psi.Arguments = String.Format ("-c \"{0}\"", cmdLine);
+
+               using (Process p = Process.Start (psi)) {
                        p.WaitForExit ();
                        return p.ExitCode;
                }