mirror of https://github.com/mono/CppSharp.git
c-sharpdotnetmonobindingsbridgecclangcpluspluscppsharpglueinteropparserparsingpinvokeswigsyntax-treevisitorsxamarinxamarin-bindings
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
235 lines
7.4 KiB
235 lines
7.4 KiB
using CppSharp.AST; |
|
using CppSharp.Generators; |
|
using CppSharp.Parser; |
|
using CppSharp.Passes; |
|
using System; |
|
using System.Collections.Generic; |
|
using System.IO; |
|
using System.Linq; |
|
using System.Text; |
|
using CppAbi = CppSharp.Parser.AST.CppAbi; |
|
|
|
namespace CppSharp |
|
{ |
|
class Generator : ILibrary |
|
{ |
|
private Options options = null; |
|
private string triple = ""; |
|
private CppAbi abi = CppAbi.Microsoft; |
|
|
|
public Generator(Options options) |
|
{ |
|
if (options == null) |
|
throw new ArgumentNullException(nameof(options)); |
|
|
|
this.options = options; |
|
} |
|
|
|
static TargetPlatform GetCurrentPlatform() |
|
{ |
|
if (Platform.IsWindows) |
|
return TargetPlatform.Windows; |
|
|
|
if (Platform.IsMacOS) |
|
return TargetPlatform.MacOS; |
|
|
|
if (Platform.IsLinux) |
|
return TargetPlatform.Linux; |
|
|
|
throw new System.NotImplementedException("Unknown host platform"); |
|
} |
|
|
|
void SetupTargetTriple() |
|
{ |
|
var tripleBuilder = new StringBuilder(); |
|
|
|
if (options.Architecture == TargetArchitecture.x64) |
|
tripleBuilder.Append("x86_64-"); |
|
else if(options.Architecture == TargetArchitecture.x86) |
|
tripleBuilder.Append("i686-"); |
|
|
|
if (options.Platform == TargetPlatform.Windows) |
|
{ |
|
tripleBuilder.Append("pc-win32-msvc"); |
|
abi = CppAbi.Microsoft; |
|
} |
|
else if (options.Platform == TargetPlatform.MacOS) |
|
{ |
|
tripleBuilder.Append("apple-darwin12.4.0"); |
|
abi = CppAbi.Itanium; |
|
} |
|
else if (options.Platform == TargetPlatform.Linux) |
|
{ |
|
tripleBuilder.Append("linux-gnu"); |
|
abi = CppAbi.Itanium; |
|
|
|
if(options.Cpp11ABI) |
|
tripleBuilder.Append("-cxx11abi"); |
|
} |
|
|
|
triple = tripleBuilder.ToString(); |
|
} |
|
|
|
public bool ValidateOptions(List<string> messages) |
|
{ |
|
if (options.HeaderFiles.Count == 0) |
|
{ |
|
messages.Add("No source header file has been given to generate bindings from."); |
|
return false; |
|
} |
|
|
|
if (!options.Platform.HasValue) |
|
options.Platform = GetCurrentPlatform(); |
|
|
|
if (string.IsNullOrEmpty(options.OutputDir)) |
|
{ |
|
options.OutputDir = Path.Combine(Directory.GetCurrentDirectory(), "gen"); |
|
} |
|
|
|
string moduleName; |
|
if (options.HeaderFiles.Count == 1) |
|
{ |
|
moduleName = Path.GetFileNameWithoutExtension(options.HeaderFiles.First()); |
|
} |
|
else |
|
{ |
|
var dir = Path.GetDirectoryName(options.HeaderFiles.First()); |
|
moduleName = new DirectoryInfo(dir).Name; |
|
} |
|
|
|
if (string.IsNullOrEmpty(options.OutputFileName)) |
|
options.OutputFileName = moduleName; |
|
|
|
if (string.IsNullOrEmpty(options.OutputNamespace)) |
|
options.OutputNamespace = moduleName; |
|
|
|
SetupTargetTriple(); |
|
|
|
return true; |
|
} |
|
|
|
public void Setup(Driver driver) |
|
{ |
|
var parserOptions = driver.ParserOptions; |
|
parserOptions.TargetTriple = triple; |
|
parserOptions.Verbose = options.Verbose; |
|
|
|
var driverOptions = driver.Options; |
|
driverOptions.GeneratorKind = options.Kind; |
|
var module = driverOptions.AddModule(options.OutputFileName); |
|
|
|
if(!string.IsNullOrEmpty(options.InputLibraryName)) |
|
module.SharedLibraryName = options.InputLibraryName; |
|
|
|
module.Headers.AddRange(options.HeaderFiles); |
|
module.Libraries.AddRange(options.Libraries); |
|
module.IncludeDirs.AddRange(options.IncludeDirs); |
|
module.OutputNamespace = options.OutputNamespace; |
|
|
|
if (abi == CppAbi.Microsoft) |
|
parserOptions.MicrosoftMode = true; |
|
|
|
parserOptions.UnityBuild = options.UnityBuild; |
|
parserOptions.EnableRTTI = options.EnableRTTI; |
|
|
|
parserOptions.Setup(); |
|
|
|
if (triple.Contains("linux")) |
|
SetupLinuxOptions(parserOptions); |
|
|
|
foreach (string s in options.Arguments) |
|
parserOptions.AddArguments(s); |
|
|
|
foreach (KeyValuePair<string, string> d in options.Defines) |
|
{ |
|
if(string.IsNullOrEmpty(d.Value)) |
|
parserOptions.AddDefines(d.Key); |
|
else |
|
parserOptions.AddDefines(d.Key + "=" + d.Value); |
|
} |
|
|
|
if (options.EnableExceptions) |
|
parserOptions.AddArguments("-fcxx-exceptions"); |
|
|
|
driverOptions.GenerateDebugOutput = options.Debug; |
|
driverOptions.CompileCode = options.Compile; |
|
driverOptions.OutputDir = options.OutputDir; |
|
driverOptions.CheckSymbols = options.CheckSymbols; |
|
driverOptions.Verbose = options.Verbose; |
|
|
|
if (!string.IsNullOrEmpty(options.Prefix)) |
|
driverOptions.GenerateName = name => |
|
options.Prefix + name.FileNameWithoutExtension; |
|
} |
|
|
|
private void SetupLinuxOptions(ParserOptions parserOptions) |
|
{ |
|
parserOptions.SetupLinux(); |
|
parserOptions.AddDefines("_GLIBCXX_USE_CXX11_ABI=" + (options.Cpp11ABI ? "1" : "0")); |
|
} |
|
|
|
public void SetupPasses(Driver driver) |
|
{ |
|
driver.Context.TranslationUnitPasses.AddPass(new FunctionToInstanceMethodPass()); |
|
driver.Context.TranslationUnitPasses.AddPass(new MarshalPrimitivePointersAsRefTypePass()); |
|
} |
|
|
|
public void GenerateCode(Driver driver, List<GeneratorOutput> outputs) |
|
{ |
|
} |
|
|
|
public void Preprocess(Driver driver, ASTContext ctx) |
|
{ |
|
} |
|
|
|
public void Postprocess(Driver driver, ASTContext ctx) |
|
{ |
|
} |
|
|
|
public void Run() |
|
{ |
|
StringBuilder messageBuilder = new StringBuilder(); |
|
messageBuilder.Append($"Generating {GetGeneratorKindName(options.Kind)}"); |
|
messageBuilder.Append($" bindings for {GetPlatformName(options.Platform)} {options.Architecture}"); |
|
|
|
if (options.Cpp11ABI) |
|
messageBuilder.Append(" (GCC C++11 ABI)"); |
|
|
|
messageBuilder.Append("..."); |
|
Console.WriteLine(messageBuilder.ToString()); |
|
|
|
ConsoleDriver.Run(this); |
|
|
|
Console.WriteLine(); |
|
} |
|
|
|
private static string GetPlatformName(TargetPlatform? platform) |
|
{ |
|
if (!platform.HasValue) |
|
return string.Empty; |
|
|
|
switch (platform.Value) |
|
{ |
|
case TargetPlatform.MacOS: |
|
return "macOS"; |
|
default: |
|
return platform.ToString(); |
|
} |
|
} |
|
|
|
private static string GetGeneratorKindName(GeneratorKind kind) |
|
{ |
|
switch (kind) |
|
{ |
|
case GeneratorKind.CLI: |
|
return "C++/CLI"; |
|
case GeneratorKind.CSharp: |
|
return "C#"; |
|
case GeneratorKind.NAPI: |
|
return "N-API"; |
|
default: |
|
return kind.ToString(); |
|
} |
|
} |
|
} |
|
}
|
|
|