static void Main(string[] args) { Console.WriteLine("Hello World!"); var unit = new CodeCompilationUnit(); var ns = unit.AddNamespace("Meziantou.CodeDom"); var c = ns.AddType(new CodeClassDeclaration("Sample")); var method = c.AddMember(new CodeMethodDeclaration("Factorial")); method.ReturnType = typeof(int); var n = method.AddArgument("n", typeof(int)); method.Modifiers = Modifiers.Public | Modifiers.Static; method.Statements = new CodeConditionStatement() { Condition = new CodeBinaryExpression(BinaryOperator.LessThanOrEqual, 1, n), TrueStatements = new CodeReturnStatement(1), FalseStatements = new CodeReturnStatement(new CodeBinaryExpression( BinaryOperator.Multiply, n, new CodeMethodInvokeExpression(method, new CodeBinaryExpression(BinaryOperator.Substract, n, 1)))) }; var generator = new CSharpCodeGenerator(); Console.WriteLine(generator.Write(unit)); }
public void RebuildLibraryAndAPI() { UpdateMsBuildPath(); CheckIspcBinary(); ProjectConfigKind configKind = ProjectConfigKind; SimpleVcxProjGen gen = new SimpleVcxProjGen(); //set some proprties //eg. IspcFilename=> simple.ispc string onlyProjectName = Path.GetFileNameWithoutExtension(IspcFilename); gen.ProjectName = onlyProjectName; //project name and output string current_dir = Directory.GetCurrentDirectory(); string tmp_dir = current_dir + "/temp"; gen.FullProjSrcPath = current_dir; gen.FullProjBuildPath = tmp_dir; string finalProductName = gen.GetFinalProductName(configKind); //----- CreateDirIfNotExists(tmp_dir); // string ispc_src = IspcFilename; string ispc_obj = tmp_dir + "/" + onlyProjectName + ".obj"; string ispc_llvm_text = tmp_dir + "/" + onlyProjectName + "_ispc.llvm.txt"; string ispc_cpp = tmp_dir + "/" + onlyProjectName + "_ispc.cpp"; string ispc_header = tmp_dir + "/" + onlyProjectName + "_ispc.h"; //generate header and object file in temp dir var procStartInfo = new System.Diagnostics.ProcessStartInfo(s_ispc, $"{ispc_src} -O2 -o {ispc_obj} -h {ispc_header}"); //$"{ispc_src} --emit-c++ -o {ispc_cpp}"); //$"{ispc_src} --emit-llvm-text -o {ispc_llvm_text} -h {ispc_header}"); procStartInfo.UseShellExecute = false; procStartInfo.RedirectStandardOutput = true; procStartInfo.RedirectStandardError = true; System.Diagnostics.Process proc = System.Diagnostics.Process.Start(procStartInfo); StreamReader errReader = proc.StandardError; { string line = errReader.ReadLine(); while (line != null) { System.Diagnostics.Debug.WriteLine(line); line = errReader.ReadLine(); } } StreamReader outputStrmReader = proc.StandardOutput; { string line = outputStrmReader.ReadLine(); while (line != null) { System.Diagnostics.Debug.WriteLine(line); line = outputStrmReader.ReadLine(); } } proc.WaitForExit(); int exit_code2 = proc.ExitCode; if (exit_code2 != 0) { throw new NotSupportedException(); } //---------- //now read auto-gen header string c_interface_filename = gen.FullProjSrcPath + "/" + onlyProjectName + ".cpp"; CodeCompilationUnit cu = ParseAutoGenHeaderFromFile(ispc_header); GenerateCBinder(cu, ispc_header, c_interface_filename); string cs_method_invoke_filename = onlyProjectName + ".cs"; //save to GenerateCsBinder(cu, ispc_header, cs_method_invoke_filename, Path.GetFileName(finalProductName)); //move cs code to src folder if (AutoCsTargetFile != null) { MoveFileOrReplaceIfExists(cs_method_invoke_filename, AutoCsTargetFile); } // //at this step we have object file and header //build a cpp dll with msbuild gen.AddObjectFile(ispc_obj); gen.AddIncludeFile(ispc_header); //add our c-interface gen.AddCompileFile(c_interface_filename); if (AdditionalInputItems != null) { foreach (string s in AdditionalInputItems) { switch (Path.GetExtension(s)) { default: throw new NotSupportedException(); case ".c": case ".cpp": gen.AddCompileFile(s); break; case ".h": case ".hpp": gen.AddIncludeFile(s); break; case ".obj": gen.AddObjectFile(s); break; } } } VcxProject project = gen.CreateVcxTemplate(); XmlOutputGen xmlOutput = new XmlOutputGen(); project.GenerateOutput(xmlOutput); string vxs_projOutputFilename = "ispc_autogen.xml.vcxproj"; File.WriteAllText(vxs_projOutputFilename, xmlOutput.Output.ToString()); //debug build or release build string p_config = ""; switch (configKind) { default: throw new NotSupportedException(); case ProjectConfigKind.Debug: p_config = " /p:configuration=debug"; break; case ProjectConfigKind.Release: p_config = " /p:configuration=release"; break; } System.Diagnostics.Process proc1 = System.Diagnostics.Process.Start(s_MsBuildPath, vxs_projOutputFilename + p_config); proc1.WaitForExit(); int exit_code1 = proc1.ExitCode; if (exit_code1 != 0) { throw new NotSupportedException(); } //build pass, then copy the result dll back MoveFileOrReplaceIfExists(finalProductName, Path.GetFileName(finalProductName)); }
/// <summary> /// generate C binder /// </summary> /// <param name="ispc_headerFilename"></param> /// <param name="outputC_filename"></param> void GenerateCBinder(CodeCompilationUnit cu, string ispc_headerFilename, string outputC_filename) { //from cu=> we generate interface c CodeStringBuilder sb = new CodeStringBuilder(); sb.AppendLine("//AUTOGEN," + DateTime.Now.ToString("s")); sb.AppendLine("//Tools: ispc and BridgeBuilder"); sb.AppendLine("//Src: " + ispc_headerFilename); sb.AppendLine("#include <stdio.h>"); sb.AppendLine("#include <stdlib.h>"); sb.AppendLine("//Include the header file that the ispc compiler generates"); sb.AppendLine($"#include \"{ Path.GetFileName(ispc_headerFilename) }\""); sb.AppendLine(@"#ifdef _WIN32 #define MY_DLL_EXPORT __declspec(dllexport) #else #define MY_DLL_EXPORT #endif "); sb.AppendLine("using namespace ispc;"); //c_inf.AppendLine("using namespace ispc;"); sb.AppendLine("extern \"C\"{"); foreach (CodeMemberDeclaration mb in cu.GlobalTypeDecl.GetMemberIter()) { if (mb is CodeTypeDeclaration namespaceDecl && namespaceDecl.Kind == TypeKind.Namespace) { //ispc output //iterate member inside the current namespace foreach (CodeMemberDeclaration nsMember in namespaceDecl.GetMemberIter()) { if (nsMember is CodeMethodDeclaration met) { sb.AppendLine("MY_DLL_EXPORT "); //WINDOWS sb.Append(met.ToString(IspcBridgeFunctionNamePrefix)); sb.AppendLine("{"); string ret = met.ReturnType.ToString(); if (ret != "void") { sb.Append("return "); } sb.Append("ispc::" + met.Name + "("); int par_i = 0; foreach (CodeMethodParameter par in met.Parameters) { if (par_i > 0) { sb.Append(","); } sb.Append(par.ParameterName); par_i++; } sb.AppendLine(");"); sb.AppendLine("}"); } else if (nsMember is CodeTypeDeclaration other && other.Kind == TypeKind.Struct) { //skip C struct regen }