static int Main() { SetupPath(); string includeRoot = Path.Combine( Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "include"); var config = new PInvokeGeneratorConfiguration( libraryPath: "openxr_loader", namespaceName: "OpenXR.PInvoke", options: PInvokeGeneratorConfigurationOptions.GenerateMultipleFiles, outputLocation: "gen", methodClassName: "XR", methodPrefixToStrip: "xr" ); string[] files = new[] { "openxr/openxr.h" } .Select(name => Path.Combine(includeRoot, name)) .ToArray(); int exitCode = 0; var translationFlags = CXTranslationUnit_Flags.CXTranslationUnit_None; translationFlags |= CXTranslationUnit_Flags.CXTranslationUnit_IncludeAttributedTypes; // Include attributed types in CXType translationFlags |= CXTranslationUnit_Flags.CXTranslationUnit_VisitImplicitAttributes; // Implicit attributes should be visited var clangCommandLineArgs = new List <string> { "--include-directory=" + includeRoot, "--include-directory=" + Path.Combine(NugetPackagesRoot, "cppsharp", "0.10.1", "output", "lib", "clang", "9.0.0", "include"), "--language=c++", }; using (var generator = new PInvokeGenerator(config)) { foreach (string file in files) { var translationUnitError = CXTranslationUnit.TryParse(generator.IndexHandle, file, clangCommandLineArgs.ToArray().AsSpan(), Array.Empty <CXUnsavedFile>(), translationFlags, out CXTranslationUnit handle); bool skipProcessing = false; if (translationUnitError != CXErrorCode.CXError_Success) { Console.WriteLine($"Error: Parsing failed for '{file}' due to '{translationUnitError}'."); skipProcessing = true; } else if (handle.NumDiagnostics != 0) { Console.WriteLine($"Diagnostics for '{file}':"); for (uint i = 0; i < handle.NumDiagnostics; ++i) { using var diagnostic = handle.GetDiagnostic(i); Console.Write(" "); Console.WriteLine(diagnostic.Format(CXDiagnostic.DefaultDisplayOptions).ToString()); skipProcessing |= (diagnostic.Severity == CXDiagnosticSeverity.CXDiagnostic_Error); skipProcessing |= (diagnostic.Severity == CXDiagnosticSeverity.CXDiagnostic_Fatal); } } if (skipProcessing) { Console.WriteLine($"Skipping '{file}' due to one or more errors listed above."); Console.WriteLine(); exitCode = -1; continue; } using var translationUnit = TranslationUnit.GetOrCreate(handle); Console.WriteLine($"Processing '{file}'"); generator.GenerateBindings(translationUnit); } if (generator.Diagnostics.Count != 0) { Console.WriteLine("Diagnostics for binding generation:"); foreach (var diagnostic in generator.Diagnostics) { Console.Write(" "); Console.WriteLine(diagnostic); if (diagnostic.Level == DiagnosticLevel.Warning) { if (exitCode >= 0) { exitCode++; } } else if (diagnostic.Level == DiagnosticLevel.Error) { if (exitCode >= 0) { exitCode = -1; } else { exitCode--; } } } } } return(exitCode); }
/// <summary> /// Build the Clang AST /// </summary> private TranslationUnit BuildClangAST(Configuration config, CXIndex index) { CXTranslationUnit tu = null; using (var section = CreateSection("Building Clang AST")) { // Assemble the arguments var clangArgs = new List <string>() { "-Wno-pragma-once-outside-header" }; switch (config.Clang.Language) { case LanguageEnum.C99: clangArgs.Add("-xc"); clangArgs.Add("-std=c99"); break; case LanguageEnum.Cpp11: clangArgs.Add("-xc++"); clangArgs.Add("-std=c++11"); break; case LanguageEnum.Cpp14: clangArgs.Add("-xc++"); clangArgs.Add("-std=c++14"); break; case LanguageEnum.Cpp17: clangArgs.Add("-xc++"); clangArgs.Add("-std=c++17"); break; default: throw new Exception($"unknown language {config.Clang.Language}"); } clangArgs.AddRange(GetWinSDKDIncludeArgs(config)); clangArgs.AddRange(GetCxxSTLIncludeArgs(config)); clangArgs.AddRange(config.Clang.Includes.Select(i => MakeIncludeArg(i))); clangArgs.AddRange(config.Clang.Defines.Select((m, v) => $"-D{m}=\"{v}\"")); clangArgs.AddRange(config.Clang.Arguments.Split(" ")); var tuFlags = CXTranslationUnit_Flags.CXTranslationUnit_SkipFunctionBodies; // Create the TU source file var sourceFiles = new HashSet <string>(); config.Hook.Descriptions.Values.ToList().ForEach(hook => hook.Input.ForEach(source => sourceFiles.Add(source))); var tuFilename = Path.GetFileNameWithoutExtension(string.IsNullOrEmpty(config.Plugin.Name) ? Path.GetTempFileName() : config.Plugin.Name) + ".cpp"; Logger.Debug($"Clang TU filename: {tuFilename}"); var tuSource = "#include <" + string.Join(">\n#include <", sourceFiles) + ">"; Logger.Debug($"Clang TU source:\n {tuSource.Replace("\n", "\n ")}"); using (var tuSourceFile = CXUnsavedFile.Create(tuFilename, tuSource)) { // Invoke clang to get the TU Logger.Debug($"Clang args: {string.Join(" ", clangArgs)}"); var tuError = CXTranslationUnit.TryParse(index, tuSourceFile.FilenameString, clangArgs.ToArray(), new CXUnsavedFile[] { tuSourceFile }, tuFlags, out tu); if (tuError != CXErrorCode.CXError_Success) { throw new Exception($"clang error: failed to generate tanslation unit: {tuError}"); } } section.Done(); } if (tu == null) { return(null); } return(TranslationUnit.GetOrCreate(tu)); }