我在 Windows 中使用 mkbundle 静态链接 Mono 时遇到问题。在我试图弄清楚发生了什么的过程中,我碰了壁。当您将静态标志传递给 Windows 中的 mkbundle 时,它会在 mono 目录中查找文件 monosgen-2.0-static.lib。该目录由以下行定义:
string monoPath = GetEnv("MONOPREFIX", @"C:\Program Files (x86)\Mono");
安装mono 5.1.1后这个目录的内容是:
首先,我注意到文件命名约定与 mkbundle 正在寻找的不同(monosgen-2.0 应该是 mono-2.0-sgen)。我可以很好地改变它,但是我怀疑 - 给定文件名 - 屏幕截图中显示的 mono-2.0-sgen.lib 文件不是静态编译的,因为当我尝试运行我的捆绑应用程序时它首先不能找到sgen dll,然后找不到其他的。
在这一点上,我想知道 mkbundle 是否在 Windows 上正式工作,如果它确实是我做的根本错误?我看过较早的帖子寻求帮助在 Windows 中设置 mkbundle,并且我自己也发布了关于此的问题。大多数都指向使用 mingw 而不是 cl.exe。我应该改用这个吗?
此代码段的来源如下所示。你可以在这里找到完整的源代码https://github.com/mono/mono/blob/master/mcs/tools/mkbundle/mkbundle.cs。
if (style == "windows")
{
Func<string, string> quote = (pp) => { return "\"" + pp + "\""; };
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 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[] libs = new string[] { winsdkPath + @"\Lib\winv6.3\um\x86" , vsPath + @"\lib" };
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)
monoLib = LocateFile (monoPath + @"\lib\monosgen-2.0-static.lib");
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
}
var compilerArgs = new List<string>();
compilerArgs.Add("/MT");
foreach (string include in includes)
compilerArgs.Add(String.Format ("/I {0}", quote (include)));
if (!nomain || custom_main != null) {
compilerArgs.Add(quote(temp_c));
compilerArgs.Add(quote(temp_o));
if (custom_main != null)
compilerArgs.Add(quote(custom_main));
compilerArgs.Add(quote(monoLib));
compilerArgs.Add("/link");
compilerArgs.Add("/NODEFAULTLIB");
compilerArgs.Add("/SUBSYSTEM:windows");
compilerArgs.Add("/ENTRY:mainCRTStartup");
compilerArgs.AddRange(linkLibraries);
compilerArgs.Add("/out:"+ output);
string cl_cmd = String.Format("{0} {1}", compiler, String.Join(" ", compilerArgs.ToArray()));
Execute (cl_cmd);
}