From f72bee85ecb0b3bcc2c8dbcb40fb0232550f97d1 Mon Sep 17 00:00:00 2001 From: Matt Ward Date: Fri, 8 Jan 2010 21:02:56 +0000 Subject: [PATCH] Python compiler now generates executables that can be run from any directory. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/3.0@5385 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../Project/Src/PythonCompiler.cs | 49 ++++++++++++++----- 1 file changed, 36 insertions(+), 13 deletions(-) diff --git a/src/AddIns/BackendBindings/Python/Python.Build.Tasks/Project/Src/PythonCompiler.cs b/src/AddIns/BackendBindings/Python/Python.Build.Tasks/Project/Src/PythonCompiler.cs index f75aec175d..c75550d014 100644 --- a/src/AddIns/BackendBindings/Python/Python.Build.Tasks/Project/Src/PythonCompiler.cs +++ b/src/AddIns/BackendBindings/Python/Python.Build.Tasks/Project/Src/PythonCompiler.cs @@ -133,7 +133,7 @@ namespace ICSharpCode.Python.Build.Tasks /// Generates an executable from the already compiled dll. /// void GenerateExecutable(string outputAssemblyDll) - { + { string outputAssemblyFileNameWithoutExtension = Path.GetFileNameWithoutExtension(outputAssembly); AssemblyName assemblyName = new AssemblyName(outputAssemblyFileNameWithoutExtension); AssemblyBuilder assemblyBuilder = PythonOps.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave); @@ -141,14 +141,45 @@ namespace ICSharpCode.Python.Build.Tasks TypeBuilder typeBuilder = moduleBuilder.DefineType("PythonMain", TypeAttributes.Public); MethodBuilder mainMethod = typeBuilder.DefineMethod("Main", MethodAttributes.Public | MethodAttributes.Static, typeof(int), new Type[0]); - // Mark main method as STA. - mainMethod.SetCustomAttribute(typeof(STAThreadAttribute).GetConstructor(Type.EmptyTypes), new byte[0]); + MarkMainMethodAsSTA(mainMethod); + GenerateMainMethodBody(mainMethod, outputAssemblyDll); + + // Add resources. + AddResources(moduleBuilder); + // Create executable. + typeBuilder.CreateType(); + assemblyBuilder.SetEntryPoint(mainMethod, targetKind); + assemblyBuilder.Save(assemblyName.Name + ".exe", executableKind, machine); + } + + void MarkMainMethodAsSTA(MethodBuilder mainMethod) + { + mainMethod.SetCustomAttribute(typeof(STAThreadAttribute).GetConstructor(Type.EmptyTypes), new byte[0]); + } + + void GenerateMainMethodBody(MethodBuilder mainMethod, string outputAssemblyDll) + { ILGenerator generator = mainMethod.GetILGenerator(); + LocalBuilder exeAssemblyLocalVariable = generator.DeclareLocal(typeof(Assembly)); + LocalBuilder directoryLocalVariable = generator.DeclareLocal(typeof(string)); + LocalBuilder fileNameLocalVariable = generator.DeclareLocal(typeof(string)); + + generator.EmitCall(OpCodes.Call, typeof(Assembly).GetMethod("GetExecutingAssembly", new Type[0], new ParameterModifier[0]), null); + generator.Emit(OpCodes.Stloc_0); + + generator.Emit(OpCodes.Ldloc_0); + generator.EmitCall(OpCodes.Callvirt, typeof(Assembly).GetMethod("get_Location"), null); + generator.EmitCall(OpCodes.Call, typeof(Path).GetMethod("GetDirectoryName", new Type[] {typeof(String)}, new ParameterModifier[0]), null); + generator.Emit(OpCodes.Stloc_1); + + generator.Emit(OpCodes.Ldloc_1); generator.Emit(OpCodes.Ldstr, Path.GetFileName(outputAssemblyDll)); - generator.EmitCall(OpCodes.Call, typeof(Path).GetMethod("GetFullPath", new Type[] {typeof(String)}, new ParameterModifier[0]), null); - generator.EmitCall(OpCodes.Call, typeof(Assembly).GetMethod("LoadFile", new Type[] {typeof(String)}, new ParameterModifier[0]), null); + generator.EmitCall(OpCodes.Call, typeof(Path).GetMethod("Combine", new Type[] {typeof(String), typeof(String)}, new ParameterModifier[0]), null); + generator.Emit(OpCodes.Stloc_2); + generator.Emit(OpCodes.Ldloc_2); + generator.EmitCall(OpCodes.Call, typeof(Assembly).GetMethod("LoadFile", new Type[] {typeof(String)}, new ParameterModifier[0]), null); generator.Emit(OpCodes.Ldstr, Path.GetFileNameWithoutExtension(mainFile)); // Add referenced assemblies. @@ -156,14 +187,6 @@ namespace ICSharpCode.Python.Build.Tasks generator.EmitCall(OpCodes.Call, typeof(PythonOps).GetMethod("InitializeModule"), new Type[0]); generator.Emit(OpCodes.Ret); - - // Add resources. - AddResources(moduleBuilder); - - // Create executable. - typeBuilder.CreateType(); - assemblyBuilder.SetEntryPoint(mainMethod, targetKind); - assemblyBuilder.Save(assemblyName.Name + ".exe", executableKind, machine); } ///