// Licensed to the .NET Foundation under one or more agreements.// The .NET Foundation licenses this file to you under the Apache 2.0 License.// See the LICENSE file in the project root for more information.using System;using System.Collections.Generic;using System.IO;using System.Resources;using IKVM.Reflection;using IKVM.Reflection.Emit;using IronPython.Hosting;using IronPython.Runtime;using IronPython.Runtime.Operations;using Microsoft.Scripting.Hosting;using Microsoft.Scripting.Runtime;using Type = IKVM.Reflection.Type;namespace IronPython.Compiler {public class Program {/// <summary>/// Generates the stub .exe file for starting the app/// </summary>/// <param name="config"></param>private static void GenerateExe(Config config) {var u = new Universe();var aName = new AssemblyName(Path.GetFileNameWithoutExtension(new FileInfo(config.Output).Name));var ab = u.DefineDynamicAssembly(aName, AssemblyBuilderAccess.Save, config.OutputPath);var mb = ab.DefineDynamicModule(config.Output, aName.Name + (aName.Name.EndsWith(".exe", StringComparison.Ordinal) ? string.Empty : ".exe"));var tb = mb.DefineType("PythonMain", IKVM.Reflection.TypeAttributes.Public);if (!string.IsNullOrEmpty(config.Win32Icon)) {ab.__DefineIconResource(File.ReadAllBytes(config.Win32Icon));}var attributes = new List<Tuple<string, Type>> {Tuple.Create(config.FileVersion, u.Import(typeof(System.Reflection.AssemblyFileVersionAttribute))),Tuple.Create(config.ProductName, u.Import(typeof(System.Reflection.AssemblyProductAttribute))),Tuple.Create(config.ProductVersion, u.Import(typeof(System.Reflection.AssemblyInformationalVersionAttribute))),Tuple.Create(config.Copyright, u.Import(typeof(System.Reflection.AssemblyCopyrightAttribute)))};foreach (var attr in attributes) {if (!string.IsNullOrWhiteSpace(config.FileVersion)) {CustomAttributeBuilder builder = new CustomAttributeBuilder(attr.Item2.GetConstructor(new[] { u.Import(typeof(string)) }), new object[] { attr.Item1 });ab.SetCustomAttribute(builder);}}ab.DefineVersionInfoResource();MethodBuilder assemblyResolveMethod = null;ILGenerator gen = null;if (config.Standalone) {ConsoleOps.Info("Generating stand alone executable");config.Embed = true;var embedAssemblies = new HashSet<string> {// DLR"Microsoft.Dynamic","Microsoft.Scripting",// System.Memory"System.Buffers","System.Memory","System.Numerics.Vectors","System.Runtime.CompilerServices.Unsafe",};foreach (var a in System.AppDomain.CurrentDomain.GetAssemblies()) {var n = new AssemblyName(a.FullName);if (!a.IsDynamic && a.EntryPoint == null && (n.Name.StartsWith("IronPython", StringComparison.Ordinal) || embedAssemblies.Contains(n.Name))) {ConsoleOps.Info($"\tEmbedded {n.Name}{n.Version}");var f = new FileStream(a.Location, FileMode.Open, FileAccess.Read);mb.DefineManifestResource("Dll." + n.Name, f, IKVM.Reflection.ResourceAttributes.Public);}}foreach (var dll in config.DLLs) {var name = Path.GetFileNameWithoutExtension(dll);ConsoleOps.Info($"\tEmbedded {name}");var f = new FileStream(dll, FileMode.Open, FileAccess.Read);mb.DefineManifestResource("Dll." + name, f, IKVM.Reflection.ResourceAttributes.Public);}// we currently do no error checking on what is passed in to the assemblyresolve event handlerassemblyResolveMethod = tb.DefineMethod("AssemblyResolve", MethodAttributes.Public | MethodAttributes.Static, u.Import(typeof(System.Reflection.Assembly)), new IKVM.Reflection.Type[] { u.Import(typeof(System.Object)), u.Import(typeof(System.ResolveEventArgs)) });gen = assemblyResolveMethod.GetILGenerator();var s = gen.DeclareLocal(u.Import(typeof(System.IO.Stream))); // resource streamgen.Emit(OpCodes.Ldnull);gen.Emit(OpCodes.Stloc, s);var d = gen.DeclareLocal(u.Import(typeof(byte[]))); // data buffer;gen.EmitCall(OpCodes.Call, u.Import(typeof(System.Reflection.Assembly)).GetMethod("GetEntryAssembly"), Type.EmptyTypes);gen.Emit(OpCodes.Ldstr, "Dll.");gen.Emit(OpCodes.Ldarg_1); // The event argsgen.EmitCall(OpCodes.Callvirt, u.Import(typeof(System.ResolveEventArgs)).GetMethod("get_Name"), Type.EmptyTypes);gen.Emit(OpCodes.Newobj, u.Import(typeof(System.Reflection.AssemblyName)).GetConstructor(new IKVM.Reflection.Type[] { u.Import(typeof(string)) }));gen.EmitCall(OpCodes.Call, u.Import(typeof(System.Reflection.AssemblyName)).GetMethod("get_Name"), Type.EmptyTypes);gen.EmitCall(OpCodes.Call, u.Import(typeof(string)).GetMethod("Concat", new IKVM.Reflection.Type[] { u.Import(typeof(string)), u.Import(typeof(string)) }), Type.EmptyTypes);gen.EmitCall(OpCodes.Callvirt, u.Import(typeof(System.Reflection.Assembly)).GetMethod("GetManifestResourceStream", new IKVM.Reflection.Type[] { u.Import(typeof(string)) }), Type.EmptyTypes);gen.Emit(OpCodes.Stloc, s);gen.Emit(OpCodes.Ldloc, s);gen.EmitCall(OpCodes.Callvirt, u.Import(typeof(System.IO.Stream)).GetMethod("get_Length"), Type.EmptyTypes);gen.Emit(OpCodes.Newarr, u.Import(typeof(System.Byte)));gen.Emit(OpCodes.Stloc, d);gen.Emit(OpCodes.Ldloc, s);gen.Emit(OpCodes.Ldloc, d);gen.Emit(OpCodes.Ldc_I4_0);gen.Emit(OpCodes.Ldloc, s);gen.EmitCall(OpCodes.Callvirt, u.Import(typeof(System.IO.Stream)).GetMethod("get_Length"), Type.EmptyTypes);gen.Emit(OpCodes.Conv_I4);gen.EmitCall(OpCodes.Callvirt, u.Import(typeof(System.IO.Stream)).GetMethod("Read", new IKVM.Reflection.Type[] { u.Import(typeof(byte[])), u.Import(typeof(int)), u.Import(typeof(int)) }), Type.EmptyTypes);gen.Emit(OpCodes.Pop);gen.Emit(OpCodes.Ldloc, d);gen.EmitCall(OpCodes.Call, u.Import(typeof(System.Reflection.Assembly)).GetMethod("Load", new IKVM.Reflection.Type[] { u.Import(typeof(byte[])) }), Type.EmptyTypes);gen.Emit(OpCodes.Ret);// generate a static constructor to assign the AssemblyResolve handler (otherwise it tries to use IronPython before it adds the handler)// the other way of handling this would be to move the call to InitializeModule into a separate method.var staticConstructor = tb.DefineConstructor(MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, Type.EmptyTypes);gen = staticConstructor.GetILGenerator();gen.EmitCall(OpCodes.Call, u.Import(typeof(System.AppDomain)).GetMethod("get_CurrentDomain"), Type.EmptyTypes);gen.Emit(OpCodes.Ldnull);gen.Emit(OpCodes.Ldftn, assemblyResolveMethod);gen.Emit(OpCodes.Newobj, u.Import(typeof(System.ResolveEventHandler)).GetConstructor(new IKVM.Reflection.Type[] { u.Import(typeof(object)), u.Import(typeof(System.IntPtr)) }));gen.EmitCall(OpCodes.Callvirt, u.Import(typeof(System.AppDomain)).GetMethod("add_AssemblyResolve"), Type.EmptyTypes);gen.Emit(OpCodes.Ret);}var mainMethod = tb.DefineMethod("Main", MethodAttributes.Public | MethodAttributes.Static, u.Import(typeof(int)), Type.EmptyTypes);if (config.Target == PEFileKinds.WindowApplication && config.UseMta) {mainMethod.SetCustomAttribute(u.Import(typeof(System.MTAThreadAttribute)).GetConstructor(Type.EmptyTypes), Array.Empty<byte>());} else if (config.Target == PEFileKinds.WindowApplication || config.Target == PEFileKinds.ConsoleApplication && config.UseSta) {mainMethod.SetCustomAttribute(u.Import(typeof(System.STAThreadAttribute)).GetConstructor(Type.EmptyTypes), Array.Empty<byte>());}gen = mainMethod.GetILGenerator();// variables for saving original working directory and return code of scriptvar strVar = gen.DeclareLocal(u.Import(typeof(string)));var intVar = gen.DeclareLocal(u.Import(typeof(int)));LocalBuilder dictVar = null;if (config.PythonOptions.Count > 0) {var True = u.Import(typeof(ScriptingRuntimeHelpers)).GetField("True");var False = u.Import(typeof(ScriptingRuntimeHelpers)).GetField("False");dictVar = gen.DeclareLocal(u.Import(typeof(Dictionary<string, object>)));gen.Emit(OpCodes.Newobj, u.Import(typeof(Dictionary<string, object>)).GetConstructor(Type.EmptyTypes));gen.Emit(OpCodes.Stloc, dictVar);foreach (var option in config.PythonOptions) {gen.Emit(OpCodes.Ldloc, dictVar);gen.Emit(OpCodes.Ldstr, option.Key);if (option.Value is int val) {if (val >= -128 && val <= 127)gen.Emit(OpCodes.Ldc_I4_S, val); // this is more optimizedelsegen.Emit(OpCodes.Ldc_I4, val);gen.Emit(OpCodes.Box, u.Import(typeof(System.Int32)));} else if (option.Value.Equals(ScriptingRuntimeHelpers.True)) {gen.Emit(OpCodes.Ldsfld, True);} else if (option.Value.Equals(ScriptingRuntimeHelpers.False)) {gen.Emit(OpCodes.Ldsfld, False);}gen.EmitCall(OpCodes.Callvirt, u.Import(typeof(Dictionary<string, object>)).GetMethod("Add", new IKVM.Reflection.Type[] { u.Import(typeof(string)), u.Import(typeof(object)) }), Type.EmptyTypes);}}Label tryStart = gen.BeginExceptionBlock();// get the ScriptCode assembly...if (config.Embed) {// put the generated DLL into the resources for the stub exevar mem = new MemoryStream();var rw = new ResourceWriter(mem);rw.AddResource("IPDll." + Path.GetFileNameWithoutExtension(config.Output) + ".dll", File.ReadAllBytes(Path.Combine(config.OutputPath, config.Output) + ".dll"));rw.Generate();mem.Position = 0;mb.DefineManifestResource("IPDll.resources", mem, ResourceAttributes.Public);File.Delete(Path.Combine(config.OutputPath, config.Output) + ".dll");// generate code to load the resourcegen.Emit(OpCodes.Ldstr, "IPDll");gen.EmitCall(OpCodes.Call, u.Import(typeof(System.Reflection.Assembly)).GetMethod("GetEntryAssembly"), Type.EmptyTypes);gen.Emit(OpCodes.Newobj, u.Import(typeof(System.Resources.ResourceManager)).GetConstructor(new IKVM.Reflection.Type[] { u.Import(typeof(string)), u.Import(typeof(System.Reflection.Assembly)) }));gen.Emit(OpCodes.Ldstr, "IPDll." + Path.GetFileNameWithoutExtension(config.Output) + ".dll");gen.EmitCall(OpCodes.Call, u.Import(typeof(System.Resources.ResourceManager)).GetMethod("GetObject", new IKVM.Reflection.Type[] { u.Import(typeof(string)) }), Type.EmptyTypes);gen.EmitCall(OpCodes.Call, u.Import(typeof(System.Reflection.Assembly)).GetMethod("Load", new IKVM.Reflection.Type[] { u.Import(typeof(byte[])) }), Type.EmptyTypes);} else {// save current working directorygen.EmitCall(OpCodes.Call, u.Import(typeof(System.Environment)).GetMethod("get_CurrentDirectory"), Type.EmptyTypes);gen.Emit(OpCodes.Stloc, strVar);gen.EmitCall(OpCodes.Call, u.Import(typeof(System.Reflection.Assembly)).GetMethod("GetEntryAssembly"), Type.EmptyTypes);gen.EmitCall(OpCodes.Callvirt, u.Import(typeof(System.Reflection.Assembly)).GetMethod("get_Location"), Type.EmptyTypes);gen.Emit(OpCodes.Newobj, u.Import(typeof(System.IO.FileInfo)).GetConstructor(new IKVM.Reflection.Type[] { u.Import(typeof(string)) }));gen.EmitCall(OpCodes.Call, u.Import(typeof(System.IO.FileInfo)).GetMethod("get_Directory"), Type.EmptyTypes);gen.EmitCall(OpCodes.Call, u.Import(typeof(System.IO.DirectoryInfo)).GetMethod("get_FullName"), Type.EmptyTypes);gen.EmitCall(OpCodes.Call, u.Import(typeof(System.Environment)).GetMethod("set_CurrentDirectory"), Type.EmptyTypes);gen.Emit(OpCodes.Ldstr, config.Output + ".dll");gen.EmitCall(OpCodes.Call, u.Import(typeof(System.IO.Path)).GetMethod("GetFullPath", new IKVM.Reflection.Type[] { u.Import(typeof(string)) }), Type.EmptyTypes);// result of GetFullPath stays on the stack during the restore of the// original working directory// restore original working directorygen.Emit(OpCodes.Ldloc, strVar);gen.EmitCall(OpCodes.Call, u.Import(typeof(System.Environment)).GetMethod("set_CurrentDirectory"), Type.EmptyTypes);// for the LoadFile() call, the full path of the assembly is still is on the stack// as the result from the call to GetFullPath()gen.EmitCall(OpCodes.Call, u.Import(typeof(System.Reflection.Assembly)).GetMethod("LoadFile", new IKVM.Reflection.Type[] { u.Import(typeof(string)) }), Type.EmptyTypes);}// emit module namegen.Emit(OpCodes.Ldstr, "__main__"); // main module namegen.Emit(OpCodes.Ldnull); // no referencesgen.Emit(OpCodes.Ldc_I4_0); // don't ignore environment variables for engine startupif (config.PythonOptions.Count > 0) {gen.Emit(OpCodes.Ldloc, dictVar);} else {gen.Emit(OpCodes.Ldnull);}// call InitializeModuleEx// (this will also run the script)// and put the return code on the stackgen.EmitCall(OpCodes.Call, u.Import(typeof(PythonOps)).GetMethod(nameof(PythonOps.InitializeModuleEx),new IKVM.Reflection.Type[] { u.Import(typeof(System.Reflection.Assembly)), u.Import(typeof(string)), u.Import(typeof(string[])), u.Import(typeof(bool)), u.Import(typeof(Dictionary<string, object>)) }),Type.EmptyTypes);gen.Emit(OpCodes.Stloc, intVar);gen.BeginCatchBlock(u.Import(typeof(Exception)));if (config.Target == PEFileKinds.ConsoleApplication) {gen.EmitCall(OpCodes.Callvirt, u.Import(typeof(System.Exception)).GetMethod("get_Message", Type.EmptyTypes), Type.EmptyTypes);gen.Emit(OpCodes.Stloc, strVar);gen.Emit(OpCodes.Ldstr, config.ErrorMessageFormat);gen.Emit(OpCodes.Ldloc, strVar);gen.EmitCall(OpCodes.Call, u.Import(typeof(System.Console)).GetMethod("WriteLine", new IKVM.Reflection.Type[] { u.Import(typeof(string)), u.Import(typeof(string)) }), Type.EmptyTypes);} else {gen.EmitCall(OpCodes.Callvirt, u.Import(typeof(System.Exception)).GetMethod("get_Message", Type.EmptyTypes), Type.EmptyTypes);gen.Emit(OpCodes.Stloc, strVar);gen.Emit(OpCodes.Ldstr, config.ErrorMessageFormat);gen.Emit(OpCodes.Ldloc, strVar);gen.EmitCall(OpCodes.Call, u.Import(typeof(string)).GetMethod("Format", new IKVM.Reflection.Type[] { u.Import(typeof(string)), u.Import(typeof(string)) }), Type.EmptyTypes);gen.Emit(OpCodes.Ldstr, "Error");gen.Emit(OpCodes.Ldc_I4, (int)System.Windows.Forms.MessageBoxButtons.OK);gen.Emit(OpCodes.Ldc_I4, (int)System.Windows.Forms.MessageBoxIcon.Error);gen.EmitCall(OpCodes.Call, u.Import(typeof(System.Windows.Forms.MessageBox)).GetMethod("Show", new IKVM.Reflection.Type[] { u.Import(typeof(string)), u.Import(typeof(string)), u.Import(typeof(System.Windows.Forms.MessageBoxButtons)), u.Import(typeof(System.Windows.Forms.MessageBoxIcon)) }), Type.EmptyTypes);gen.Emit(OpCodes.Pop);}gen.Emit(OpCodes.Ldc_I4, -1); // return code is -1 to show failuregen.Emit(OpCodes.Stloc, intVar);gen.EndExceptionBlock();gen.Emit(OpCodes.Ldloc, intVar);gen.Emit(OpCodes.Ret);tb.CreateType();ab.SetEntryPoint(mainMethod, config.Target);string fileName = aName.Name.EndsWith(".exe", StringComparison.Ordinal) ? aName.Name : aName.Name + ".exe";ab.Save(fileName, config.Platform, config.Machine);}public static int Main(string[] args) {var files = new List<string>();var config = new Config();config.ParseArgs(args);if (!config.Validate()) {ConsoleOps.Usage(true);}// we don't use the engine, but we create it so we can have a default context.ScriptEngine engine = Python.CreateEngine(config.PythonOptions);ConsoleOps.Info($"IronPython Compiler for {engine.Setup.DisplayName} ({engine.LanguageVersion})");ConsoleOps.Info($"{config}");ConsoleOps.Info("compiling...");var compileOptions = new Dictionary<string, object>() {{ "mainModule", config.MainName },{ "assemblyFileVersion", config.FileVersion },{ "copyright", config.Copyright },{ "productName", config.ProductName },{ "productVersion", config.ProductVersion },};try {ClrModule.CompileModules(DefaultContext.DefaultCLS,Path.Combine(config.OutputPath, Path.ChangeExtension(config.Output, ".dll")),compileOptions,config.Files.ToArray());var outputfilename = Path.Combine(config.OutputPath, Path.ChangeExtension(config.Output, ".dll"));if (config.Target != PEFileKinds.Dll) {outputfilename = Path.Combine(config.OutputPath, Path.ChangeExtension(config.Output, ".exe"));GenerateExe(config);}ConsoleOps.Info($"Saved to {outputfilename}");} catch (Exception e) {Console.WriteLine();ConsoleOps.Error(true, e.Message);}return 0;}}}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。