Browse Source

Added CppSharp CLI code from CppSharp.CLI repo

Added CppSharp CLI code from CppSharp.CLI repository to add its
functionalities to CppSharp.
pull/728/head
zillemarco 9 years ago
parent
commit
4e5778dd4d
  1. 176
      src/CLI/CLI.cs
  2. 259
      src/CLI/Generator.cs
  3. 77
      src/CLI/Options.cs

176
src/CLI/CLI.cs

@ -0,0 +1,176 @@ @@ -0,0 +1,176 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Policy;
using System.Text;
using System.Threading.Tasks;
namespace CppSharp
{
class CLI
{
private static Options _options = new Options();
private static List<string> _assemblies;
static void AddIncludeDirs(String dir)
{
_options.IncludeDirs.Add(dir);
}
static void ParseCommandLineArgs(string[] args)
{
var showHelp = args.Length == 0;
var optionSet = new Mono.Options.OptionSet()
{
{ "h|header=", "the path to an header file to generate source from", h => _options.HeaderFiles.Add(h) },
{ "pa|path=", "the path of a folder whose files will generate code (can append a filter at the end like '<path>/*.hpp'", pa => { GetFilesFromPath(pa); } },
{ "inc|includedir=", "the path of a folder to search for include files", i => { AddIncludeDirs(i); } },
{ "l|library=", "the path of a library that includes the definitions for the generated source code", l => _options.Libraries.Add(l) },
{ "ld|librarydir=", "the path of a folder to search for additional libraries", l => _options.LibraryDirs.Add(l) },
{ "d|define=", "a define to add for the parse of the given header files", d => _options.Defines.Add(d) },
{ "od|outputdir=", "the path for the destination folder that will contain the generated code", od => _options.OutputDir = od },
{ "on|outputnamespace=", "the namespace that will be used for the generated code", on => _options.OutputNamespace = on },
{ "iln|inputlibraryname=", "the name of the shared library that contains the actual definitions (without extension)", iln => _options.InputLibraryName = iln },
{ "isln|inputsharedlibraryname=", "the full name of the shared library that contains the actual definitions (with extension)", isln => _options.InputSharedLibraryName = isln },
{ "gen|generator=", "the type of generated code: 'chsarp' or 'cli' ('cli' supported only for Windows)", g => { GetGeneratorKind(g); } },
{ "p|platform=", "the platform that the generated code will target: 'win', 'osx', 'linux'", p => { GetDestinationPlatform(p); } },
{ "a|arch=", "the architecture that the generated code will target: 'x86', 'x64'", a => { GetDestinationArchitecture(a); } },
{ "c++11", "enables GCC C++ 11 compilation (valid only for Linux platform)", cpp11 => { _options.Cpp11ABI = (cpp11 != null); } },
{ "cs|checksymbols", "enable the symbol check for the generated code", cs => { _options.CheckSymbols = (cs != null); } },
{ "ub|unitybuild", "enable unity build", ub => { _options.UnityBuild = (ub != null); } },
{ "help", "shows the help", hl => { showHelp = (hl != null); } }
};
try
{
_assemblies = optionSet.Parse(args);
}
catch (Mono.Options.OptionException e)
{
Console.WriteLine(e.Message);
Environment.Exit(0);
}
if (showHelp)
{
// Print usage and exit.
Console.WriteLine("{0} [options]+", AppDomain.CurrentDomain.FriendlyName);
Console.WriteLine("Generates target language bindings for interop with unmanaged code.");
Console.WriteLine();
optionSet.WriteOptionDescriptions(Console.Out);
Environment.Exit(0);
}
if (_assemblies == null)
{
Console.WriteLine("Invalid arguments.");
Environment.Exit(0);
}
}
static void GetFilesFromPath(String path)
{
path = path.Replace(System.IO.Path.DirectorySeparatorChar, System.IO.Path.AltDirectorySeparatorChar);
String searchPattern = String.Empty;
int lastSeparatorPosition = path.LastIndexOf(System.IO.Path.AltDirectorySeparatorChar);
if (lastSeparatorPosition >= 0)
{
if (path.IndexOf('*', lastSeparatorPosition) >= lastSeparatorPosition || path.IndexOf('?', lastSeparatorPosition) >= lastSeparatorPosition)
{
searchPattern = path.Substring(lastSeparatorPosition + 1);
path = path.Substring(0, lastSeparatorPosition);
}
}
try
{
if (searchPattern != String.Empty)
{
String[] files = System.IO.Directory.GetFiles(path, searchPattern);
foreach (String s in files)
_options.HeaderFiles.Add(s);
}
else
{
String[] files = System.IO.Directory.GetFiles(path);
foreach (String s in files)
_options.HeaderFiles.Add(s);
}
}
catch (Exception ex)
{
Console.WriteLine("Source files path error: " + ex.Message);
Environment.Exit(0);
}
}
static void GetGeneratorKind(String generator)
{
switch (generator.ToLower())
{
case "csharp":
_options.Kind = CppSharp.Generators.GeneratorKind.CSharp;
break;
case "cli":
_options.Kind = CppSharp.Generators.GeneratorKind.CLI;
break;
}
throw new NotSupportedException("Unknown generator kind: " + generator);
}
static void GetDestinationPlatform(String platform)
{
switch (platform.ToLower())
{
case "win":
_options.Platform = TargetPlatform.Windows;
break;
case "osx":
_options.Platform = TargetPlatform.MacOS;
break;
case "linux":
_options.Platform = TargetPlatform.Linux;
break;
}
throw new NotSupportedException("Unknown target platform: " + platform);
}
static void GetDestinationArchitecture(String architecture)
{
switch (architecture.ToLower())
{
case "x86":
_options.Architecture = TargetArchitecture.x86;
break;
case "x64":
_options.Architecture = TargetArchitecture.x64;
break;
}
throw new NotSupportedException("Unknown target architecture: " + architecture);
}
static void Main(string[] args)
{
ParseCommandLineArgs(args);
Generator gen = new Generator(_options);
try
{
gen.Run();
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex.ToString());
}
}
}
}

259
src/CLI/Generator.cs

@ -0,0 +1,259 @@ @@ -0,0 +1,259 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using CppSharp.AST;
using CppSharp.Generators;
using CppSharp.Passes;
using CppSharp.Types;
using CppAbi = CppSharp.Parser.AST.CppAbi;
using CppSharp.Parser;
using CppSharp;
namespace CppSharp
{
class Generator : ILibrary
{
private Options _options;
private String _triple = "";
private CppAbi _abi = CppAbi.Microsoft;
public Generator(Options options)
{
if (options == null)
throw new ArgumentNullException("options");
_options = options;
}
public void ValidateOptions()
{
if (Platform.IsWindows && _options.Platform != TargetPlatform.Windows)
throw new NotSupportedException("Cannot create bindings for a platform other that Windows from a Windows running machine");
else if (Platform.IsMacOS && _options.Platform != TargetPlatform.MacOS)
throw new NotSupportedException("Cannot create bindings for a platform other that MacOS from a MacOS running machine");
else if (Platform.IsUnixPlatform && _options.Platform != TargetPlatform.Linux)
throw new NotSupportedException("Cannot create bindings for a platform other that Linux from a Linux running machine");
if(_options.Platform != TargetPlatform.Windows && _options.Kind != GeneratorKind.CSharp)
throw new NotSupportedException("Cannot create bindings for languages other than C# from a non Windows machine");
if(_options.Platform == TargetPlatform.Linux && _options.Architecture != TargetArchitecture.x64)
throw new NotSupportedException("Cannot create bindings for architectures other than x64 for Linux machines");
if(_options.HeaderFiles.Count == 0)
throw new NotSupportedException("No source header file has been given");
if (_options.OutputNamespace == String.Empty)
throw new NotSupportedException("Output namespace is empty");
if (_options.InputLibraryName == String.Empty)
throw new NotSupportedException("Input library name is empty");
if (_options.Architecture == TargetArchitecture.x64)
_triple = "x86_64-";
else if(_options.Architecture == TargetArchitecture.x86)
_triple = "i686-";
if (_options.Platform == TargetPlatform.Windows)
{
_triple += "pc-win32-msvc";
_abi = CppAbi.Microsoft;
}
else if (_options.Platform == TargetPlatform.MacOS)
{
_triple += "apple-darwin12.4.0";
_abi = CppAbi.Itanium;
}
else if (_options.Platform == TargetPlatform.Linux)
{
_triple += "linux-gnu";
_abi = CppAbi.Itanium;
if(_options.Cpp11ABI)
_triple += "-cxx11abi";
}
}
public void Setup(Driver driver)
{
var parserOptions = driver.ParserOptions;
parserOptions.TargetTriple = _triple;
parserOptions.Abi = _abi;
var options = driver.Options;
options.LibraryName = _options.InputLibraryName;
if(_options.InputSharedLibraryName != String.Empty)
options.SharedLibraryName = _options.InputSharedLibraryName;
options.GeneratorKind = _options.Kind;
options.Headers.AddRange(_options.HeaderFiles);
options.Libraries.AddRange(_options.Libraries);
if (_abi == CppAbi.Microsoft)
parserOptions.MicrosoftMode = true;
if (_triple.Contains("apple"))
SetupMacOptions(parserOptions);
if (_triple.Contains("linux"))
SetupLinuxOptions(parserOptions);
Console.WriteLine("\n\nAdding " + (_options.IncludeDirs.Count) + " include dirs\n\n");
foreach (String s in _options.IncludeDirs)
{
parserOptions.AddIncludeDirs(s);
Console.WriteLine("Add include: " + s);
}
foreach (String s in _options.LibraryDirs)
parserOptions.AddLibraryDirs(s);
foreach (String s in _options.Defines)
parserOptions.AddDefines(s);
options.OutputDir = _options.OutputDir;
options.OutputNamespace = _options.OutputNamespace;
options.CheckSymbols = _options.CheckSymbols;
options.UnityBuild = _options.UnityBuild;
}
private void SetupLinuxOptions(ParserOptions options)
{
options.MicrosoftMode = false;
options.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", "include", "x86_64-linux-gnu"),
Path.Combine("usr", "include")
};
foreach (var dir in systemIncludeDirs)
options.AddSystemIncludeDirs(Path.Combine(headersPath, dir));
options.AddDefines("_GLIBCXX_USE_CXX11_ABI=" + (_options.Cpp11ABI ? "1" : "0"));
}
private static void SetupMacOptions(ParserOptions options)
{
options.MicrosoftMode = false;
options.NoBuiltinIncludes = true;
if (Platform.IsMacOS)
{
var headersPaths = new List<string> {
// Path.Combine(GetSourceDirectory("deps"), "llvm/tools/clang/lib/Headers"),
// Path.Combine(GetSourceDirectory("deps"), "libcxx", "include"),
"/usr/include"
};
foreach (var header in headersPaths)
Console.WriteLine(header);
foreach (var header in headersPaths)
options.AddSystemIncludeDirs(header);
}
// var headersPath = Path.Combine(GetSourceDirectory("build"), "headers", "osx");
// options.AddSystemIncludeDirs(Path.Combine(headersPath, "include"));
// options.AddSystemIncludeDirs(Path.Combine(headersPath, "clang", "4.2", "include"));
// options.AddSystemIncludeDirs(Path.Combine(headersPath, "libcxx", "include"));
options.AddArguments("-stdlib=libc++");
}
public void SetupPasses(Driver driver)
{
driver.AddTranslationUnitPass(new CheckMacroPass());
driver.Context.TranslationUnitPasses.RenameDeclsUpperCase(RenameTargets.Any);
driver.Context.TranslationUnitPasses.AddPass(new FunctionToInstanceMethodPass());
driver.Context.TranslationUnitPasses.AddPass(new MarshalPrimitivePointersAsRefTypePass());
}
public void Preprocess(Driver driver, ASTContext ctx)
{
}
public void Postprocess(Driver driver, ASTContext ctx)
{
new CaseRenamePass(
RenameTargets.Function | RenameTargets.Method | RenameTargets.Property | RenameTargets.Delegate |
RenameTargets.Field | RenameTargets.Variable,
RenameCasePattern.UpperCamelCase).VisitASTContext(driver.Context.ASTContext);
}
public void Run()
{
ValidateOptions();
String message = "Generating the ";
switch(_options.Kind)
{
case GeneratorKind.CLI:
message += "C++/CLI";
break;
case GeneratorKind.CSharp:
message += "C#";
break;
}
message += " parser bindings for ";
switch (_options.Platform)
{
case TargetPlatform.Linux:
message += "Linux";
break;
case TargetPlatform.MacOS:
message += "OSX";
break;
case TargetPlatform.Windows:
message += "Windows";
break;
}
message += " ";
switch (_options.Architecture)
{
case TargetArchitecture.x86:
message += "x86";
break;
case TargetArchitecture.x64:
message += "x64";
break;
}
if(_options.Cpp11ABI)
message += " (GCC C++11 ABI)";
message += "...";
Console.WriteLine(message);
ConsoleDriver.Run(this);
Console.WriteLine();
}
}
}

77
src/CLI/Options.cs

@ -0,0 +1,77 @@ @@ -0,0 +1,77 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CppSharp.Generators;
namespace CppSharp
{
enum TargetPlatform
{
Windows,
MacOS,
Linux
}
enum TargetArchitecture
{
x86,
x64
}
class Options
{
private List<String> _headerFiles = new List<string>();
public List<String> HeaderFiles { get { return _headerFiles; } set { _headerFiles = value; } }
private List<String> _includeDirs = new List<string>();
public List<String> IncludeDirs { get { return _includeDirs; } set { _includeDirs = value; } }
private List<String> _libraryDirs = new List<string>();
public List<String> LibraryDirs { get { return _libraryDirs; } set { _libraryDirs = value; } }
private List<String> _libraries = new List<string>();
public List<String> Libraries { get { return _libraries; } set { _libraries = value; } }
private List<String> _defines = new List<string>();
public List<String> Defines { get { return _defines; } set { _defines = value; } }
private String _outputDir = "";
public String OutputDir { get { return _outputDir; } set { _outputDir = value; } }
private String _outputNamespace = "";
public String OutputNamespace { get { return _outputNamespace; } set { _outputNamespace = value; } }
private String _inputLibraryName = "";
public String InputLibraryName { get { return _inputLibraryName; } set { _inputLibraryName = value; } }
private String _inputSharedLibraryName = "";
public String InputSharedLibraryName { get { return _inputSharedLibraryName; } set { _inputSharedLibraryName = value; } }
private String _triple = "";
public String Triple { get { return _triple; } set { _triple = value; } }
private TargetPlatform _platform = TargetPlatform.Windows;
public TargetPlatform Platform { get { return _platform; } set { _platform = value; } }
private TargetArchitecture _architecture = TargetArchitecture.x86;
public TargetArchitecture Architecture { get { return _architecture; } set { _architecture = value; } }
private GeneratorKind _kind = GeneratorKind.CSharp;
public GeneratorKind Kind { get { return _kind; } set { _kind = value; } }
//private bool _verbose = false;
//public bool Verbose { get { return _verbose; } set { _verbose = value; } }
private bool _checkSymbols = false;
public bool CheckSymbols { get { return _checkSymbols; } set { _checkSymbols = value; } }
private bool _unityBuild = false;
public bool UnityBuild { get { return _unityBuild; } set { _unityBuild = value; } }
private bool _cpp11ABI = false;
public bool Cpp11ABI { get { return _cpp11ABI; } set { _cpp11ABI = value; } }
}
}
Loading…
Cancel
Save