1 module selfscript.compile; 2 3 version (Windows) { 4 import core.sys.windows.windows; 5 import selfscript.windll; 6 } 7 8 import std.stdio; 9 import std.process; 10 import f = std.file; 11 import std.string; 12 13 import selfscript.dload; 14 15 // general path and extension 16 private enum buildCache = "buildcache/"; 17 version (Windows) { 18 private enum fileExtension = "dll"; 19 } else { 20 private enum fileExtension = "so"; 21 } 22 23 // windows specific generated files 24 version (Windows) { 25 private enum winDllDefFile = buildCache~"dllSharedGcBody.def"; 26 private enum winDllFile = buildCache~"dllSharedGcBody.d"; 27 private enum winBuildFiles = [winDllDefFile,winDllFile]; 28 } 29 30 /// Creates the build cache folder 31 private void prepareBuilddir() 32 { 33 version (Windows) { 34 alias exceptionType = f.WindowsException; 35 } else { 36 alias exceptionType = f.FileException; 37 } 38 try { 39 f.mkdir(buildCache); 40 } 41 catch (exceptionType e) { 42 //ignore 43 } 44 // on windows, create these two files we need 45 version (Windows) { 46 f.write(winDllDefFile,winDllDefFileContent); 47 f.write(winDllFile,winDllFileContent); 48 } 49 } 50 51 //void makeTempfile(in char[] line) { 52 // prepareBuilddir(); 53 // f.write(tempDfile,"\n\n extern(C) export void dllFunc(){\n"~line~"\n}\n"); 54 //} 55 56 57 /** Compiles a file into a Script object. 58 * Parameters: 59 filename = name of the file to compile 60 buildDebug = if the script should be build with debug settings 61 Return: false on failure. 62 */ 63 bool compileScript(string filename, bool buildDebug = true, string[] compilerFlags = []) 64 { 65 import std.path; 66 67 prepareBuilddir(); 68 // build files 69 auto dmdCommandline = ["dmd", filename]; 70 version (Windows) { 71 dmdCommandline ~= winBuildFiles; 72 } 73 version (Posix) { 74 dmdCommandline ~= ["-shared","-defaultlib="]; 75 } 76 // dir and target 77 dmdCommandline ~= ["-od"~buildCache, "-of"~buildCache~baseName(filename,".d")~"."~fileExtension]; 78 // additional flags, likely for libs n shit 79 dmdCommandline ~= compilerFlags; 80 // build settings 81 if (buildDebug) { 82 dmdCommandline ~= ["-g","-map"]; 83 } else { 84 dmdCommandline ~= ["-O","-release", "-inline"]; 85 } 86 87 // execute and pray 88 if (wait(spawnProcess(dmdCommandline)) != 0) { 89 return false; 90 } 91 92 return true; 93 } 94 95 /** Evals a string input. 96 includes creating the target file, compiling it, loading it, exectuing it and unloading it. 97 Paramter: 98 input = the input to compile 99 tmpname = name for the temp. script object 100 Return: true on success, false on compiler or loading errors 101 */ 102 bool eval(string input, string tmpname="evaltmp", bool buildDebug = true, string[] compilerFlags=[]) 103 { 104 prepareBuilddir(); 105 auto fname = buildCache~tmpname~".d"; 106 f.write(fname,"\n\n extern(C) export void dllFunc(){\n"~input~"\n}\n"); 107 if (compileScript(fname,buildDebug,compilerFlags)) { 108 auto s = new ScriptObjectDShared(buildCache~tmpname); 109 s.execute(); 110 s.unload(); 111 112 return true; 113 } 114 115 return false; 116 }