123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351 |
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using Bee.Core;
- using Bee.DotNet;
- using JetBrains.Annotations;
- using NiceIO;
- #if NEW_BEE_NAMESPACES_REMOVE
- using Bee.NativeProgramSupport;
- using Bee.Tools;
- #else
- using Unity.BuildSystem.NativeProgramSupport;
- using Unity.BuildTools;
- #endif
- /*
-
- // Activate this part once we have found a workaround for compiling against a custom Unity.Burst.Unsafe
- // compatible with Tiny. See issue #1490
- [UsedImplicitly]
- class CustomizerForUnityBurst : AsmDefCSharpProgramCustomizer
- {
- public override string CustomizerFor => "Unity.Burst";
-
- // not exactly right, but good enough for now
- public override void CustomizeSelf(AsmDefCSharpProgram program)
- {
- var path = program.AsmDefDescription.Path.Parent.Parent.Combine("Unity.Burst.Unsafe.dll");
- program.References.Add(new DotNetAssembly(path, Framework.NetStandard20));
- }
- }
- */
-
- /*
- * This file exists as an interface to programs that want to invoke bcl.exe from a bee buildprogram.
- * The idea is that when bcl.exe command line options change, this file should change, and then programs using
- * burst will pick up the changes for free, without depending on specific command line options of bcl.exe.
- *
- * How well that works, is another question.
- */
- public abstract class BurstCompiler
- {
- public static NPath BurstExecutable { get; set; }
- public abstract string TargetPlatform { get; set; }
-
- // TODO: This should become a list of target architectures to add.
- public abstract string TargetArchitecture { get; set; }
-
- public abstract string ObjectFormat { get; set; }
- public abstract string ObjectFileExtension { get; set; }
- public abstract bool UseOwnToolchain { get; set; }
- public virtual bool OnlyStaticMethods { get; set; } = false;
-
- public virtual string BurstBackend { get; set; } = "burst-llvm-10"; // Bumping this, but really should not be specifying by default, or when we bump llvm dots runtime gets left behind
-
- // Options
- public virtual bool SafetyChecks { get; set; } = false;
- public virtual bool DisableVectors { get; set; } = false;
- public virtual bool Link { get; set; } = true;
- public virtual bool Verbose { get; set; } = false;
- public abstract string FloatPrecision { get; set; }
- public virtual int Threads { get; set; } = 9;
- public virtual bool DisableOpt { get; set; } = false;
- public virtual bool EnableGuard { get; set; } = false;
- public virtual string ExecuteMethodName { get; set; } = "ProducerExecuteFn_Gen";
- public virtual bool EnableStaticLinkage { get; set; } = false;
- public virtual bool EnableJobMarshalling { get; set; } = false;
- public virtual bool EnableDirectExternalLinking { get; set; } = false;
- public virtual string DisableWarnings { get; set; } = ""; // ; seperated list of ids, e.g. BC1370;BC1322
-
- public virtual bool EmitLlvmObjects { get; set; } = false; // Added because burst now compiles/links wasm code as native objects by default
-
- static string[] GetBurstCommandLineArgs(
- BurstCompiler compiler,
- NPath outputPrefixForObjectFile,
- NPath outputDirForPatchedAssemblies,
- string pinvokeName,
- DotNetAssembly[] inputAssemblies)
- {
- var commandLineArguments = new[]
- {
- $"--platform={compiler.TargetPlatform}",
- $"--target={compiler.TargetArchitecture}",
- $"--format={compiler.ObjectFormat}",
- compiler.SafetyChecks ? "--safety-checks" : "",
- $"--dump=None",
- compiler.DisableVectors ? "--disable-vectors" : "",
- compiler.Link ? "" : "--nolink",
- $"--float-precision={compiler.FloatPrecision}",
- $"--keep-intermediate-files",
- compiler.EmitLlvmObjects?"--emit-llvm-objects":"",
- compiler.Verbose ? "--verbose" : "",
- $"--patch-assemblies-into={outputDirForPatchedAssemblies}",
- $"--output={outputPrefixForObjectFile}",
- compiler.OnlyStaticMethods ? "--only-static-methods" : "",
- "--method-prefix=burstedmethod_",
- $"--pinvoke-name={pinvokeName}",
- $"--backend={compiler.BurstBackend}",
- $"--execute-method-name={compiler.ExecuteMethodName}",
- "--debug=Full",
- compiler.EnableDirectExternalLinking ? "--enable-direct-external-linking" : "",
- compiler.DisableOpt ? "--disable-opt" : "",
- $"--threads={compiler.Threads}",
- compiler.EnableGuard ? "--enable-guard" : "",
- !String.IsNullOrEmpty(compiler.DisableWarnings) ? $"--disable-warnings={compiler.DisableWarnings}" : ""
- }.Concat(inputAssemblies.Select(asm => $"--root-assembly={asm.Path}"));
- if (!compiler.UseOwnToolchain)
- commandLineArguments = commandLineArguments.Concat(new[] {"--no-native-toolchain"});
-
-
- if (!HostPlatform.IsWindows)
- commandLineArguments = new[] {BurstExecutable.ToString(SlashMode.Native)}.Concat(commandLineArguments);
- if (compiler.EnableStaticLinkage)
- commandLineArguments = commandLineArguments.Concat(new[] {"--generate-static-linkage-methods"});
- if (compiler.EnableJobMarshalling)
- commandLineArguments = commandLineArguments.Concat(new[] { "--generate-job-marshalling-methods" });
-
- return commandLineArguments.ToArray();
- }
-
- static IEnumerable<NPath> AddDebugSymbolPaths(DotNetAssembly[] assemblies)
- {
- return assemblies.SelectMany(
- asm =>
- {
- var ret = new List<NPath> {asm.Path};
- if (asm.DebugSymbolPath != null)
- ret.Add(asm.DebugSymbolPath);
- return ret;
- });
- }
-
- static string[] ArgumentsToResponseFile(bool usesMono, NPath targetDir, string[] commandLineArgs, out NPath responseFile)
- {
- var remainingArgs = usesMono? commandLineArgs.Skip(1) : commandLineArgs;
- var joinedArgs = String.Join(Environment.NewLine, remainingArgs.Where(s => !String.IsNullOrEmpty(s)));
- KnuthHash hash = new KnuthHash();
- hash.Add(joinedArgs);
- responseFile = targetDir.Combine($"{hash.Value}.rsp");
-
- Backend.Current.AddWriteTextAction(
- responseFile,
- joinedArgs,
- "BurstResponseFile");
-
- if (usesMono)
- {
- return new [] { commandLineArgs[0], $"@{responseFile}"};
- }
- return new [] {$"@{responseFile}"};
- }
-
- public static BagOfObjectFilesLibrary SetupBurstCompilationForAssemblies(
- BurstCompiler compiler,
- DotNetAssembly unpatchedInputAssembly,
- NPath outputDirForObjectFile,
- NPath outputDirForPatchedAssemblies,
- string pinvokeName,
- out DotNetAssembly patchedAssembly)
- {
- /*
- * Note that you can have Link be true and still use this, because on iOS for example if you
- * DON'T pass --no-link, it will NOT link, but it WILL correctly override the llvm backend.
- *
- * if you DO pass --no-link, it will also not link, but then incorrectly use llvm 9.
- */
-
- patchedAssembly = unpatchedInputAssembly.ApplyDotNetAssembliesPostProcessor(
- outputDirForPatchedAssemblies,
- (inputAssemblies, targetDir) =>
- {
- var usesMono = HostPlatform.IsWindows ? false : true;
- var executableStringFor = !usesMono ? BurstExecutable.ToString(SlashMode.Native) : "mono";
- var commandLineArgs = GetBurstCommandLineArgs(
- compiler,
- outputDirForObjectFile.Combine(pinvokeName),
- outputDirForPatchedAssemblies,
- pinvokeName,
- inputAssemblies);
-
- var inputPaths = AddDebugSymbolPaths(inputAssemblies);
- var targetFiles = inputPaths.Select(p => targetDir.Combine(p.FileName));
-
- var finalArguments = ArgumentsToResponseFile(usesMono, targetDir, commandLineArgs, out var responseFile);
-
- Backend.Current.AddAction(
- "Burst",
- //todo: make burst process pdbs
- targetFiles.ToArray(),
- inputPaths.Concat(new[] {BurstExecutable, responseFile}).ToArray(),
- executableStringFor,
- finalArguments,
- targetDirectories: new[] {outputDirForObjectFile}
- );
- });
- var needFake = true;
- NPath[] objectFileList = null;
- if (outputDirForObjectFile.Exists())
- {
- objectFileList = outputDirForObjectFile.Files($"*{compiler.ObjectFileExtension}");
- if (objectFileList.Length > 0)
- needFake = false;
- }
- if (needFake)
- objectFileList = new[] {outputDirForObjectFile.Combine($"fake{compiler.ObjectFileExtension}")};
- return new BagOfObjectFilesLibrary(objectFileList);
- }
-
- public static DynamicLibrary SetupBurstCompilationAndLinkForAssemblies(
- BurstCompiler compiler,
- DotNetAssembly unpatchedInputAssembly,
- NPath targetNativeLibrary,
- NPath outputDirForPatchedAssemblies,
- out DotNetAssembly patchedAssembly)
- {
- if (!compiler.Link)
- {
- throw new ArgumentException("BurstCompiler.Link must be true for SetupBurstCompilationAndLinkForAssemblies");
- }
-
- patchedAssembly = unpatchedInputAssembly.ApplyDotNetAssembliesPostProcessor(
- outputDirForPatchedAssemblies,
- (inputAssemblies, targetDir) =>
- {
- var usesMono = HostPlatform.IsWindows ? false : true;
- var executableStringFor = !usesMono ? BurstExecutable.ToString(SlashMode.Native) : "mono";
-
- var pinvokeName = HostPlatform.IsWindows
- ? targetNativeLibrary.FileNameWithoutExtension
- : targetNativeLibrary.FileName;
- var commandLineArgs = GetBurstCommandLineArgs(
- compiler,
- targetNativeLibrary.ChangeExtension(""),
- outputDirForPatchedAssemblies,
- pinvokeName,
- inputAssemblies);
-
- var inputPaths = AddDebugSymbolPaths(inputAssemblies);
- var targetFiles = inputPaths.Select(p => targetDir.Combine(p.FileName))
- .Concat(new[] {targetNativeLibrary});
-
- var finalArguments = ArgumentsToResponseFile(usesMono, targetDir, commandLineArgs, out var responseFile);
-
- Backend.Current.AddAction(
- "Burst",
- //todo: make burst process pdbs
- targetFiles.ToArray(),
- inputPaths.Concat(new[] {BurstExecutable, responseFile}).ToArray(),
- executableStringFor,
- finalArguments
- );
- });
-
- return new DynamicLibrary(targetNativeLibrary, symbolFiles: null);
- }
- }
-
- public class BurstCompilerForEmscripten : BurstCompiler
- {
- public override string TargetPlatform { get; set; } = "Wasm";
- public override string TargetArchitecture { get; set; } = "WASM32";
- public override string ObjectFormat { get; set; } = "Wasm";
- public override string FloatPrecision { get; set; } = "High";
- public override bool SafetyChecks { get; set; } = true;
- public override bool DisableVectors { get; set; } = true;
- public override bool Link { get; set; } = false;
- public override string ObjectFileExtension { get; set; } = ".bc";
- public override bool UseOwnToolchain { get; set; } = false;
- public override bool EnableStaticLinkage { get; set; } = true;
- public override bool EnableJobMarshalling { get; set; } = false;
- public override bool EnableDirectExternalLinking { get; set; } = true;
- public override bool EmitLlvmObjects { get; set; } = true; // Added because burst now compiles/links wasm code as native objects by default
- }
-
- public class BurstCompilerForWindows : BurstCompiler
- {
- public override string TargetPlatform { get; set; } = "Windows";
-
- //--target=VALUE Target CPU <Auto|X86_SSE2|X86_SSE4|X64_SSE2|X64_
- // SSE4|AVX|AVX2|AVX512|WASM32|ARMV7A_NEON32|ARMV8A_
- // AARCH64|THUMB2_NEON32> Default: Auto
- public override string TargetArchitecture { get; set; } = "X64_SSE2";
- public override string ObjectFormat { get; set; } = "Coff";
- public override string FloatPrecision { get; set; } = "High";
- public override bool SafetyChecks { get; set; } = true;
- public override bool DisableVectors { get; set; } = false;
- public override bool Link { get; set; } = false; //true;
- public override string ObjectFileExtension { get; set; } = ".obj";
- public override bool UseOwnToolchain { get; set; } = true;
- public override bool EnableDirectExternalLinking { get; set; } = false;
- //public override string BurstBackend { get; set; } = "burst-llvm-custom";
- public override bool EnableJobMarshalling { get; set; } = true;
- }
-
- public class BurstCompilerForWindows64 : BurstCompilerForWindows
- {
- public override string TargetArchitecture { get; set; } = "X64_SSE4";
- }
-
- public class BurstCompilerForMac : BurstCompiler
- {
- public override string TargetPlatform { get; set; } = "macOS";
-
- //--target=VALUE Target CPU <Auto|X86_SSE2|X86_SSE4|X64_SSE2|X64_
- // SSE4|AVX|AVX2|AVX512|WASM32|ARMV7A_NEON32|ARMV8A_
- // AARCH64|THUMB2_NEON32> Default: Auto
- public override string TargetArchitecture { get; set; } = "X64_SSE2";
- public override string ObjectFormat { get; set; } = "MachO";
- public override string FloatPrecision { get; set; } = "High";
- public override bool SafetyChecks { get; set; } = true;
- public override bool DisableVectors { get; set; } = false;
- public override bool Link { get; set; } = false;
- public override string ObjectFileExtension { get; set; } = ".o";
- public override bool UseOwnToolchain { get; set; } = true;
- }
-
- public class BurstCompilerForAndroid : BurstCompiler
- {
- public override string TargetPlatform { get; set; } = "Android";
-
- //--target=VALUE Target CPU <Auto|X86_SSE2|X86_SSE4|X64_SSE2|X64_
- // SSE4|AVX|AVX2|AVX512|WASM32|ARMV7A_NEON32|ARMV8A_
- // AARCH64|THUMB2_NEON32> Default: Auto
- public override string TargetArchitecture { get; set; } = "ARMV7A_NEON32";
- public override string ObjectFormat { get; set; } = "Elf";
- public override string FloatPrecision { get; set; } = "High";
- public override bool SafetyChecks { get; set; } = true;
- public override bool DisableVectors { get; set; } = false;
- public override bool Link { get; set; } = false;
- public override string ObjectFileExtension { get; set; } = ".o";
- public override bool UseOwnToolchain { get; set; } = true;
-
- public override bool EnableDirectExternalLinking { get; set; } = true;
- }
-
- public class BurstCompilerForiOS : BurstCompiler
- {
- public override string TargetPlatform { get; set; } = "iOS";
-
- //--target=VALUE Target CPU <Auto|X86_SSE2|X86_SSE4|X64_SSE2|X64_
- // SSE4|AVX|AVX2|AVX512|WASM32|ARMV7A_NEON32|ARMV8A_
- // AARCH64|THUMB2_NEON32> Default: Auto
- public override string TargetArchitecture { get; set; } = "ARMV8A_AARCH64";
- public override string ObjectFormat { get; set; } = "Elf";
- public override bool SafetyChecks { get; set; } = true;
- public override bool DisableVectors { get; set; } = false;
- public override bool Link { get; set; } = true;
- public override string FloatPrecision { get; set; } = "High";
- public override string ObjectFileExtension { get; set; } = ".o";
- public override bool UseOwnToolchain { get; set; } = true;
- public override bool EnableDirectExternalLinking { get; set; } = true;
- }
|