diff options
author | Bernhard Urban <lewurm@gmail.com> | 2019-07-26 15:15:50 +0300 |
---|---|---|
committer | monojenkins <jo.shields+jenkins@xamarin.com> | 2019-07-26 15:15:50 +0300 |
commit | b4c5d68c2852272b393d71e49e4cb30106b1ac79 (patch) | |
tree | 73c39f07e036b4c67a8bfed4e8ca405162e67862 /tools | |
parent | ddb1f31c9e09ee921b30661fd097b3f229a041ad (diff) |
[android] switch to python offset tool (#15834)
[android] switch to python offset tool
And drop C# tool.
Fixes https://github.com/mono/mono/issues/9621
Diffstat (limited to 'tools')
-rw-r--r-- | tools/offsets-tool-py/offsets-tool.py | 39 | ||||
-rw-r--r-- | tools/offsets-tool/.gitignore | 5 | ||||
-rw-r--r-- | tools/offsets-tool/Makefile | 65 | ||||
-rw-r--r-- | tools/offsets-tool/MonoAotOffsetsDumper.cs | 963 |
4 files changed, 33 insertions, 1039 deletions
diff --git a/tools/offsets-tool-py/offsets-tool.py b/tools/offsets-tool-py/offsets-tool.py index 64fdaf92b64..c7cbc57e07f 100644 --- a/tools/offsets-tool-py/offsets-tool.py +++ b/tools/offsets-tool-py/offsets-tool.py @@ -7,6 +7,7 @@ import argparse import clang.cindex IOS_DEFINES = ["HOST_DARWIN", "TARGET_MACH", "MONO_CROSS_COMPILE", "USE_MONO_CTX", "_XOPEN_SOURCE"] +ANDROID_DEFINES = ["HOST_ANDROID", "MONO_CROSS_COMPILE", "USE_MONO_CTX", "BIONIC_IOCTL_NO_SIGNEDNESS_OVERLOAD"] class Target: def __init__(self, arch, platform, others): @@ -52,7 +53,7 @@ class OffsetsTool: sys.exit (1) parser = argparse.ArgumentParser () - parser.add_argument ('--libclang-path', dest='libclang_path', help='path to directory where libclang.{so,dylib} lives') + parser.add_argument ('--libclang', dest='libclang', help='path to shared library of libclang.{so,dylib}') parser.add_argument ('--emscripten-sdk', dest='emscripten_path', help='path to emscripten sdk') parser.add_argument ('--outfile', dest='outfile', help='path to output file', required=True) parser.add_argument ('--monodir', dest='mono_path', help='path to mono source tree', required=True) @@ -61,8 +62,8 @@ class OffsetsTool: parser.add_argument ('--sysroot=', dest='sysroot', help='path to sysroot headers of target') args = parser.parse_args () - if not args.libclang_path or not os.path.isdir (args.libclang_path): - print ("Libclang path '" + args.libclang_path + "' doesn't exist.", file=sys.stderr) + if not args.libclang or not os.path.isfile (args.libclang): + print ("Libclang '" + args.libclang + "' doesn't exist.", file=sys.stderr) sys.exit (1) if not os.path.isdir (args.mono_path): print ("Mono directory '" + args.mono_path + "' doesn't exist.", file=sys.stderr) @@ -74,6 +75,7 @@ class OffsetsTool: self.sys_includes=[] self.target = None self.target_args = [] + android_api_level = "-D__ANDROID_API=21" if "wasm" in args.abi: require_emscipten_path (args) @@ -81,30 +83,55 @@ class OffsetsTool: self.target = Target ("TARGET_WASM", None, []) self.target_args += ["-target", args.abi] + # iOS elif "arm-apple-darwin10" == args.abi: require_sysroot (args) self.target = Target ("TARGET_ARM", "TARGET_IOS", ["ARM_FPU_VFP", "HAVE_ARMV5"] + IOS_DEFINES) self.target_args += ["-arch", "arm"] self.target_args += ["-isysroot", args.sysroot] - elif "aarch64-apple-darwin10" == args.abi: require_sysroot (args) self.target = Target ("TARGET_ARM64", "TARGET_IOS", IOS_DEFINES) self.target_args += ["-arch", "arm64"] self.target_args += ["-isysroot", args.sysroot] + # watchOS elif "armv7k-apple-darwin" == args.abi: require_sysroot (args) self.target = Target ("TARGET_ARM", "TARGET_WATCHOS", ["ARM_FPU_VFP", "HAVE_ARMV5"] + IOS_DEFINES) self.target_args += ["-arch", "armv7k"] self.target_args += ["-isysroot", args.sysroot] - elif "aarch64-apple-darwin10_ilp32" == args.abi: require_sysroot (args) self.target = Target ("TARGET_ARM64", "TARGET_WATCHOS", ["MONO_ARCH_ILP32"] + IOS_DEFINES) self.target_args += ["-arch", "arm64_32"] self.target_args += ["-isysroot", args.sysroot] + # Android + elif "i686-none-linux-android" == args.abi: + require_sysroot (args) + self.target = Target ("TARGET_X86", "TARGET_ANDROID", ANDROID_DEFINES) + self.target_args += ["--target=i386---android"] + self.target_args += ["-I", args.sysroot + "/usr/include/i686-linux-android"] + elif "x86_64-none-linux-android" == args.abi: + require_sysroot (args) + self.target = Target ("TARGET_AMD64", "TARGET_ANDROID", ANDROID_DEFINES) + self.target_args += ["--target=x86_64---android"] + self.target_args += ["-I", args.sysroot + "/usr/include/x86_64-linux-android"] + elif "armv7-none-linux-androideabi" == args.abi: + require_sysroot (args) + self.target = Target ("TARGET_ARM", "TARGET_ANDROID", ["ARM_FPU_VFP", "HAVE_ARMV5", "HAVE_ARMV6", "HAVE_ARMV7"] + ANDROID_DEFINES) + self.target_args += ["--target=arm---androideabi"] + self.target_args += ["-I", args.sysroot + "/usr/include/arm-linux-androideabi"] + elif "aarch64-v8a-linux-android" == args.abi: + require_sysroot (args) + self.target = Target ("TARGET_ARM64", "TARGET_ANDROID", ANDROID_DEFINES) + self.target_args += ["--target=aarch64---android"] + self.target_args += ["-I", args.sysroot + "/usr/include/aarch64-linux-android"] + + if self.target.platform_define == "TARGET_ANDROID": + self.target_args += [android_api_level] + self.target_args += ["-isysroot", args.sysroot] if not self.target: print ("ABI '" + args.abi + "' is not supported.", file=sys.stderr) @@ -189,7 +216,7 @@ class OffsetsTool: for define in self.target.get_clang_args (): clang_args.append ("-D" + define) - clang.cindex.Config.set_library_path (args.libclang_path) + clang.cindex.Config.set_library_file (args.libclang) for srcfile in srcfiles: src = args.mono_path + "/" + srcfile diff --git a/tools/offsets-tool/.gitignore b/tools/offsets-tool/.gitignore deleted file mode 100644 index afc98f0d6b8..00000000000 --- a/tools/offsets-tool/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -.stamp-clone-* -CppSharp -*.exe -*.h -*.exe.mdb diff --git a/tools/offsets-tool/Makefile b/tools/offsets-tool/Makefile deleted file mode 100644 index c974d0364ae..00000000000 --- a/tools/offsets-tool/Makefile +++ /dev/null @@ -1,65 +0,0 @@ -CPPSHARP_BASE_DIR = CppSharp - -ifeq ($(OS),Windows_NT) - CPPSHARP_OS=windows - ifeq ($(PROCESSOR_ARCHITEW6432),AMD64) - CPPSHARP_ARCH=64 - else - ifeq ($(PROCESSOR_ARCHITECTURE),AMD64) - CPPSHARP_ARCH=64 - endif - ifeq ($(PROCESSOR_ARCHITECTURE),x86) - CPPSHARP_ARCH=32 - endif - endif -else - UNAME_S := $(shell uname -s) - ifeq ($(UNAME_S),Linux) - CPPSHARP_OS=linux - CPPSHARP_ARCH=64 - endif - ifeq ($(UNAME_S),Darwin) - CPPSHARP_OS=osx - CPPSHARP_ARCH=64 - endif -endif - -CPPSHARP_DIR = $(CPPSHARP_BASE_DIR)/$(CPPSHARP_OS)_$(CPPSHARP_ARCH) - -CPPSHARP_REFS = -r:$(CPPSHARP_DIR)/CppSharp.dll \ - -r:$(CPPSHARP_DIR)/CppSharp.AST.dll \ - -r:$(CPPSHARP_DIR)/CppSharp.Parser.dll \ - -r:$(CPPSHARP_DIR)/CppSharp.Parser.CSharp.dll \ - -r:$(CPPSHARP_DIR)/CppSharp.Generator.dll - -SRC_ROOT = ../.. - -MONO_OPTIONS_SRC = $(SRC_ROOT)/mcs/class/Mono.Options/Mono.Options/Options.cs - -HASH=9dc880dd -.stamp-clone-$(HASH): - rm -Rf $(CPPSHARP_BASE_DIR) - git clone -b $(HASH) --depth 1 git://github.com/xamarin/CppSharpBinaries.git $(CPPSHARP_BASE_DIR) && touch $@ - -MonoAotOffsetsDumper.exe: .stamp-clone-$(HASH) MonoAotOffsetsDumper.cs $(MONO_OPTIONS_SRC) - mcs MonoAotOffsetsDumper.cs /debug /nowarn:0436 $(MONO_OPTIONS_SRC) $(CPPSHARP_REFS) - -.PHONY: clean -clean: - rm MonoAotOffsetsDumper.exe - -dump: MonoAotOffsetsDumper.exe - MONO_PATH=$(CPPSHARP_DIR) mono MonoAotOffsetsDumper.exe - -update: - @if [ -f object-offsets.h ]; then rm object-offsets.h; fi; - @for f in *.h; do \ - echo "Processing $$f.."; \ - echo "#include \"$$f\"" >> object-offsets1.h; \ - done - @cp *.h ../mono/metadata - -gen-proj: - $(CPPSHARP_DIR)/premake5 vs2012 - -all: MonoAotOffsetsDumper.exe diff --git a/tools/offsets-tool/MonoAotOffsetsDumper.cs b/tools/offsets-tool/MonoAotOffsetsDumper.cs deleted file mode 100644 index e20df920f78..00000000000 --- a/tools/offsets-tool/MonoAotOffsetsDumper.cs +++ /dev/null @@ -1,963 +0,0 @@ -// -*- indent-tabs-mode:nil -*- -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text.RegularExpressions; -using CppSharp.AST; -using CppSharp.AST.Extensions; -using CppSharp.Parser; - -namespace CppSharp -{ - /** - * This tool dumps the offsets of structures used in the Mono VM needed - * by the AOT compiler for cross-compiling code to target platforms - * different than the host the compiler is being invoked on. - */ - static class MonoAotOffsetsDumper - { - static string MonoDir = @""; - - static List<string> Abis = new List<string> (); - static string OutputDir; - static string OutputFile; - - static string AndroidNdkPath = @""; - static string EmscriptenSdkPath = @""; - static string TargetDir = @""; - static bool GenIOS; - static bool GenAndroid; - - public enum TargetPlatform - { - Android, - iOS, - WatchOS, - OSX, - WASM - } - - public class Target - { - public Target() - { - Defines = new List<string>(); - Arguments = new List<string>(); - } - - public Target(Target target) - { - Platform = target.Platform; - Triple = target.Triple; - Build = target.Build; - Defines = target.Defines; - Arguments = target.Arguments; - } - - public TargetPlatform Platform; - public string Triple; - public string Build; - public List<string> Defines; - public List<string> Arguments; - }; - - public static List<Target> Targets = new List<Target>(); - - public static IEnumerable<Target> AndroidTargets - { - get { return Targets.Where ((t) => t.Platform == TargetPlatform.Android); } - } - - public static IEnumerable<Target> DarwinTargets - { - get - { - return Targets.Where ((t) => - t.Platform == TargetPlatform.iOS || - t.Platform == TargetPlatform.WatchOS || - t.Platform == TargetPlatform.OSX); - } - } - - public static IEnumerable<Target> iOSTargets - { - get - { - return Targets.Where ((t) => t.Platform == TargetPlatform.iOS); - } - } - - public static void SetupAndroidTargets() - { - Targets.Add (new Target { - Platform = TargetPlatform.Android, - Triple = "i686-none-linux-android", - Defines = { "TARGET_X86" } - }); - - Targets.Add (new Target { - Platform = TargetPlatform.Android, - Triple = "x86_64-none-linux-android", - Defines = { "TARGET_AMD64" } - }); - - Targets.Add (new Target { - Platform = TargetPlatform.Android, - Triple = "armv5-none-linux-androideabi", - Defines = { "TARGET_ARM", "ARM_FPU_VFP", "HAVE_ARMV5" } - }); - - Targets.Add (new Target { - Platform = TargetPlatform.Android, - Triple = "armv7-none-linux-androideabi", - Defines = { "TARGET_ARM", "ARM_FPU_VFP", "HAVE_ARMV5", "HAVE_ARMV6", - "HAVE_ARMV7" - } - }); - - Targets.Add (new Target { - Platform = TargetPlatform.Android, - Triple = "aarch64-v8a-linux-android", - Defines = { "TARGET_ARM64" } - }); - - /*Targets.Add(new Target { - Platform = TargetPlatform.Android, - Triple = "mipsel-none-linux-android", - Defines = { "TARGET_MIPS", "__mips__" } - });*/ - - foreach (var target in AndroidTargets) - target.Defines.AddRange (new string[] { "HOST_ANDROID", - "TARGET_ANDROID", "MONO_CROSS_COMPILE", "USE_MONO_CTX", - "BIONIC_IOCTL_NO_SIGNEDNESS_OVERLOAD" - }); - } - - public static void SetupiOSTargets() - { - Targets.Add(new Target { - Platform = TargetPlatform.iOS, - Triple = "arm-apple-darwin10", - Build = "target7", - Defines = { "TARGET_ARM", "ARM_FPU_VFP", "HAVE_ARMV5" } - }); - - Targets.Add(new Target { - Platform = TargetPlatform.iOS, - Triple = "aarch64-apple-darwin10", - Build = "target64", - Defines = { "TARGET_ARM64" } - }); - - foreach (var target in iOSTargets) { - target.Defines.AddRange (new string[] { "HOST_DARWIN", - "TARGET_IOS", "TARGET_MACH", "MONO_CROSS_COMPILE", "USE_MONO_CTX", - "_XOPEN_SOURCE" - }); - } - - Targets.Add(new Target { - Platform = TargetPlatform.WatchOS, - Triple = "armv7k-apple-darwin", - Build = "targetwatch", - Defines = { "TARGET_ARM", "ARM_FPU_VFP", "HAVE_ARMV5" } - }); - - Targets.Add(new Target { - Platform = TargetPlatform.WatchOS, - Triple = "armv7k-apple-darwin_ilp32", /* fake triple, aarch64-apple-darwin_ilp32 isn't recognized correctly */ - Build = "targetwatch64_32", - Defines = { "TARGET_ARM64", "MONO_ARCH_ILP32", "MONO_CPPSHARP_HACK" } - }); - - foreach (var target in DarwinTargets) { - target.Defines.AddRange (new string[] { "HOST_DARWIN", - "TARGET_IOS", "TARGET_MACH", "MONO_CROSS_COMPILE", "USE_MONO_CTX", - "_XOPEN_SOURCE" - }); - } - } - - public static void SetupOtherTargets() - { - if (Abis.Count != 1) { - Console.WriteLine ("Exactly --abi= argument is required."); - Environment.Exit (1); - } - string abi = Abis [0]; - if (abi == "i386-apple-darwin13.0.0") { - Targets.Add(new Target { - Platform = TargetPlatform.OSX, - Triple = "i386-apple-darwin13.0.0", - Build = "", - Defines = { "TARGET_X86" }, - }); - } else if (abi == "wasm32-unknown-unknown") { - Targets.Add(new Target { - Platform = TargetPlatform.WASM, - Triple = "wasm32-unknown-unknown", - Build = "", - Defines = { "TARGET_WASM" }, - }); - } else { - Console.WriteLine ($"Unsupported abi: {abi}."); - Environment.Exit (1); - } - } - - static bool GetParentSubDirectoryPath(string parent, out string subdir) - { - var directory = Directory.GetParent(Directory.GetCurrentDirectory()); - - while (directory != null) { - var path = Path.Combine(directory.FullName, parent); - - if (Directory.Exists (path)) { - subdir = path; - return true; - } - - directory = directory.Parent; - } - - subdir = null; - return false; - } - - public static int Main(string[] args) - { - ParseCommandLineArgs(args); - - if (GenAndroid) - SetupAndroidTargets(); - - if (GenIOS) - SetupiOSTargets(); - - if (Targets.Count == 0) - SetupOtherTargets (); - - foreach (var target in Targets) - { - if (Abis.Any() && !Abis.Contains (target.Triple)) - continue; - - Console.WriteLine(); - Console.WriteLine("Processing triple: {0}", target.Triple); - - var options = new DriverOptions(); - - var driver = new Driver(options); - - Setup(driver, target); - driver.Setup(); - - BuildParseOptions(driver, target); - if (!driver.ParseCode()) - return 1; - - Dump(driver.Context.ASTContext, driver.Context.TargetInfo, target); - } - return 0; - } - - static void BuildParseOptions(Driver driver, Target target) - { - foreach (var header in driver.Options.Headers) - { - var source = driver.Project.AddFile(header); - source.Options = driver.BuildParserOptions(source); - - if (header.Contains ("mini")) - continue; - - source.Options.AddDefines ("HAVE_SGEN_GC"); - source.Options.AddDefines ("HAVE_MOVING_COLLECTOR"); - source.Options.AddDefines("MONO_GENERATING_OFFSETS"); - } - } - - static void ParseCommandLineArgs(string[] args) - { - var showHelp = false; - - var options = new Mono.Options.OptionSet () { - { "abi=", "ABI triple to generate", v => Abis.Add(v) }, - { "o|out=", "output directory", v => OutputDir = v }, - { "outfile=", "output directory", v => OutputFile = v }, - { "android-ndk=", "Path to Android NDK", v => AndroidNdkPath = v }, - { "emscripten-sdk=", "Path to emscripten sdk", v => EmscriptenSdkPath = v }, - { "targetdir=", "Path to the directory containing the mono build", v =>TargetDir = v }, - { "mono=", "include directory", v => MonoDir = v }, - { "gen-ios", "generate iOS offsets", v => GenIOS = v != null }, - { "gen-android", "generate Android offsets", v => GenAndroid = v != null }, - { "h|help", "show this message and exit", v => showHelp = v != null }, - }; - - try { - options.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); - options.WriteOptionDescriptions (Console.Out); - Environment.Exit(0); - } - } - - static void Setup(Driver driver, Target target) - { - var options = driver.Options; - options.DryRun = true; - options.LibraryName = "Mono"; - - var parserOptions = driver.ParserOptions; - parserOptions.Verbose = false; - parserOptions.MicrosoftMode = false; - parserOptions.AddArguments("-xc"); - parserOptions.AddArguments("-std=gnu99"); - parserOptions.AddDefines("CPPSHARP"); - parserOptions.AddDefines("MONO_GENERATING_OFFSETS"); - - foreach (var define in target.Defines) - parserOptions.AddDefines(define); - - SetupToolchainPaths(driver, target); - - SetupMono(driver, target); - } - - static void SetupMono(Driver driver, Target target) - { - string targetBuild; - switch (target.Platform) { - case TargetPlatform.Android: - if (string.IsNullOrEmpty (TargetDir)) { - Console.Error.WriteLine ("The --targetdir= option is required when targeting android."); - Environment.Exit (1); - } - if (string.IsNullOrEmpty (MonoDir)) { - Console.Error.WriteLine ("The --mono= option is required when targeting android."); - Environment.Exit (1); - } - if (string.IsNullOrEmpty(AndroidNdkPath)) { - Console.WriteLine("The --android-ndk= option is required when targeting android"); - Environment.Exit (1); - } - if (Abis.Count != 1) { - Console.Error.WriteLine ("Exactly one --abi= argument is required when targeting android."); - Environment.Exit (1); - } - targetBuild = TargetDir; - break; - case TargetPlatform.WatchOS: - case TargetPlatform.iOS: { - if (string.IsNullOrEmpty (TargetDir)) { - Console.Error.WriteLine ("The --targetdir= option is required when targeting ios."); - Environment.Exit (1); - } - if (string.IsNullOrEmpty (MonoDir)) { - Console.Error.WriteLine ("The --mono= option is required when targeting ios."); - Environment.Exit (1); - } - targetBuild = TargetDir; - break; - } - case TargetPlatform.OSX: - case TargetPlatform.WASM: - if (MonoDir == "") { - Console.Error.WriteLine ("The --mono= option is required when targeting osx."); - Environment.Exit (1); - } - if (!string.IsNullOrEmpty (TargetDir)) { - targetBuild = TargetDir; - } else { - targetBuild = "."; - } - break; - default: - throw new ArgumentOutOfRangeException (); - } - - if (!Directory.Exists(targetBuild)) - throw new Exception(string.Format("Could not find the target build directory: {0}", targetBuild)); - - var includeDirs = new[] - { - targetBuild, - Path.Combine(targetBuild, "mono", "eglib"), - MonoDir, - Path.Combine(MonoDir, "mono"), - Path.Combine(MonoDir, "mono", "mini"), - Path.Combine(MonoDir, "mono", "eglib") - }; - - foreach (var inc in includeDirs) - driver.ParserOptions.AddIncludeDirs(inc); - - var filesToParse = new[] - { - Path.Combine(MonoDir, "mono", "metadata", "metadata-cross-helpers.c"), - Path.Combine(MonoDir, "mono", "mini", "mini-cross-helpers.c"), - }; - - foreach (var file in filesToParse) - driver.Options.Headers.Add(file); - } - - static void SetupMSVC(Driver driver, string triple) - { - var parserOptions = driver.ParserOptions; - - parserOptions.Abi = Parser.AST.CppAbi.Microsoft; - parserOptions.MicrosoftMode = true; - - var systemIncludeDirs = new[] - { - @"C:\Program Files (x86)\Windows Kits\8.1\Include\um", - @"C:\Program Files (x86)\Windows Kits\8.1\Include\shared" - }; - - foreach (var inc in systemIncludeDirs) - parserOptions.AddSystemIncludeDirs(inc); - - parserOptions.AddDefines("HOST_WIN32"); - } - - static void SetupToolchainPaths(Driver driver, Target target) - { - switch (target.Platform) { - case TargetPlatform.Android: - SetupAndroidNDK(driver, target); - break; - case TargetPlatform.iOS: - case TargetPlatform.WatchOS: - case TargetPlatform.OSX: - SetupXcode(driver, target); - break; - case TargetPlatform.WASM: - if (EmscriptenSdkPath == "") { - Console.Error.WriteLine ("The --emscripten-sdk= option is required when targeting wasm."); - Environment.Exit (1); - } - string include_dir = Path.Combine (EmscriptenSdkPath, "system", "include", "libc"); - if (!Directory.Exists (include_dir)) { - Console.Error.WriteLine ($"emscripten include directory {include_dir} does not exist."); - Environment.Exit (1); - } - var parserOptions = driver.ParserOptions; - parserOptions.NoBuiltinIncludes = true; - parserOptions.NoStandardIncludes = true; - parserOptions.TargetTriple = target.Triple; - parserOptions.AddSystemIncludeDirs(include_dir); - break; - default: - throw new ArgumentOutOfRangeException (); - } - } - - static string GetArchFromTriple(string triple) - { - if (triple.Contains("mips")) - return "mips"; - - if (triple.Contains("arm64") || triple.Contains("aarch64")) - return "arm64"; - - if (triple.Contains("arm")) - return "arm"; - - if (triple.Contains("i686")) - return "x86"; - - if (triple.Contains("x86_64")) - return "x86_64"; - - throw new Exception("Unknown architecture from triple: " + triple); - } - - static string GetXcodeToolchainPath() - { - var toolchains = Directory.EnumerateDirectories("/Applications", "Xcode*") - .ToList(); - toolchains.Sort(); - - var toolchainPath = toolchains.LastOrDefault(); - if (toolchainPath == null) - throw new Exception("Could not find a valid Xcode SDK"); - - return toolchainPath; - } - - static string GetXcodeBuiltinIncludesFolder() - { - var toolchainPath = GetXcodeToolchainPath(); - - var toolchains = Directory.EnumerateDirectories(Path.Combine(toolchainPath, - "Contents/Developer/Toolchains")).ToList(); - toolchains.Sort(); - - toolchainPath = toolchains.LastOrDefault(); - if (toolchainPath == null) - throw new Exception("Could not find a valid Xcode toolchain"); - - var includePaths = Directory.EnumerateDirectories(Path.Combine(toolchainPath, - "usr/lib/clang")).ToList(); - var includePath = includePaths.LastOrDefault(); - - if (includePath == null) - throw new Exception("Could not find a valid Clang include folder"); - - return Path.Combine(includePath, "include"); - } - - static string GetXcodeiOSIncludesFolder() - { - var toolchainPath = GetXcodeToolchainPath(); - - var sdkPaths = Directory.EnumerateDirectories(Path.Combine(toolchainPath, - "Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs")).ToList(); - var sdkPath = sdkPaths.LastOrDefault(); - - if (sdkPath == null) - throw new Exception("Could not find a valid iPhone SDK"); - - return Path.Combine(sdkPath, "usr/include"); - } - - static string GetXcodeOSXIncludesFolder() - { - var toolchainPath = GetXcodeToolchainPath(); - - var sdkPaths = Directory.EnumerateDirectories(Path.Combine(toolchainPath, - "Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs")).ToList(); - var sdkPath = sdkPaths.LastOrDefault(); - - if (sdkPath == null) - throw new Exception("Could not find a valid OSX SDK"); - - return Path.Combine(sdkPath, "usr/include"); - } - - static string GetXcodeWatchOSIncludesFolder() - { - var toolchainPath = GetXcodeToolchainPath(); - - var sdkPaths = Directory.EnumerateDirectories(Path.Combine(toolchainPath, - "Contents/Developer/Platforms/WatchOS.platform/Developer/SDKs")).ToList(); - var sdkPath = sdkPaths.LastOrDefault(); - - if (sdkPath == null) - throw new Exception("Could not find a valid WatchOS SDK"); - - return Path.Combine(sdkPath, "usr/include"); - } - - static void SetupXcode(Driver driver, Target target) - { - var parserOptions = driver.ParserOptions; - - var builtinsPath = GetXcodeBuiltinIncludesFolder(); - string includePath; - - switch (target.Platform) { - case TargetPlatform.iOS: - includePath = GetXcodeiOSIncludesFolder(); - break; - case TargetPlatform.WatchOS: - includePath = GetXcodeWatchOSIncludesFolder(); - break; - case TargetPlatform.OSX: - includePath = GetXcodeOSXIncludesFolder(); - break; - default: - throw new ArgumentOutOfRangeException (); - } - - parserOptions.AddSystemIncludeDirs(builtinsPath); - parserOptions.AddSystemIncludeDirs(includePath); - - parserOptions.NoBuiltinIncludes = true; - parserOptions.NoStandardIncludes = true; - parserOptions.TargetTriple = target.Triple; - } - - static string GetAndroidHostToolchainPath() - { - var toolchains = Directory.EnumerateDirectories( - Path.Combine(AndroidNdkPath, "toolchains"), "llvm*").ToList(); - toolchains.Sort(); - - var toolchainPath = toolchains.LastOrDefault(); - if (toolchainPath == null) - throw new Exception("Could not find a valid NDK host toolchain"); - - toolchains = Directory.EnumerateDirectories(Path.Combine(toolchainPath, - "prebuilt")).ToList(); - toolchains.Sort(); - - toolchainPath = toolchains.LastOrDefault(); - if (toolchainPath == null) - throw new Exception("Could not find a valid NDK host toolchain"); - - return toolchainPath; - } - - static string GetAndroidBuiltinIncludesFolder() - { - var toolchainPath = GetAndroidHostToolchainPath(); - - string clangToolchainPath = Path.Combine(toolchainPath, "lib64", "clang"); - if (!Directory.Exists (clangToolchainPath)) - clangToolchainPath = Path.Combine(toolchainPath, "lib", "clang"); - - string includePath = null; - if (Directory.Exists (clangToolchainPath)) { - var includePaths = Directory.EnumerateDirectories(clangToolchainPath).ToList(); - includePath = includePaths.LastOrDefault(); - } - if (includePath == null) - throw new Exception("Could not find a valid Clang include folder"); - - return Path.Combine(includePath, "include"); - } - - static void SetupAndroidNDK(Driver driver, Target target) - { - var options = driver.Options; - var parserOptions = driver.ParserOptions; - - var builtinsPath = GetAndroidBuiltinIncludesFolder(); - parserOptions.AddSystemIncludeDirs(builtinsPath); - - const int androidNdkApiLevel = 21; - - string arch = GetArchFromTriple(target.Triple); - var toolchainPath = Path.Combine(AndroidNdkPath, "platforms", - "android-" + androidNdkApiLevel, "arch-" + arch, - "usr", "include"); - - if (!Directory.Exists (toolchainPath)) { - // Android NDK r17 and newer no longer have per-platform include directories, they instead use a - // unified set of headers - toolchainPath = Path.Combine (AndroidNdkPath, "sysroot", "usr", "include"); - - // The unified headers require that the target API level is defined as a macro - that's how they - // differentiate between native APIs available for the given API level - parserOptions.AddDefines ($"__ANDROID_API__={androidNdkApiLevel}"); - - // And they also need to point to the per-arch `asm` directory - string asmTriple; - switch (arch) { - case "arm64": - asmTriple = "aarch64-linux-android"; - break; - - case "arm": - asmTriple = "arm-linux-androideabi"; - break; - - case "x86": - asmTriple = "i686-linux-android"; - break; - - case "x86_64": - asmTriple = "x86_64-linux-android"; - break; - - default: - throw new Exception ($"Unsupported architecture {arch}"); - } - - parserOptions.AddSystemIncludeDirs (Path.Combine (toolchainPath, asmTriple)); - } - - parserOptions.AddSystemIncludeDirs(toolchainPath); - - parserOptions.NoBuiltinIncludes = true; - parserOptions.NoStandardIncludes = true; - parserOptions.TargetTriple = target.Triple; - } - - static uint GetTypeAlign(ParserTargetInfo target, ParserIntType type) - { - switch (type) - { - case ParserIntType.SignedChar: - case ParserIntType.UnsignedChar: - return target.CharAlign; - case ParserIntType.SignedShort: - case ParserIntType.UnsignedShort: - return target.ShortAlign; - case ParserIntType.SignedInt: - case ParserIntType.UnsignedInt: - return target.IntAlign; - case ParserIntType.SignedLong: - case ParserIntType.UnsignedLong: - return target.LongAlign; - case ParserIntType.SignedLongLong: - case ParserIntType.UnsignedLongLong: - return target.LongLongAlign; - default: - throw new Exception("Type has no alignment"); - } - } - - static uint GetTypeSize(ParserTargetInfo target, ParserIntType type) - { - switch (type) - { - case ParserIntType.SignedChar: - case ParserIntType.UnsignedChar: - return target.CharWidth; - case ParserIntType.SignedShort: - case ParserIntType.UnsignedShort: - return target.ShortWidth; - case ParserIntType.SignedInt: - case ParserIntType.UnsignedInt: - return target.IntWidth; - case ParserIntType.SignedLong: - case ParserIntType.UnsignedLong: - return target.LongWidth; - case ParserIntType.SignedLongLong: - case ParserIntType.UnsignedLongLong: - return target.LongLongWidth; - default: - throw new Exception("Type has no size"); - } - } - - static string GetTargetPlatformDefine(TargetPlatform target) - { - switch (target) { - case TargetPlatform.Android: - return "TARGET_ANDROID"; - case TargetPlatform.iOS: - return "TARGET_IOS"; - case TargetPlatform.WatchOS: - return "TARGET_WATCHOS"; - case TargetPlatform.OSX: - return "TARGET_OSX"; - case TargetPlatform.WASM: - return "TARGET_WASM"; - default: - throw new ArgumentOutOfRangeException (); - } - } - - static void Dump(ASTContext ctx, ParserTargetInfo targetInfo, Target target) - { - string targetFile; - - if (!string.IsNullOrEmpty (OutputFile)) { - targetFile = OutputFile; - } else { - targetFile = target.Triple; - - if (!string.IsNullOrEmpty (OutputDir)) - targetFile = Path.Combine (OutputDir, targetFile); - - targetFile += ".h"; - } - - using (var writer = new StreamWriter(targetFile)) - //using (var writer = Console.Out) - { - writer.WriteLine("#ifndef USED_CROSS_COMPILER_OFFSETS"); - writer.WriteLine("#ifdef {0}", target.Defines[0]); - writer.WriteLine ("#ifdef {0}", GetTargetPlatformDefine (target.Platform)); - writer.WriteLine("#ifndef HAVE_BOEHM_GC"); - writer.WriteLine("#define HAS_CROSS_COMPILER_OFFSETS"); - writer.WriteLine("#if defined (USE_CROSS_COMPILE_OFFSETS) || defined (MONO_CROSS_COMPILE)"); - writer.WriteLine("#if !defined (DISABLE_METADATA_OFFSETS)"); - writer.WriteLine("#define USED_CROSS_COMPILER_OFFSETS"); - - DumpAligns(writer, targetInfo); - DumpSizes(writer, targetInfo); - DumpMetadataOffsets(writer, ctx, target); - - writer.WriteLine("#endif //disable metadata check"); - - DumpJITOffsets(writer, ctx); - - writer.WriteLine("#endif //cross compiler checks"); - writer.WriteLine("#endif //gc check"); - writer.WriteLine("#endif //os check"); - writer.WriteLine("#endif //arch check"); - writer.WriteLine("#endif //USED_CROSS_COMPILER_OFFSETS check"); - } - - Console.WriteLine("Generated offsets file: {0}", targetFile); - } - - static void DumpAligns(TextWriter writer, ParserTargetInfo target) - { - var aligns = new[] - { - new { Name = "gint8", Align = target.CharAlign}, - new { Name = "gint16", Align = target.ShortAlign}, - new { Name = "gint32", Align = target.IntAlign}, - new { Name = "gint64", Align = GetTypeAlign(target, target.Int64Type)}, - new { Name = "float", Align = target.FloatAlign}, - new { Name = "double", Align = target.DoubleAlign}, - new { Name = "gpointer", Align = GetTypeAlign(target, target.IntPtrType)}, - }; - - // Write the alignment info for the basic types. - foreach (var align in aligns) - writer.WriteLine("DECL_ALIGN2({0},{1})", align.Name, align.Align / 8); - } - - static void DumpSizes(TextWriter writer, ParserTargetInfo target) - { - var sizes = new[] - { - new { Name = "gint8", Size = target.CharWidth}, - new { Name = "gint16", Size = target.ShortWidth}, - new { Name = "gint32", Size = target.IntWidth}, - new { Name = "gint64", Size = GetTypeSize(target, target.Int64Type)}, - new { Name = "float", Size = target.FloatWidth}, - new { Name = "double", Size = target.DoubleWidth}, - new { Name = "gpointer", Size = GetTypeSize(target, target.IntPtrType)}, - }; - - // Write the size info for the basic types. - foreach (var size in sizes) - writer.WriteLine("DECL_SIZE2({0},{1})", size.Name, size.Size / 8); - } - - static Class GetClassFromTypedef(ITypedDecl typedef) - { - var type = typedef.Type.Desugar() as TagType; - if (type == null) - return null; - - var @class = type.Declaration as Class; - - return @class.IsIncomplete ? - (@class.CompleteDeclaration as Class) : @class; - } - - static void DumpClasses(TextWriter writer, ASTContext ctx, IEnumerable<string> types, - bool optional = false) - { - foreach (var @struct in types) - { - var @class = ctx.FindCompleteClass(@struct); - if (@class == null) - @class = ctx.FindCompleteClass("_" + @struct); - - if (@class == null) - { - var typedef = ctx.FindTypedef(@struct).FirstOrDefault( - decl => !decl.IsIncomplete); - - if (typedef != null) - @class = GetClassFromTypedef(typedef); - } - - if (@class == null && optional) - continue; - - if (@class == null) - throw new Exception("Expected to find struct definition for " + @struct); - - DumpStruct(writer, @class); - } - } - - static void DumpMetadataOffsets(TextWriter writer, ASTContext ctx, Target target) - { - var types = new List<string> - { - "MonoObject", - "MonoClass", - "MonoVTable", - "MonoDelegate", - "MonoInternalThread", - "MonoMulticastDelegate", - "MonoTransparentProxy", - "MonoRealProxy", - "MonoRemoteClass", - "MonoArray", - "MonoArrayBounds", - "MonoSafeHandle", - "MonoHandleRef", - "MonoComInteropProxy", - "MonoString", - "MonoException", - "MonoTypedRef", - "MonoThreadsSync", - "SgenThreadInfo", - "SgenClientThreadInfo", - "MonoProfilerCallContext" - }; - - DumpClasses(writer, ctx, types); - } - - static void DumpJITOffsets(TextWriter writer, ASTContext ctx) - { - writer.WriteLine("#ifndef DISABLE_JIT_OFFSETS"); - writer.WriteLine("#define USED_CROSS_COMPILER_OFFSETS"); - - var types = new[] - { - "MonoLMF", - "MonoMethodRuntimeGenericContext", - "MonoJitTlsData", - "MonoGSharedVtMethodRuntimeInfo", - "MonoContinuation", - "MonoContext", - "MonoDelegateTrampInfo", - }; - - DumpClasses(writer, ctx, types); - - var optionalTypes = new[] - { - "GSharedVtCallInfo", - "SeqPointInfo", - "DynCallArgs", - "MonoLMFTramp", - "CallContext", - "MonoFtnDesc" - }; - - DumpClasses(writer, ctx, optionalTypes, optional: true); - - writer.WriteLine("#endif //disable jit check"); - } - - static void DumpStruct(TextWriter writer, Class @class) - { - var name = @class.Name; - if (name.StartsWith ("_", StringComparison.Ordinal)) - name = name.Substring (1); - - writer.WriteLine ("DECL_SIZE2({0},{1})", name, @class.Layout.Size); - - foreach (var field in @class.Fields) - { - if (field.IsBitField) continue; - - if (name == "SgenThreadInfo" && field.Name == "regs") - continue; - - var layout = @class.Layout.Fields.First(f => f.FieldPtr == field.OriginalPtr); - - writer.WriteLine("DECL_OFFSET2({0},{1},{2})", name, field.Name, - layout.Offset); - } - } - } -} |