[mkbundle] More Windows linking fixes, added "--custom-main" option
authorAlexis Christoforides <alexis@thenull.net>
Fri, 22 Jan 2016 22:38:32 +0000 (17:38 -0500)
committerAlexis Christoforides <alexis@thenull.net>
Tue, 26 Jan 2016 19:48:14 +0000 (14:48 -0500)
mcs/tools/mkbundle/mkbundle.cs

index fa39892bb03574f3d7a8a0f42533cef69a606f99..7a3936fd34b0b391e8705383f27b66576b5c9417 100755 (executable)
@@ -36,6 +36,7 @@ class MakeBundle {
        static string os_message = "";
        static bool compress;
        static bool nomain;
+       static string custom_main = null;
        static bool? use_dos2unix = null;
        static bool skip_scan;
        static string ctor_func;
@@ -134,6 +135,13 @@ class MakeBundle {
                        case "--nomain":
                                nomain = true;
                                break;
+                       case "--custom-main":
+                               if (i+1 == top) {
+                                       Help ();
+                                       return 1;
+                               }
+                               custom_main = args [++i];
+                               break;
                        case "--style":
                                if (i+1 == top) {
                                        Help ();
@@ -476,7 +484,7 @@ void          mono_register_config_for_assembly (const char* assembly_name, cons
                        string template = s.ReadToEnd ();
                        tc.Write (template);
 
-                       if (!nomain) {
+                       if (!nomain && custom_main == null) {
                                Stream template_main_stream = System.Reflection.Assembly.GetAssembly (typeof(MakeBundle)).GetManifestResourceStream ("template_main.c");
                                StreamReader st = new StreamReader (template_main_stream);
                                string maintemplate = st.ReadToEnd ();
@@ -502,37 +510,78 @@ void          mono_register_config_for_assembly (const char* assembly_name, cons
 
                                string compiler = GetEnv("CC", "cl.exe");
                                string winsdkPath = GetEnv("WINSDK", @"C:\Program Files (x86)\Windows Kits\8.1");
-                               string vsPath = GetEnv("VSINCLUDE", @"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC");
+                               string vsPath = GetEnv("VSINCLUDE", @"C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC");
                                string monoPath = GetEnv("MONOPREFIX", @"C:\Program Files (x86)\Mono");
 
-                               string[] includes = new string[] {winsdkPath + @"\Include\um", winsdkPath + @"\Include\shared", vsPath + @"\include", monoPath + @"\include\mono-2.0"};
+                               string[] includes = new string[] {winsdkPath + @"\Include\um", winsdkPath + @"\Include\shared", vsPath + @"\include", monoPath + @"\include\mono-2.0", "." };
                                string[] libs = new string[] { winsdkPath + @"\Lib\winv6.3\um\x86" , vsPath + @"\lib" };
-                               string monoFile;
-
-                               var compilerArgs = new List<string>();
-                               foreach (string include in includes)
-                                       compilerArgs.Add(String.Format ("/I {0}", quote (include)));
+                               var linkLibraries = new string[] {  "kernel32.lib",
+                                                                                               "version.lib",
+                                                                                               "Ws2_32.lib",
+                                                                                               "Mswsock.lib",
+                                                                                               "Psapi.lib",
+                                                                                               "shell32.lib",
+                                                                                               "OleAut32.lib",
+                                                                                               "ole32.lib",
+                                                                                               "winmm.lib",
+                                                                                               "user32.lib",
+                                                                                               "libvcruntime.lib",
+                                                                                               "advapi32.lib",
+                                                                                               "OLDNAMES.lib",
+                                                                                               "libucrt.lib" };
+
+                               string glue_obj = "mkbundle_glue.obj";
+                               string monoLib;
 
                                if (static_link)
-                                       monoFile = LocateFile (monoPath + @"\lib\monosgen-2.0.lib");
-                               else
-                                       monoFile = LocateFile (monoPath + @"\lib\monosgen-2.0.dll");
+                                       monoLib = LocateFile (monoPath + @"\lib\monosgen-2.0-static.lib");
 
-                               compilerArgs.Add("/MD");
-                               compilerArgs.Add(temp_c);
-                               compilerArgs.Add(temp_o);
-                               compilerArgs.Add("/link");
+                               else {
+                                       Console.WriteLine ("WARNING: Dynamically linking the Mono runtime on Windows is not a tested option.");
+                                       monoLib = LocateFile (monoPath + @"\lib\monosgen-2.0.lib");
+                                       LocateFile (monoPath + @"\lib\monosgen-2.0.dll"); // in this case, the .lib is just the import library, and the .dll is also needed
+                               }
 
-                               if (nomain)
-                                       compilerArgs.Add("/NOENTRY");
-                                       compilerArgs.Add("/DLL");
+                               var compilerArgs = new List<string>();
+                               compilerArgs.Add("/MT");
 
-                               foreach (string lib in libs)
-                                       compilerArgs.Add(String.Format ("/LIBPATH:{0}", quote(lib)));
-                               compilerArgs.Add (quote(monoFile));
+                               foreach (string include in includes)
+                                       compilerArgs.Add(String.Format ("/I {0}", quote (include)));
 
-                               string cl_cmd = String.Format("{0} {1}", compiler, String.Join(" ", compilerArgs.ToArray()));
-                               Execute (cl_cmd);
+                               if (!nomain || custom_main != null) {
+                                       compilerArgs.Add(temp_c);
+                                       compilerArgs.Add(temp_o);
+                                       if (custom_main != null)
+                                               compilerArgs.Add(quote(custom_main));
+                                       compilerArgs.Add(monoLib);
+                                       compilerArgs.Add("/link");
+                                       compilerArgs.Add("/NODEFAULTLIB");
+                                       compilerArgs.Add("/SUBSYSTEM:CONSOLE");
+                                       compilerArgs.AddRange(linkLibraries);
+                                       compilerArgs.Add("/out:"+ output);
+
+                                       string cl_cmd = String.Format("{0} {1}", compiler, String.Join(" ", compilerArgs.ToArray()));
+                                       Execute (cl_cmd);
+                               }
+                               else
+                               {
+                                       // we are just creating a .lib
+                                       compilerArgs.Add("/c"); // compile only
+                                       compilerArgs.Add(temp_c);
+                                       compilerArgs.Add(String.Format("/Fo" + glue_obj)); // .obj output name
+
+                                       string cl_cmd = String.Format("{0} {1}", compiler, String.Join(" ", compilerArgs.ToArray()));
+                                       Execute (cl_cmd);
+
+                                       string librarian = GetEnv ("LIB", "lib.exe");
+                                       var librarianArgs = new List<string> ();
+                                       librarianArgs.Add (String.Format ("/out:{0}.lib" + output));
+                                       librarianArgs.Add (temp_o);
+                                       librarianArgs.Add (glue_obj);
+                                       librarianArgs.Add (monoLib);
+                                       string lib_cmd = String.Format("{0} {1}", librarian, String.Join(" ", librarianArgs.ToArray()));
+                                       Execute (lib_cmd);
+                               }
                        }
                        else
                        {
@@ -724,6 +773,7 @@ void          mono_register_config_for_assembly (const char* assembly_name, cons
                                   "    --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" +
+                                  "    --custom-main C         Link the specified compilation unit (.c or .obj) with entry point/init code\n" +
                                   "    -z                  Compress the assemblies before embedding.\n" +
                                   "    --skip-scan         Skip scanning assemblies that could not be loaded (but still embed them).\n" +
                                   "    --static-ctor ctor  Add a constructor call to the supplied function.\n" +