using CppSharp.Parser.AST; using System.Reflection; using LanguageVersion = CppSharp.Parser.LanguageVersion; using System.Globalization; using System.Collections.Generic; using System.Linq; namespace CppSharp.Parser { public enum LanguageVersion { /// /// C programming language (year 1999). /// C99, /// /// C programming language (year 1999, GNU variant). /// C99_GNU, /// /// C++ programming language (year 1998). /// CPP98, /// /// C++ programming language (year 1998, GNU variant). /// CPP98_GNU, /// /// C++ programming language (year 2011). /// CPP11, /// /// C++ programming language (year 2011, GNU variant). /// CPP11_GNU, /// /// C++ programming language (year 2014). /// CPP14, /// /// C++ programming language (year 2014, GNU variant). /// CPP14_GNU, /// /// C++ programming language (year 2017). /// CPP17, /// /// C++ programming language (year 2017, GNU variant). /// CPP17_GNU, } public class ParserOptions : CppParserOptions { public ParserOptions() { Abi = Platform.IsUnixPlatform ? CppAbi.Itanium : CppAbi.Microsoft; MicrosoftMode = !Platform.IsUnixPlatform; CurrentDir = Assembly.GetExecutingAssembly().Location; } public bool IsItaniumLikeAbi => Abi != CppAbi.Microsoft; public bool IsMicrosoftAbi => Abi == CppAbi.Microsoft; public bool EnableRTTI { get; set; } public LanguageVersion? LanguageVersion { get; set; } public ParserOptions BuildForSourceFile( IEnumerable modules, string file = null) { var options = new ParserOptions { Abi = this.Abi, ToolSetToUse = this.ToolSetToUse, TargetTriple = this.TargetTriple, NoStandardIncludes = this.NoStandardIncludes, NoBuiltinIncludes = this.NoBuiltinIncludes, MicrosoftMode = this.MicrosoftMode, Verbose = this.Verbose, LanguageVersion = this.LanguageVersion }; // This eventually gets passed to Clang's MSCompatibilityVersion, which // is in turn used to derive the value of the built-in define _MSC_VER. // It used to receive a 4-digit based identifier but now expects a full // version MSVC digit, so check if we still have the old version and // convert to the right format. if (ToolSetToUse.ToString(CultureInfo.InvariantCulture).Length == 4) ToolSetToUse *= 100000; for (uint i = 0; i < ArgumentsCount; ++i) { var arg = GetArguments(i); options.AddArguments(arg); } for (uint i = 0; i < IncludeDirsCount; ++i) { var include = GetIncludeDirs(i); options.AddIncludeDirs(include); } for (uint i = 0; i < SystemIncludeDirsCount; ++i) { var include = GetSystemIncludeDirs(i); options.AddSystemIncludeDirs(include); } for (uint i = 0; i < DefinesCount; ++i) { var define = GetDefines(i); options.AddDefines(define); } for (uint i = 0; i < UndefinesCount; ++i) { var define = GetUndefines(i); options.AddUndefines(define); } for (uint i = 0; i < LibraryDirsCount; ++i) { var lib = GetLibraryDirs(i); options.AddLibraryDirs(lib); } foreach (var module in modules.Where( m => file == null || m.Headers.Contains(file))) { foreach (var include in module.IncludeDirs) options.AddIncludeDirs(include); foreach (var define in module.Defines) options.AddDefines(define); foreach (var undefine in module.Undefines) options.AddUndefines(undefine); foreach (var libraryDir in module.LibraryDirs) options.AddLibraryDirs(libraryDir); } return options; } public void SetupMSVC() { var vsVersion = VisualStudioVersion.Latest; // Silence "warning CS0162: Unreachable code detected" #pragma warning disable 162 switch (BuildConfig.Choice) { case "vs2012": vsVersion = VisualStudioVersion.VS2012; break; case "vs2013": vsVersion = VisualStudioVersion.VS2013; break; case "vs2015": vsVersion = VisualStudioVersion.VS2015; break; case "vs2017": vsVersion = VisualStudioVersion.VS2017; break; #pragma warning restore 162 } SetupMSVC(vsVersion); } /// /// Sets up the parser options to work with the given Visual Studio toolchain. /// /// The version of Visual Studio to look for. public void SetupMSVC(VisualStudioVersion vsVersion) { MicrosoftMode = true; NoBuiltinIncludes = true; NoStandardIncludes = true; Abi = CppAbi.Microsoft; vsVersion = MSVCToolchain.FindVSVersion(vsVersion); foreach (var include in MSVCToolchain.GetSystemIncludes(vsVersion)) AddSystemIncludeDirs(include); // do not remove the CppSharp prefix becase the Mono C# compiler breaks if (!LanguageVersion.HasValue) LanguageVersion = CppSharp.Parser.LanguageVersion.CPP14_GNU; var clVersion = MSVCToolchain.GetCLVersion(vsVersion); ToolSetToUse = clVersion.Major * 10000000 + clVersion.Minor * 100000; AddArguments("-fms-extensions"); AddArguments("-fms-compatibility"); AddArguments("-fdelayed-template-parsing"); } public void SetupXcode() { var builtinsPath = XcodeToolchain.GetXcodeBuiltinIncludesFolder(); AddSystemIncludeDirs(builtinsPath); var cppIncPath = XcodeToolchain.GetXcodeCppIncludesFolder(); AddSystemIncludeDirs(cppIncPath); var includePath = XcodeToolchain.GetXcodeIncludesFolder(); AddSystemIncludeDirs(includePath); NoBuiltinIncludes = true; NoStandardIncludes = true; AddArguments("-stdlib=libc++"); } public void Setup() { SetupArguments(); if (!NoBuiltinIncludes) SetupIncludes(); } private void SetupArguments() { // do not remove the CppSharp prefix becase the Mono C# compiler breaks if (!LanguageVersion.HasValue) LanguageVersion = CppSharp.Parser.LanguageVersion.CPP14_GNU; switch (LanguageVersion) { case CppSharp.Parser.LanguageVersion.C99: case CppSharp.Parser.LanguageVersion.C99_GNU: AddArguments("-xc"); break; default: AddArguments("-xc++"); break; } switch (LanguageVersion) { case CppSharp.Parser.LanguageVersion.C99: AddArguments("-std=c99"); break; case CppSharp.Parser.LanguageVersion.C99_GNU: AddArguments("-std=gnu99"); break; case CppSharp.Parser.LanguageVersion.CPP98: AddArguments("-std=c++98"); break; case CppSharp.Parser.LanguageVersion.CPP98_GNU: AddArguments("-std=gnu++98"); break; case CppSharp.Parser.LanguageVersion.CPP11: AddArguments("-std=c++11"); break; case CppSharp.Parser.LanguageVersion.CPP11_GNU: AddArguments("-std=gnu++11"); break; case CppSharp.Parser.LanguageVersion.CPP14: AddArguments("-std=c++14"); break; case CppSharp.Parser.LanguageVersion.CPP14_GNU: AddArguments("-std=gnu++14"); break; case CppSharp.Parser.LanguageVersion.CPP17: AddArguments("-std=c++1z"); break; case CppSharp.Parser.LanguageVersion.CPP17_GNU: AddArguments("-std=gnu++1z"); break; } if (!EnableRTTI) AddArguments("-fno-rtti"); } private void SetupIncludes() { switch(Platform.Host) { case TargetPlatform.Windows: SetupMSVC(); break; case TargetPlatform.MacOS: SetupXcode(); break; } } } }