diff --git a/src/CLI/Generator.cs b/src/CLI/Generator.cs index af07d7cb..dff7de51 100644 --- a/src/CLI/Generator.cs +++ b/src/CLI/Generator.cs @@ -4,9 +4,11 @@ using CppSharp.Parser; using CppSharp.Passes; using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Linq; using System.Text; +using System.Text.RegularExpressions; using CppAbi = CppSharp.Parser.AST.CppAbi; namespace CppSharp @@ -193,34 +195,7 @@ namespace CppSharp private void SetupLinuxOptions(ParserOptions parserOptions) { - parserOptions.MicrosoftMode = false; - parserOptions.NoBuiltinIncludes = true; - - var headersPath = string.Empty; - - // Search for the available GCC versions on the provided headers. - var versions = Directory.EnumerateDirectories(Path.Combine(headersPath, "usr/include/c++")); - - if (versions.Count() == 0) - throw new Exception("No valid GCC version found on system include paths"); - - string gccVersionPath = versions.First(); - string gccVersion = gccVersionPath.Substring(gccVersionPath.LastIndexOf(Path.DirectorySeparatorChar) + 1); - - string[] systemIncludeDirs = { - Path.Combine("usr", "include", "c++", gccVersion), - Path.Combine("usr", "include", "x86_64-linux-gnu", "c++", gccVersion), - Path.Combine("usr", "include", "c++", gccVersion, "backward"), - Path.Combine("usr", "lib", "gcc", "x86_64-linux-gnu", gccVersion, "include"), - Path.Combine("usr", "lib", "gcc", "x86_64-pc-linux-gnu", gccVersion, "include"), - Path.Combine("usr", "include", "x86_64-linux-gnu"), - Path.Combine("usr", "include", "x86_64-pc-linux-gnu"), - Path.Combine("usr", "include") - }; - - foreach (var dir in systemIncludeDirs) - parserOptions.AddSystemIncludeDirs(Path.Combine(headersPath, dir)); - + parserOptions.SetupLinux(); parserOptions.AddDefines("_GLIBCXX_USE_CXX11_ABI=" + (options.Cpp11ABI ? "1" : "0")); } diff --git a/src/CppParser/ParserGen/ParserGen.cs b/src/CppParser/ParserGen/ParserGen.cs index 2b16cba8..8a2f6cfd 100644 --- a/src/CppParser/ParserGen/ParserGen.cs +++ b/src/CppParser/ParserGen/ParserGen.cs @@ -98,32 +98,7 @@ namespace CppSharp var headersPath = Platform.IsLinux ? string.Empty : Path.Combine(GetSourceDirectory("build"), "headers", "x86_64-linux-gnu"); - - // Search for the available GCC versions on the provided headers. - var versions = Directory.EnumerateDirectories(Path.Combine(headersPath, - "usr/include/c++")); - - if (versions.Count() == 0) - throw new Exception("No valid GCC version found on system include paths"); - - string gccVersionPath = versions.First(); - string gccVersion = gccVersionPath.Substring( - gccVersionPath.LastIndexOf(Path.DirectorySeparatorChar) + 1); - - string[] systemIncludeDirs = { - Path.Combine("usr", "include", "c++", gccVersion), - Path.Combine("usr", "include", "x86_64-linux-gnu", "c++", gccVersion), - Path.Combine("usr", "include", "c++", gccVersion, "backward"), - Path.Combine("usr", "lib", "gcc", "x86_64-linux-gnu", gccVersion, "include"), - Path.Combine("usr", "lib", "gcc", "x86_64-pc-linux-gnu", gccVersion, "include"), - Path.Combine("usr", "include", "x86_64-linux-gnu"), - Path.Combine("usr", "include", "x86_64-pc-linux-gnu"), - Path.Combine("usr", "include") - }; - - foreach (var dir in systemIncludeDirs) - options.AddSystemIncludeDirs(Path.Combine(headersPath, dir)); - + options.SetupLinux(headersPath); options.AddDefines("_GLIBCXX_USE_CXX11_ABI=" + (IsGnuCpp11Abi ? "1" : "0")); } @@ -237,4 +212,4 @@ namespace CppSharp } } } -} \ No newline at end of file +} diff --git a/src/Parser/ParserOptions.cs b/src/Parser/ParserOptions.cs index fb0110cb..7b500225 100644 --- a/src/Parser/ParserOptions.cs +++ b/src/Parser/ParserOptions.cs @@ -1,9 +1,12 @@ -using CppSharp.Parser.AST; +using System; +using CppSharp.Parser.AST; using System.Reflection; using LanguageVersion = CppSharp.Parser.LanguageVersion; using System.Globalization; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; +using System.Text.RegularExpressions; namespace CppSharp.Parser { @@ -218,6 +221,53 @@ namespace CppSharp.Parser AddArguments("-stdlib=libc++"); } + private void GetUnixCompilerInfo(out string compiler, out string version) + { + var info = new ProcessStartInfo(Environment.GetEnvironmentVariable("CXX") ?? "gcc", "-v"); + info.RedirectStandardError = true; + info.CreateNoWindow = true; + info.UseShellExecute = false; + var process = Process.Start(info); + if (process == null) + throw new SystemException("GCC compiler was not found."); + process.WaitForExit(); + + var output = process.StandardError.ReadToEnd(); + var match = Regex.Match(output, "(gcc|clang) version ([0-9\\.]+)"); + if (!match.Success) + throw new SystemException("GCC compiler was not found."); + + compiler = match.Groups[1].ToString(); + version = match.Groups[2].ToString(); + } + + public void SetupLinux(string headersPath="") + { + MicrosoftMode = false; + NoBuiltinIncludes = true; + NoStandardIncludes = true; + Abi = CppAbi.Itanium; + + string compiler, version; + GetUnixCompilerInfo(out compiler, out version); + Console.WriteLine($"Compiler version: {compiler}/{version}"); + AddSystemIncludeDirs($"{headersPath}/usr/include"); + if (compiler == "gcc") + { + AddSystemIncludeDirs($"{headersPath}/usr/include/c++/{version}"); + AddSystemIncludeDirs($"{headersPath}/usr/include/x86_64-linux-gnu/c++/{version}"); + AddSystemIncludeDirs($"{headersPath}/usr/include/c++/{version}/backward"); + } + string[] tripples = {"x86_64-linux-gnu", "x86_64-pc-linux-gnu"}; + foreach (var tripple in tripples) + { + AddSystemIncludeDirs($"{headersPath}/usr/lib/{compiler}/{tripple}/{version}/include"); + AddSystemIncludeDirs($"{headersPath}/usr/lib/{compiler}/{tripple}/{version}/include/c++"); + AddSystemIncludeDirs($"{headersPath}/usr/lib/{compiler}/{tripple}/{version}/include/c++/{tripple}"); + AddSystemIncludeDirs($"{headersPath}/usr/include/{tripple}"); + } + } + public void Setup() { SetupArguments(); @@ -291,6 +341,9 @@ namespace CppSharp.Parser case TargetPlatform.MacOS: SetupXcode(); break; + case TargetPlatform.Linux: + SetupLinux(); + break; } } }