Example #1
0
    private static IFileBundle Il2CppFromSteve()
    {
        var stevedoreArtifact = new StevedoreArtifact("il2cpp");

        Backend.Current.Register(stevedoreArtifact);
        return(stevedoreArtifact);
    }
Example #2
0
        public AndroidApkToolchain(AndroidNdk ndk) : base(ndk)
        {
            DynamicLibraryFormat = new AndroidApkDynamicLibraryFormat(this);
            ExecutableFormat     = new AndroidApkMainModuleFormat(this);

            var sdk = new StevedoreArtifact(HostPlatform.Pick(
                                                linux: "android-sdk-linux-x86_64",
                                                mac: "android-sdk-darwin-x86_64",
                                                windows: "android-sdk-windows-x86_64"
                                                ));

            var jdk = new StevedoreArtifact(HostPlatform.Pick(
                                                linux: "open-jdk-linux-x64",
                                                mac: "open-jdk-mac-x64",
                                                windows: "open-jdk-win-x64"
                                                ));

            Backend.Current.Register(sdk);
            SdkPath = sdk.Path;

            Backend.Current.Register(jdk);
            JavaPath = jdk.Path;

            var gradle = new StevedoreArtifact("gradle");

            Backend.Current.Register(gradle);
            GradlePath = gradle.Path;
        }
Example #3
0
    private static IFileBundle Il2CppDepsFromSteve()
    {
        var stevedoreArtifact = new StevedoreArtifact("MonoBleedingEdgeSub");

        Backend.Current.Register(stevedoreArtifact);
        return(stevedoreArtifact);
    }
    private static NPath GetOrCreateSteveArtifactPath(String name)
    {
        if (!ArtifactPaths.ContainsKey(name))
        {
            var artifact = new StevedoreArtifact(name);
            ArtifactPaths[name] = artifact.Path;
        }

        return(ArtifactPaths[name]);
    }
    protected override void SetupReferences()
    {
        base.SetupReferences();
        var cecilArtifact = StevedoreArtifact.Testing("unity-cecil/b093701f8ba7b54aea0c62ac08f376b783a0cf98_b3fb8db6e2d68564c9e28c3713b6f742d4c928aef8a420028d3a149af7d67152.zip");

        Backend.Current.Register(cecilArtifact);
        References.Add(cecilArtifact.Path.Combine("lib", "net40", "Unity.Cecil.dll"));
        References.Add(cecilArtifact.Path.Combine("lib", "net40", "Unity.Cecil.Rocks.dll"));
        References.Add(cecilArtifact.Path.Combine("lib", "net40", "Unity.Cecil.Mdb.dll"));
        References.Add(cecilArtifact.Path.Combine("lib", "net40", "Unity.Cecil.Pdb.dll"));
    }
    static void SetupGetEditorToolsFromStevedore()
    {
        // since this target and `get-editor-tools` target outputs the same files
        // we cannot have these two targets side by side in the dag.
        // We need this to generate the only correct target
        if (CompileEditorToolsFromSourceFileFlag.FileExists())
        {
            return;
        }

        var executablesFromEditorTools = new HashSet <string>
        {
            "artifacts/Stevedore/dots-editor-tools/images/osx/cwebp",
            "artifacts/Stevedore/dots-editor-tools/images/osx/moz-cjpeg",
            "artifacts/Stevedore/dots-editor-tools/images/osx/pngcrush",
            "artifacts/Stevedore/dots-editor-tools/manager/DotsEditorTools-macos",
        };

        var EditorTools = new StevedoreArtifact("dots-editor-tools");

        Backend.Current.Register(EditorTools);

        var dependencies = new List <NPath>();

        foreach (var file in EditorTools.GetFileList())
        {
            var target = new NPath(file.ToString().Replace(EditorTools.Path.ToString(), InstallationDirectory.ToString()));

            if ((HostPlatform.IsOSX || HostPlatform.IsLinux) && executablesFromEditorTools.Contains(file.ToString()))
            {
                Backend.Current.AddAction("copy and chmod +x", new[] { target }, new[] { file }, $"cp {file.InQuotes()} {target.InQuotes()} && chmod +x {target.InQuotes()}", Array.Empty <string>());
            }
            else
            {
                CopyTool.Instance().Setup(target, file);
            }

            dependencies.Add(target);
        }

        Backend.Current.AddAliasDependency("get-editor-tools", dependencies.ToArray());
    }
Example #7
0
    public static NPath GetUnusualPath(this StevedoreArtifact artifact)
    {
        var path = new NPath("artifacts").Combine("Stevedore", artifact.ArtifactName);

        return(path);
    }
    public BgfxBuild()
    {
        var rendererRoot = AsmDefConfigFile.AsmDefDescriptionFor("Unity.Tiny.Rendering.Native").Directory;

        bool useLocalBgfx = false;

        BgfxArtifact = new StevedoreArtifact("bgfx-source");
        BgfxRoot     = BgfxArtifact.Path.ResolveWithFileSystem();

        //BgfxRoot = @"C:\Users\sebastianm\gits\bgfx-root";
        //useLocalBgfx = true;

        var bx   = BgfxRoot.Combine("bx");
        var bgfx = BgfxRoot.Combine("bgfx");
        var bimg = BgfxRoot.Combine("bimg");

        // Note that these 3 NativePrograms are only linked in as BagOfObjects into the bgfx dll above.
        // They should not have Libraries themselves (e.g. bgfx should not reference the bx or bimg NativePrograms).
        // This means that PublicIncludes won't work, which is why Bimg and Bgfx explicitly add BxLib's PublicIncludes
        // to their own Includes.

        BxLib = new NativeProgram("bx")
        {
            Exceptions = { false },
            RTTI       = { false },
            PublicIncludeDirectories =
            {
                bx.Combine("include"),
                bx.Combine("3rdparty"),
            },
            Sources =
            {
                //bx.Combine("src").Files("*.cpp").Except(new[] {bx.Combine("src/amalgamated.cpp"), bx.Combine("src/crtnone.cpp")})
                bx.Combine("src/amalgamated.cpp")
            },
            Defines = { "__STDC_FORMAT_MACROS" },
        };
        BxLib.CompilerSettings().Add(c => c.WithCppLanguageVersion(CppLanguageVersion.Cpp14));
        BxLib.CompilerSettingsForMac().Add(c => c.WithObjcArc(false));
        BxLib.CompilerSettingsForIos().Add(c => c.WithObjcArc(false));
        BxLib.Defines.Add(c => c.Platform is WindowsPlatform, "_CRT_SECURE_NO_WARNINGS");
        BxLib.PublicIncludeDirectories.Add(c => c.ToolChain is WindowsToolchain, bx.Combine("include/compat/msvc"));
        BxLib.PublicIncludeDirectories.Add(c => c.Platform is MacOSXPlatform, bx.Combine("include/compat/osx"));
        BxLib.PublicIncludeDirectories.Add(c => c.Platform is IosPlatform, bx.Combine("include/compat/ios"));
        BxLib.CompilerSettingsForEmscripten().Add(Il2Cpp.ManagedDebuggingIsEnabled,
                                                  c => c.WithMultithreading_Compiler(EmscriptenMultithreadingMode.Enabled));

        BimgLib = new NativeProgram("bimg")
        {
            Exceptions         = { false },
            RTTI               = { false },
            IncludeDirectories =
            {
                bimg.Combine("include"),
                bimg.Combine("3rdparty/astc-codec/include"),
                // comment out next line once BIMG_DECODE_ASTC lands in bimg
                bimg.Combine("3rdparty/astc-codec"),
            },
            Sources =
            {
                bimg.Combine("src/image.cpp"),
                bimg.Combine("src/image_gnf.cpp"),
                // comment out next line once BIMG_DECODE_ASTC lands in bimg
                bimg.Combine("3rdparty/astc-codec/src/decoder").CombineMany(new [] { "astc_file.cc","codec.cc",                                                    "endpoint_codec.cc", "footprint.cc", "integer_sequence_codec.cc", "intermediate_astc_block.cc", "logical_astc_block.cc", "partition.cc", "physical_astc_block.cc", "quantization.cc", "weight_infill.cc" })
            },
            Defines =
            {
                "__STDC_FORMAT_MACROS",
                "BIMG_DECODE_ENABLE=0"
            },
        };
        BimgLib.CompilerSettings().Add(c => c.WithCppLanguageVersion(CppLanguageVersion.Cpp14));
        BimgLib.CompilerSettingsForMac().Add(c => c.WithObjcArc(false));
        BimgLib.CompilerSettingsForIos().Add(c => c.WithObjcArc(false));
        BimgLib.IncludeDirectories.Add(c => BxLib.PublicIncludeDirectories.For(c));
        BimgLib.CompilerSettingsForEmscripten().Add(Il2Cpp.ManagedDebuggingIsEnabled,
                                                    c => c.WithMultithreading_Compiler(EmscriptenMultithreadingMode.Enabled));

        BgfxLib = new NativeProgram("bgfx")
        {
            Exceptions         = { false },
            RTTI               = { false },
            IncludeDirectories =
            {
                bimg.Combine("include"),
                bgfx.Combine("include"),
                bgfx.Combine("3rdparty"),
                bgfx.Combine("3rdparty/khronos"),
                rendererRoot.Combine("cpp~/include"),
            },
            Defines =
            {
                "BGFX_SHARED_LIB_BUILD",
                "__STDC_FORMAT_MACROS"
            },
        };
        BgfxLib.CompilerSettings().Add(c => c.WithCppLanguageVersion(CppLanguageVersion.Cpp14));
        BgfxLib.CompilerSettingsForMac().Add(c => c.WithObjcArc(false));
        BgfxLib.CompilerSettingsForIos().Add(c => c.WithObjcArc(false));
        BgfxLib.IncludeDirectories.Add(c => BxLib.PublicIncludeDirectories.For(c));

        BgfxLib.Defines.Add(c => ((DotsRuntimeNativeProgramConfiguration)c).CSharpConfig.Defines.Contains("RENDERING_ENABLE_TRACE"), "BGFX_CONFIG_DEBUG=1");
        BgfxLib.Defines.Add(c => c.ToolChain is WindowsToolchain, "_CRT_SECURE_NO_WARNINGS");
        //BgfxLib.Defines.Add("BGFX_CONFIG_DEBUG_UNIFORM=0");
        if (!useLocalBgfx)
        {
            // when using bgfx from stevedore, this requires pix3.h which we don't distribute
            BgfxLib.Defines.Add(c => c.Platform is WindowsPlatform, "BGFX_CONFIG_DEBUG_ANNOTATION=0");
        }
        else
        {
            BgfxLib.Defines.Add(c => c.Platform is WindowsPlatform, "BGFX_CONFIG_DEBUG_ANNOTATION=0");
            ///BgfxLib.IncludeDirectories.Add(bgfx.Combine("3rdparty/dxsdk"));
        }

        BgfxLib.Defines.Add("BGFX_CONFIG_MAX_BONES=4");
        BgfxLib.Defines.Add(c => (c as DotsRuntimeNativeProgramConfiguration)?.CSharpConfig.EnableProfiler == true, "BGFX_CONFIG_PROFILER=1");

        // At some point we need to stop using amalgamated, especially for small-size web builds
        BgfxLib.Sources.Add(c => !(c.Platform is MacOSXPlatform || c.Platform is IosPlatform), bgfx.Combine("src/amalgamated.cpp"));
        BgfxLib.Sources.Add(c => (c.Platform is MacOSXPlatform || c.Platform is IosPlatform), bgfx.Combine("src/amalgamated.mm"));

        // This is a hack that the Khronos eglplatform.h header understands in order to define the EGL types as intptr_t,
        // which is what emscripten wants.  Otherwise we fall into a __unix__ path, which includes X11/Xlib.h, and
        // all hell breaks loose.
        BgfxLib.Defines.Add(c => c.Platform is WebGLPlatform, "USE_OZONE");

        BgfxLib.CompilerSettingsForEmscripten().Add(Il2Cpp.ManagedDebuggingIsEnabled,
                                                    c => c.WithMultithreading_Compiler(EmscriptenMultithreadingMode.Enabled));
    }
Example #9
0
    public static NPath GenerateUnusualPath(this StevedoreArtifact artifact)
    {
        var path = new NPath("artifacts").Combine("Stevedore", artifact.ArtifactName);

        return(artifact.UnpackToUnusualLocation(path));
    }
Example #10
0
    static void Main()
    {
        BeeRootValue = BuildProgramConfigFile.AsmDefDescriptionFor("Unity.Tiny.Text").Path.Parent.Parent.Parent.Combine("DotsPlayer/bee~");

        StevedoreGlobalSettings.Instance = new StevedoreGlobalSettings
        {
            // Manifest entries always override artifact IDs hard-coded in Bee
            // Setting EnforceManifest to true will also ensure no artifacts
            // are used without being listed in a manifest.
            EnforceManifest = true,
            Manifest        =
            {
                BeeRootValue.Combine("manifest.stevedore"),
            },
        };
        //The stevedore global manifest will override DownloadableCsc.Csc72 artifacts and use Csc73
        CSharpProgram.DefaultConfig = new CSharpProgramConfiguration(CSharpCodeGen.Release, DownloadableCsc.Csc72);

        UnityLowLevel = new DotsRuntimeCSharpProgram($"{LowLevelRoot}/Unity.LowLevel")
        {
            References = { UnsafeUtility.DotNetAssembly },
            Unsafe     = true
        };

        ZeroJobs = new DotsRuntimeCSharpProgram(BeeRoot.Parent.Combine("ZeroJobs"), "Unity.ZeroJobs")
        {
            References = { UnityLowLevel },
            Unsafe     = true
        };

        var nunit = new StevedoreArtifact("nunit-framework");

        Backend.Current.Register(nunit);
        NUnitLite      = new DotNetAssembly(nunit.Path.Combine("bin", "net40", "nunitlite.dll"), Framework.Framework40);
        NUnitFramework = new DotNetAssembly(nunit.Path.Combine("bin", "net40", "nunit.framework.dll"), Framework.Framework40);

        //any asmdef that sits next to a .project file we will consider a tiny game.
        var asmDefDescriptions = BuildProgramConfigFile.AssemblyDefinitions.ToArray();

        var gameAsmDefs  = asmDefDescriptions.Where(d => d.Path.Parent.Files("*.project").Any());
        var gamePrograms = gameAsmDefs.Select(SetupGame).ToArray();

        //any asmdef that has .Tests in its name, is going to be our indicator for being a test project for now.
        var testAsmDefs  = asmDefDescriptions.Where(ad => ad.Name.EndsWith(".Tests"));
        var testPrograms = testAsmDefs.Where(asm => asm.PackageSource != "BuiltIn" && asm.PackageSource != "Registry")
                           .Select(SetupTest)
                           .ExcludeNulls()
                           .ToArray();

        var vs = new VisualStudioSolution()
        {
            Path = BuildProgramConfigFile.UnityProjectPath.Combine($"{BuildProgramConfigFile.ProjectName}-Dots.sln").RelativeTo(NPath.CurrentDirectory),
            DefaultSolutionFolderFor = file => (file.Name.Contains("Unity.") || file.Name == "mscorlib") ? "Unity" : ""
        };

        var unityToolsFolder = "Unity/tools";

        if (BeeRoot.IsChildOf(BuildProgramConfigFile.UnityProjectPath))
        {
            vs.Projects.Add(new CSharpProjectFileReference("buildprogram.gen.csproj"), unityToolsFolder);
        }

        foreach (var gameProgram in gamePrograms)
        {
            vs.Projects.Add(gameProgram);
        }
        foreach (var testProgram in testPrograms)
        {
            vs.Projects.Add(testProgram);
        }

        var toolPrograms = new[]
        { TypeRegistrationTool.EntityBuildUtils, TypeRegistrationTool.TypeRegProgram, BindGem.Instance().Program };

        if (BeeRoot.IsChildOf(BuildProgramConfigFile.UnityProjectPath))
        {
            foreach (var p in toolPrograms)
            {
                vs.Projects.Add(p, unityToolsFolder);
            }
        }

        foreach (var config in DotsConfigs.Configs)
        {
            //we want dotnet to be the default, and we cannot have nice things: https://aras-p.info/blog/2017/03/23/How-does-Visual-Studio-pick-default-config/platform/
            var solutionConfigName = config.Identifier == "dotnet" ? "Debug (dotnet)": config.Identifier;

            vs.Configurations.Add(new SolutionConfiguration(solutionConfigName, (configurations, file) =>
            {
                var firstOrDefault = configurations.FirstOrDefault(c => c == config);
                return(new Tuple <IProjectConfiguration, bool>(
                           firstOrDefault ?? configurations.First(),
                           firstOrDefault != null || toolPrograms.Any(t => t.ProjectFile == file)));
            }));
        }
        Backend.Current.AddAliasDependency("ProjectFiles", vs.Setup());

        EditorToolsBuildProgram.Setup(BeeRoot);
    }
    public static EmscriptenToolchain MakeEmscripten(EmscriptenArchitecture arch)
    {
        var emscripten        = new StevedoreArtifact("emscripten");
        var emscriptenVersion = new Version(1, 38, 28);
        var emscriptenRoot    = emscripten.Path.Combine("emscripten-nightly-1.38.28-2019_04_05_07_52");

        EmscriptenSdk sdk = null;

        if (Environment.GetEnvironmentVariable("EMSDK") != null)
        {
            Console.WriteLine("Using pre-set environment EMSDK=" + Environment.GetEnvironmentVariable("EMSDK") +
                              ". This should only be used for local development. Unset EMSDK env. variable to use tagged Emscripten version from Stevedore.");
            NodeExe = Environment.GetEnvironmentVariable("EMSDK_NODE");
            return(new EmscriptenToolchain(new EmscriptenSdk(
                                               Environment.GetEnvironmentVariable("EMSCRIPTEN"),
                                               llvmRoot: Environment.GetEnvironmentVariable("LLVM_ROOT"),
                                               pythonExe: Environment.GetEnvironmentVariable("EMSDK_PYTHON"),
                                               nodeExe: Environment.GetEnvironmentVariable("EMSDK_NODE"),
                                               architecture: arch,
                                               // Use a dummy/hardcoded version string to represent Emscripten "incoming" branch (it should be always considered
                                               // a "dirty" branch that does not correspond to any tagged release)
                                               version: new Version(9, 9, 9),
                                               isDownloadable: false
                                               )));
        }

        if (HostPlatform.IsWindows)
        {
            var llvm = new StevedoreArtifact("emscripten-llvm-win-x64");

            var python = new StevedoreArtifact("winpython2-x64");
            var node   = new StevedoreArtifact("node-win-x64");
            NodeExe = node.Path.Combine("node.exe");

            sdk = new EmscriptenSdk(
                emscriptenRoot,
                llvmRoot: llvm.Path.Combine("emscripten-llvm-e1.38.28-2019_04_05_07_52"),
                pythonExe: python.Path.Combine("WinPython-64bit-2.7.13.1Zero/python-2.7.13.amd64/python.exe"),
                nodeExe: NodeExe,
                architecture: arch,
                version: emscriptenVersion,
                isDownloadable: true,
                backendRegistrables: new[] { emscripten, llvm, python, node });
        }

        if (HostPlatform.IsLinux)
        {
            var llvm = new StevedoreArtifact("emscripten-llvm-linux-x64");
            var node = new StevedoreArtifact("node-linux-x64");
            NodeExe = node.Path.Combine("bin/node");

            sdk = new EmscriptenSdk(
                emscriptenRoot,
                llvmRoot: llvm.Path.Combine("emscripten-llvm-e1.38.28-2019_03_07_23_26"),
                pythonExe: "/usr/bin/python2",
                nodeExe: NodeExe,
                architecture: arch,
                version: emscriptenVersion,
                isDownloadable: true,
                backendRegistrables: new[] { emscripten, llvm, node });
        }

        if (HostPlatform.IsOSX)
        {
            var llvm = new StevedoreArtifact("emscripten-llvm-mac-x64");
            var node = new StevedoreArtifact("node-mac-x64");
            NodeExe = node.Path.Combine("bin/node");

            sdk = new EmscriptenSdk(
                emscriptenRoot: emscriptenRoot,
                llvmRoot: llvm.Path.Combine("emscripten-llvm-e1.38.28-2019_04_05_07_52"),
                pythonExe: "/usr/bin/python",
                nodeExe: NodeExe,
                architecture: arch,
                version: emscriptenVersion,
                isDownloadable: true,
                backendRegistrables: new[] { emscripten, llvm, node });
        }

        if (sdk == null)
        {
            return(null);
        }

        return(new EmscriptenToolchain(sdk));
    }
    public static EmscriptenToolchain MakeEmscripten(EmscriptenArchitecture arch)
    {
        var emscripten        = new StevedoreArtifact("emscripten-" + EmscriptenPackageOSName());
        var llvm              = new StevedoreArtifact("emscripten-" + (UseWasmBackend ? "wasm" : "fc") + "-llvm-" + EmscriptenPackageOSName());
        var emscriptenVersion = new Version(1, 39, 17);

        emscripten.GenerateUnusualPath();
        var emscriptenRoot = emscripten.GetUnusualPath();

        var llvmPath = llvm.Path.ResolveWithFileSystem();

        EmscriptenSdk sdk = null;

        if (Environment.GetEnvironmentVariable("EMSDK") != null)
        {
            Console.WriteLine("Using pre-set environment EMSDK=" + Environment.GetEnvironmentVariable("EMSDK") +
                              ". This should only be used for local development. Unset EMSDK env. variable to use tagged Emscripten version from Stevedore.");
            NodeExe = Environment.GetEnvironmentVariable("EMSDK_NODE");
            sdk     = new EmscriptenSdk(
                Environment.GetEnvironmentVariable("EMSCRIPTEN"),
                llvmRoot: Environment.GetEnvironmentVariable("LLVM_ROOT"),
                pythonExe: Environment.GetEnvironmentVariable("EMSDK_PYTHON"),
                nodeExe: NodeExe,
                architecture: arch,
                // Use a dummy/hardcoded version string to represent Emscripten "incoming" branch (it should be always considered
                // a "dirty" branch that does not correspond to any tagged release)
                version: new Version(9, 9, 9),
                isDownloadable: false
                );
        }
        else if (HostPlatform.IsWindows)
        {
            var python = new StevedoreArtifact("winpython2-x64");
            var node   = new StevedoreArtifact("node-win-x64");

            node.GenerateUnusualPath();
            NodeExe = node.GetUnusualPath().Combine("node.exe");

            var pythonPath = python.Path.Combine("WinPython-64bit-2.7.13.1Zero/python-2.7.13.amd64/python.exe").ResolveWithFileSystem();

            sdk = new EmscriptenSdk(
                emscriptenRoot,
                llvmRoot: llvmPath,
                pythonExe: pythonPath,
                nodeExe: NodeExe,
                architecture: arch,
                version: emscriptenVersion,
                isDownloadable: true
                );
        }
        else if (HostPlatform.IsLinux)
        {
            var node = new StevedoreArtifact("node-linux-x64");

            node.GenerateUnusualPath();
            NodeExe = node.GetUnusualPath().Combine("bin/node");

            sdk = new EmscriptenSdk(
                emscriptenRoot,
                llvmRoot: llvmPath,
                pythonExe: "/usr/bin/python2",
                nodeExe: NodeExe,
                architecture: arch,
                version: emscriptenVersion,
                isDownloadable: true
                );
        }
        else if (HostPlatform.IsOSX)
        {
            var node = new StevedoreArtifact("node-mac-x64");

            node.GenerateUnusualPath();
            NodeExe = node.GetUnusualPath().Combine("bin/node");

            sdk = new EmscriptenSdk(
                emscriptenRoot: emscriptenRoot,
                llvmRoot: llvmPath,
                pythonExe: "/usr/bin/python",
                nodeExe: NodeExe,
                architecture: arch,
                version: emscriptenVersion,
                isDownloadable: true
                );
        }

        if (sdk == null)
        {
            return(null);
        }

        // All Emsdk components are already pre-setup, so no need to verify the environment.
        // This avoids issues reported in https://github.com/emscripten-core/emscripten/issues/5042
        // (macOS Java check dialog popping up and slight slowdown in compiler invocation times)
        // BUG: this does not actually work. Emcc is not a child of the Bee build process.
        // Switch to use something else.
//        if (Environment.GetEnvironmentVariable("EMCC_SKIP_SANITY_CHECK") == null)
//            Environment.SetEnvironmentVariable("EMCC_SKIP_SANITY_CHECK", "1");

        return(new EmscriptenToolchain(sdk));
    }
Example #13
0
        public static void Add(NativeProgram np)
        {
            var allPlatforms = new []
            {
                "Android",
                "Linux",
                "Windows",
                "OSX",
                "IOS",
                "WebGL"
            };

            var staticPlatforms = new[]
            {
                "IOS",
                "WebGL",
            };

            var allArtifact = new StevedoreArtifact("nativejobs-all-public");

            Backend.Current.Register(allArtifact);
            np.PublicIncludeDirectories.Add(allArtifact.Path.Combine("Include"));

            DotsConfiguration DotsConfig(NativeProgramConfiguration npc) => ((DotsRuntimeNativeProgramConfiguration)npc).CSharpConfig.DotsConfiguration;

            foreach (var platform in allPlatforms)
            {
                var platformIncludes = new StevedoreArtifact($"nativejobs-{platform}-public");
                var prebuiltLibName  = $"nativejobs-{platform}" + (staticPlatforms.Contains(platform) ? "-s" : "-d");
                var prebuiltLib      = new StevedoreArtifact(prebuiltLibName);
                Backend.Current.Register(platformIncludes);
                Backend.Current.Register(prebuiltLib);

                np.PublicDefines.Add(c => c.Platform.Name == platform, "BASELIB_USE_DYNAMICLIBRARY=1");
                np.PublicIncludeDirectories.Add(c => c.Platform.Name == platform, platformIncludes.Path.Combine("Platforms", platform, "Include"));

                switch (platform)
                {
                case "Windows":
                    np.Libraries.Add(c => c.Platform.Name == platform,
                                     c => new[] { new MsvcDynamicLibrary(prebuiltLib.Path.Combine("lib", platform.ToLower(), BaselibArchitectureName(c), DotsConfig(c).ToString().ToLower(), "nativejobs.dll")) });
                    break;

                case "Linux":
                case "Android":
                    np.Libraries.Add(c => c.Platform.Name == platform,
                                     c => new[] { new DynamicLibrary(prebuiltLib.Path.Combine("lib", platform.ToLower(), BaselibArchitectureName(c), DotsConfig(c).ToString().ToLower(), "libnativejobs.so")) });
                    break;

                case "OSX":
                    np.Libraries.Add(c => c.Platform.Name == platform,
                                     c => new[] { new DynamicLibrary(prebuiltLib.Path.Combine("lib", platform.ToLower(), BaselibArchitectureName(c), DotsConfig(c).ToString().ToLower(), "libnativejobs.dylib")) });
                    break;

                case "IOS":
                    // this is ugly solution, but I don't see any other way to add static librray to Deployables
                    np.Libraries.Add(c => c.Platform.Name == platform,
                                     c => new[] { new DynamicLibrary(prebuiltLib.Path.Combine("lib", platform.ToLower(), BaselibArchitectureName(c), DotsConfig(c).ToString().ToLower(), "libnativejobs.a")) });
                    break;

                case "WebGL":
                    np.Libraries.Add(c => c.Platform.Name == platform,
                                     c => new[] { new StaticLibrary(prebuiltLib.Path.Combine("lib", platform.ToLower(), BaselibArchitectureName(c), DotsConfig(c).ToString().ToLower(), "libnativejobs.bc")) });
                    break;
                }
            }
        }
    public static NativeProgram SetupGLFW()
    {
        var glfwArtifacts = new StevedoreArtifact("glfw");

        Backend.Current.Register(glfwArtifacts);
        var glfwRoot = glfwArtifacts.Path;

        var glfwLib = new NativeProgram("libglfw")
        {
            //RootDirectory = glfwRoot,
            IncludeDirectories =
            {
                glfwRoot.Combine("include"),
                glfwRoot.Combine("src"),
            },
            PublicIncludeDirectories =
            {
                glfwRoot.Combine("include")
            },
            Sources =
            {
            },
        };

        glfwLib.Defines.Add(c => c.CodeGen != CodeGen.Debug, "NDEBUG");

        glfwLib.Sources.Add(glfwRoot.Combine("src").CombineMany(new string[]
        {
            "context.c", "init.c", "input.c", "monitor.c", "vulkan.c", "window.c",
        }));

        //
        // Windows
        //
        glfwLib.Defines.Add(c => c.Platform is WindowsPlatform, "_GLFW_WIN32", "_GLFW_BUILD_DLL");
        glfwLib.Sources.Add(c => c.Platform is WindowsPlatform, glfwRoot.Combine("src").CombineMany(new string[]
        {
            "win32_init.c",
            "win32_joystick.c",
            "win32_monitor.c",
            "win32_time.c",
            "win32_thread.c",
            "win32_window.c",
            "wgl_context.c",
            "egl_context.c",
            "osmesa_context.c"
        }));

        glfwLib.Libraries.Add(c => c.Platform is WindowsPlatform,
                              new List <string>
        {
            "winmm",
            "gdi32",
            "opengl32",
            "user32",
            "winspool",
            "shell32",
            "uuid",
            "comdlg32",
            "advapi32"
        }
                              .ConvertAll(s => new SystemLibrary(s + ".lib"))
                              );

        //
        // Linux
        //
        glfwLib.Defines.Add(c => c.Platform is LinuxPlatform, new string[]
                            { "_GLFW_X11", "IL_NO_UTX" });


        glfwLib.Sources.Add(c => c.Platform is LinuxPlatform, glfwRoot.Combine("src").CombineMany(new string[]
        {
            "input.c",
            "linux_joystick.c",
            "x11_init.c",
            "x11_monitor.c",
            "x11_window.c",
            "xkb_unicode.c",
            "egl_context.c",
            "glx_context.c",
            "osmesa_context.c",
            "posix_thread.c",
            "posix_time.c"
        }));
        glfwLib.Libraries.Add(c => c.Platform is LinuxPlatform,
                              new List <string> {
            "GL", "X11", "udev", "Xrandr", "dl", "rt"
        }
                              .ConvertAll(s => new SystemLibrary(s)));
        //
        // Mac/iOS
        //
        glfwLib.Defines.Add(c => c.Platform is MacOSXPlatform, new string[]
                            { "_GLFW_COCOA" });

        glfwLib.Sources.Add(c => c.Platform is MacOSXPlatform, glfwRoot.Combine("src").CombineMany(new string[]
        {
            "cocoa_init.m", "cocoa_joystick.m", "cocoa_monitor.m",
            "cocoa_window.m", "cocoa_time.c", "posix_thread.c",
            "nsgl_context.m", "egl_context.c", "osmesa_context.c"
        }));

        glfwLib.Libraries.Add(c => c.Platform is MacOSXPlatform,
                              new List <string> {
            "OpenGL", "CoreFoundation", "IOKit", "Cocoa", "CoreData", "CoreVideo"
        }
                              .ConvertAll(s => new SystemFramework(s)));
        return(glfwLib);
    }
Example #15
0
    private static IFileBundle Il2CppFromSteve()
    {
        var stevedoreArtifact = new StevedoreArtifact("il2cpp");

        return(stevedoreArtifact);
    }
Example #16
0
    static void Main()
    {
        if (!(Backend.Current is TundraBackend))
        {
            StandaloneBeeDriver.RunBuildProgramInBeeEnvironment("dummy.json", Main);
            return;
        }

        BeeRootValue = AsmDefConfigFile.AsmDefDescriptionFor("Unity.ZeroPlayer.TypeRegGen").Path.Parent.Parent.Combine("bee~");

        StevedoreGlobalSettings.Instance = new StevedoreGlobalSettings
        {
            // Manifest entries always override artifact IDs hard-coded in Bee
            // Setting EnforceManifest to true will also ensure no artifacts
            // are used without being listed in a manifest.
            EnforceManifest = true,
            Manifest        =
            {
                BeeRootValue.Combine("manifest.stevedore"),
            },
        };
        //The stevedore global manifest will override DownloadableCsc.Csc72 artifacts and use Csc73
        CSharpProgram.DefaultConfig = new CSharpProgramConfiguration(CSharpCodeGen.Release, DownloadableCsc.Csc72);

        UnityLowLevel = new DotsRuntimeCSharpProgram($"{LowLevelRoot}/Unity.LowLevel")
        {
            References = { UnsafeUtility.DotNetAssembly },
            Unsafe     = true
        };
        UnityLowLevel.NativeProgram.Libraries.Add(IsLinux, new SystemLibrary("dl"));

        ZeroJobs = new DotsRuntimeCSharpProgram($"{LowLevelRoot}/Unity.ZeroJobs")
        {
            References = { UnityLowLevel },
            Unsafe     = true
        };

        UnityCompilationPipeline = new DotNetAssembly(AsmDefConfigFile.UnityCompilationPipelineAssemblyPath, Framework.NetStandard20);

        var nunit = new StevedoreArtifact("nunit-framework");

        Backend.Current.Register(nunit);
        NUnitLite      = new DotNetAssembly(nunit.Path.Combine("bin", "net40", "nunitlite.dll"), Framework.Framework40);
        NUnitFramework = new DotNetAssembly(nunit.Path.Combine("bin", "net40", "nunit.framework.dll"), Framework.Framework40);

        //any asmdef that sits next to a .project file we will consider a tiny game.
        var asmDefDescriptions = AsmDefConfigFile.AssemblyDefinitions.ToArray();

        BurstCompiler.BurstExecutable = asmDefDescriptions.First(d => d.Name == "Unity.Burst")
                                        .Path.Parent.Parent.Combine(".Runtime/bcl.exe").QuoteForProcessStart();

        var ilPostProcessorPrograms = asmDefDescriptions.Where(d => d.Name.EndsWith(".CodeGen") && !d.DefineConstraints.Contains("!NET_DOTS")).Select(GetOrMakeDotsRuntimeCSharpProgramFor);

        ILPostProcessorAssemblies = ilPostProcessorPrograms.Select(p => p.SetupSpecificConfiguration(DotsConfigs.HostDotnet)).ToArray();
        PerConfigBuildSettings    = DotsConfigs.MakeConfigs();

        var tinyMainAsmDefs = asmDefDescriptions;//.Where(d => d.NamedReferences.Contains("Unity.Tiny.Main"));
        var gameAsmDefs     = tinyMainAsmDefs.Union(AsmDefConfigFile.TestableAssemblyDefinitions);
        var gamePrograms    = gameAsmDefs.Select(SetupGame).ExcludeNulls().ToArray();

        var vs = new VisualStudioSolution
        {
            Path = AsmDefConfigFile.UnityProjectPath.Combine($"{AsmDefConfigFile.ProjectName}-Dots.sln").RelativeTo(NPath.CurrentDirectory),
            DefaultSolutionFolderFor = file => (file.Name.Contains("Unity.") || file.Name == "mscorlib") ? "Unity" : ""
        };

        var unityToolsFolder            = "Unity/tools";
        var unityILPostProcessorsFolder = "Unity/ILPostProcessing";

        if (BeeRoot.IsChildOf(AsmDefConfigFile.UnityProjectPath))
        {
            var buildProjRef = new CSharpProjectFileReference("buildprogram.gen.csproj");
            vs.Projects.Add(buildProjRef, unityToolsFolder);
            vs.Projects.Add(buildProjRef, unityILPostProcessorsFolder);
        }

        foreach (var gameProgram in gamePrograms)
        {
            vs.Projects.Add(gameProgram);
        }

        var toolPrograms = new[]
        { TypeRegistrationTool.EntityBuildUtils, TypeRegistrationTool.TypeRegProgram };

        foreach (var p in toolPrograms)
        {
            vs.Projects.Add(p, unityToolsFolder);
        }

        vs.Projects.Add(ILPostProcessorTool.ILPostProcessorRunnerProgram, unityILPostProcessorsFolder);
        foreach (var p in ilPostProcessorPrograms)
        {
            vs.Projects.Add(p, unityILPostProcessorsFolder);
        }

        foreach (var config in PerConfigBuildSettings.SelectMany(entry => entry.Value))
        {
            //we want dotnet to be the default, and we cannot have nice things: https://aras-p.info/blog/2017/03/23/How-does-Visual-Studio-pick-default-config/platform/
            var solutionConfigName = config.Identifier == "dotnet" ? "Debug (dotnet)": config.Identifier;

            vs.Configurations.Add(new SolutionConfiguration(solutionConfigName, (configurations, file) =>
            {
                var firstOrDefault = configurations.FirstOrDefault(c => c == config);
                return(new Tuple <IProjectConfiguration, bool>(
                           firstOrDefault ?? configurations.First(),
                           firstOrDefault != null || toolPrograms.Any(t => t.ProjectFile == file)));
            }));
        }

        VisualStudioSolution = vs;

        EditorToolsBuildProgram.Setup(BeeRoot);

        // Run this before solution setup, to potentially give this a chance to muck with the VisualStudioSolution
        DotsBuildCustomizer.RunAllCustomizers();

        if (!IsRequestedTargetExactlySingleAppSingleConfig())
        {
            Backend.Current.AddAliasDependency("ProjectFiles", vs.Setup());
        }
    }
Example #17
0
    private static DotsRuntimeCSharpProgram SetupGame(AsmDefDescription game)
    {
        var gameProgram       = GetOrMakeDotsRuntimeCSharpProgramFor(game);
        var configToSetupGame = new Dictionary <DotsRuntimeCSharpProgramConfiguration, DotNetAssembly>();

        if (!PerConfigBuildSettings.ContainsKey(game.Name))
        {
            return(null);
        }

        var configsToUse = PerConfigBuildSettings[game.Name].Where(config => !CanSkipSetupOf(game.Name, config));

        foreach (var config in configsToUse)
        {
            var   withoutExt     = new NPath(new NPath(gameProgram.FileName).FileNameWithoutExtension).Combine(config.Identifier);
            NPath exportManifest = withoutExt.Combine("export.manifest");
            Backend.Current.RegisterFileInfluencingGraph(exportManifest);
            if (exportManifest.FileExists())
            {
                var dataFiles = exportManifest.MakeAbsolute().ReadAllLines();
                foreach (var dataFile in dataFiles.Select(d => new NPath(d)))
                {
                    gameProgram.SupportFiles.Add(
                        c => c.Equals(config),
                        new DeployableFile(dataFile, GetDeployPathFromExportPath(dataFile)));
                }
            }

            gameProgram.ProjectFile.StartInfo.Add(
                c => c == config,
                StartInfoFor(config, EntryPointExecutableFor(gameProgram, config)));
            gameProgram.ProjectFile.BuildCommand.Add(
                c => c == config,
                new BeeBuildCommand(GameDeployBinaryFor(gameProgram, config).ToString(), false, false).ToExecuteArgs());
        }

        foreach (var config in configsToUse)
        {
            DotNetAssembly setupGame = gameProgram.SetupSpecificConfiguration(config);

            if (config.TargetFramework == TargetFramework.Tiny)
            {
                var tinyStandard = new DotNetAssembly(Il2Cpp.Distribution.Path.Combine("build/profiles/Tiny/Facades/netstandard.dll"), Framework.FrameworkNone);
                setupGame = setupGame.WithDeployables(tinyStandard);
            }

            var postILProcessedGame = ILPostProcessorTool.SetupInvocation(
                setupGame,
                config,
                gameProgram.Defines.For(config).ToArray());

            var postTypeRegGenGame = TypeRegistrationTool.SetupInvocation(postILProcessedGame, config);
            configToSetupGame[config] = postTypeRegGenGame;
        }

        var il2CppOutputProgram = new Il2Cpp.Il2CppOutputProgram(gameProgram.AsmDefDescription.Name);

        var configToSetupGameBursted = new Dictionary <DotsRuntimeCSharpProgramConfiguration, DotNetAssembly>();

        foreach (var kvp in configToSetupGame)
        {
            var config    = kvp.Key;
            var setupGame = kvp.Value;

            if (config.UseBurst)
            {
                BurstCompiler burstCompiler = null;
                if (config.Platform is WindowsPlatform)
                {
                    burstCompiler      = new BurstCompilerForWindows64();
                    burstCompiler.Link = false;
                }
                else if (config.Platform is MacOSXPlatform)
                {
                    burstCompiler      = new BurstCompilerForMac();
                    burstCompiler.Link = false;
                }
                else if (config.Platform is IosPlatform)
                {
                    burstCompiler = new BurstCompilerForiOS();
                    burstCompiler.EnableStaticLinkage = true;
                    burstCompiler.ObjectFileExtension = "a";
                }
                else if (config.Platform is LinuxPlatform)
                {
                    burstCompiler = new BurstCompilerForLinuxWaitingForBurstRelease();
                }
                else if (config.Platform is AndroidPlatform)
                {
                    burstCompiler = new BurstCompilerForAndroid();
                    burstCompiler.EnableStaticLinkage = false;
                    burstCompiler.Link = false;
                    burstCompiler.EnableDirectExternalLinking = true;
                    if (config.NativeProgramConfiguration.ToolChain.Architecture is Arm64Architecture)
                    {
                        burstCompiler.TargetArchitecture = "ARMV8A_AARCH64";
                    }
                }
                else if (config.Platform is WebGLPlatform)
                {
                    burstCompiler = new BurstCompilerForEmscripten();
                    burstCompiler.EnableStaticLinkage = true;
                    burstCompiler.DisableVectors      = false;
                }

                // Only generate marshaling info for platforms that require marshalling (e.g. Windows DotNet)
                // but also if collection checks are enabled (as that is why we need marshalling)
                burstCompiler.EnableJobMarshalling &= config.EnableUnityCollectionsChecks;
                burstCompiler.SafetyChecks          = config.EnableUnityCollectionsChecks;
                burstCompiler.DisableWarnings       = "BC1370"; // Suppress warning for burst function throwing an exception

                var            outputDir    = $"artifacts/{game.Name}/{config.Identifier}_bursted";
                var            burstLibName = "lib_burst_generated";
                DotNetAssembly burstedGame  = setupGame;

                var burstlib = BurstCompiler.SetupBurstCompilationForAssemblies(
                    burstCompiler,
                    setupGame,
                    new NPath(outputDir).Combine("bclobj"),
                    outputDir,
                    burstLibName,
                    out burstedGame);
                if ((config.Platform is IosPlatform || config.Platform is AndroidPlatform) &&
                    config.NativeProgramConfiguration.ToolChain.DynamicLibraryFormat.Extension == "a") // static lib based toolchain
                {
                    il2CppOutputProgram.Libraries.Add(c => c.Equals(config.NativeProgramConfiguration), burstlib);
                    il2CppOutputProgram.Defines.Add(
                        c => c.Equals(config.NativeProgramConfiguration),
                        $"FORCE_PINVOKE_{burstLibName}_INTERNAL");
                }
                else if (config.Platform is WebGLPlatform)
                {
                    il2CppOutputProgram.Libraries.Add(c => c.Equals(config.NativeProgramConfiguration), burstlib);
                }
                else
                {
                    var burstDynamicLib = new NativeProgram(burstLibName);
                    burstDynamicLib.Libraries.Add(c => c.Equals(config.NativeProgramConfiguration), burstlib);
                    burstDynamicLib.Libraries.Add(
                        c => c.Equals(config.NativeProgramConfiguration),
                        gameProgram.TransitiveReferencesFor(config)
                        .Where(
                            p => p is DotsRuntimeCSharpProgram &&
                            ((DotsRuntimeCSharpProgram)p).NativeProgram != null)
                        .Select(
                            p => new NativeProgramAsLibrary(((DotsRuntimeCSharpProgram)p).NativeProgram)
                    {
                        BuildMode = NativeProgramLibraryBuildMode.Dynamic
                    }));

                    if (config.Platform is IosPlatform || config.Platform is AndroidPlatform)
                    {
                        NativeJobsPrebuiltLibrary.AddToNativeProgram(burstDynamicLib);
                    }

                    DotsRuntimeCSharpProgram.SetupDotsRuntimeNativeProgram(burstLibName, burstDynamicLib);

                    var builtBurstLib = burstDynamicLib.SetupSpecificConfiguration(
                        config.NativeProgramConfiguration,
                        config.NativeProgramConfiguration.ToolChain.DynamicLibraryFormat);
                    burstedGame = burstedGame.WithDeployables(builtBurstLib);
                }

                configToSetupGameBursted[config] = burstedGame;
            }
            else
            {
                configToSetupGameBursted[config] = setupGame;
            }
        }

        var configToSetupGameStripped = new Dictionary <DotsRuntimeCSharpProgramConfiguration, DotNetAssembly>();

        foreach (var kvp in configToSetupGameBursted)
        {
            var config    = kvp.Key;
            var setupGame = kvp.Value;

            if (config.ScriptingBackend == ScriptingBackend.TinyIl2cpp)
            {
                setupGame = Il2Cpp.UnityLinker.SetupInvocation(setupGame, $"artifacts/{game.Name}/{config.Identifier}_stripped", config.NativeProgramConfiguration);
                il2CppOutputProgram.SetupConditionalSourcesAndLibrariesForConfig(config, setupGame);
                configToSetupGameStripped[kvp.Key] = setupGame;
            }
            else
            {
                configToSetupGameStripped[kvp.Key] = kvp.Value;
            }
        }

        foreach (var kvp in configToSetupGameStripped)
        {
            var   config     = kvp.Key;
            var   setupGame  = kvp.Value;
            NPath deployPath = GameDeployDirectoryFor(gameProgram, config);

            IDeployable deployedGame;
            NPath       entryPointExecutable = null;

            if (config.ScriptingBackend == ScriptingBackend.TinyIl2cpp)
            {
                var   tinyShellFileName = "tiny_shell.html";
                NPath tinyShellPath     = new NPath(new NPath(gameProgram.FileName).FileNameWithoutExtension).Combine(config.Identifier, "WebTemplate", tinyShellFileName);
                il2CppOutputProgram.DynamicLinkerSettingsForEmscripten().Add(c => c.WithShellFile(tinyShellPath));

                var builtNativeProgram = il2CppOutputProgram.SetupSpecificConfiguration(
                    config.NativeProgramConfiguration,
                    config.NativeProgramConfiguration.ExecutableFormat
                    )
                                         .WithDeployables(setupGame.RecursiveRuntimeDependenciesIncludingSelf.SelectMany(a => a.Deployables.Where(d => !(d is DotNetAssembly) && !(d is StaticLibrary)))
                                                          .ToArray());

                if (builtNativeProgram is IPackagedAppExtension)
                {
                    (builtNativeProgram as IPackagedAppExtension).SetAppPackagingParameters(
                        gameProgram.AsmDefDescription.Name, config.DotsConfiguration);
                }

                if (config.PlatformBuildConfig is WebBuildConfig webBuildConfig)
                {
                    if (webBuildConfig.SingleFile)
                    {
                        deployedGame = new DeployableFile(GameDeployBinaryFor(gameProgram, config));
                        CopyTool.Instance().Setup(deployedGame.Path, (builtNativeProgram as EmscriptenExecutable).Path);
                    }
                    else
                    {
                        deployedGame = builtNativeProgram.DeployTo(deployPath);
                    }

                    var webTemplateFolder = webBuildConfig.WebTemplateFolder;
                    if (String.IsNullOrEmpty(webTemplateFolder))
                    {
                        webTemplateFolder = LowLevelRoot.Combine("WebSupport", "WebTemplates", "Default").ToString();
                    }
                    if (new NPath(webTemplateFolder).IsRelative)
                    {
                        webTemplateFolder = new NPath("../..").Combine(webTemplateFolder).MakeAbsolute().ToString();
                    }
                    if (!new NPath(webTemplateFolder).Combine(tinyShellFileName).FileExists())
                    {
                        throw new InvalidProgramException($"Web template folder \"{webTemplateFolder}\" doesn't contain \"{tinyShellFileName}\" file.");
                    }

                    foreach (var templateFilePath in new NPath(webTemplateFolder).Files(recurse:true))
                    {
                        string fileRelativePath = templateFilePath.ToString().Substring(webTemplateFolder.Length + 1);
                        if (fileRelativePath == tinyShellFileName)
                        {
                            NPath shellPackager = LowLevelRoot.Combine("WebSupport", "package_shell_file.js");
                            NPath tinyShellJS   = LowLevelRoot.Combine("WebSupport", "tiny_shell.js");
                            var   inputs        = new List <NPath> {
                                TinyEmscripten.NodeExe, shellPackager, templateFilePath, tinyShellJS
                            };
                            var commandLineArguments = new List <string> {
                                shellPackager.ToString(), "--outputHtml", tinyShellPath.ToString(), "--inputShellHtml", templateFilePath.ToString(), "--inputShellJs", tinyShellJS.ToString()
                            };
                            NPath exportManifest = new NPath(new NPath(gameProgram.FileName).FileNameWithoutExtension).Combine(config.Identifier, "export.manifest");
                            if (webBuildConfig.SingleFile && exportManifest.FileExists())
                            {
                                inputs.Add(exportManifest.MakeAbsolute().ReadAllLines().Select(d => new NPath(d)));
                                NPath assetRootDirectory = new NPath(new NPath(gameProgram.FileName).FileNameWithoutExtension).Combine(config.Identifier);
                                commandLineArguments.AddRange(new List <string> {
                                    "--assetRootDirectory", assetRootDirectory.ToString(), "--assetManifest", exportManifest.ToString()
                                });
                            }
                            Backend.Current.AddAction(
                                actionName: "Package Shell File",
                                targetFiles: new NPath[] { tinyShellPath },
                                inputs: inputs.ToArray(),
                                executableStringFor: TinyEmscripten.NodeExe.InQuotes(),
                                commandLineArguments: commandLineArguments.Select(d => d.InQuotes()).ToArray()
                                );
                            Backend.Current.AddDependency(deployedGame.Path, tinyShellPath);
                        }
                        else if (!templateFilePath.HasExtension("meta"))
                        {
                            var targetPath = deployPath.Combine(fileRelativePath);
                            CopyTool.Instance().Setup(targetPath, templateFilePath);
                            Backend.Current.AddDependency(deployedGame.Path, targetPath);
                        }
                    }
                }
                else
                {
                    deployedGame = builtNativeProgram.DeployTo(deployPath);
                }

                entryPointExecutable = deployedGame.Path;
                if (config.EnableManagedDebugging && !(builtNativeProgram is IPackagedAppExtension))
                {
                    Backend.Current.AddDependency(deployedGame.Path, Il2Cpp.CopyIL2CPPMetadataFile(deployPath, setupGame));
                }

                // make sure http-server gets fetched from stevedore.  this should probably go elsewhere, but this is
                // a convenient quick hack place.
                if (config.PlatformBuildConfig is WebBuildConfig)
                {
                    var httpserver = new StevedoreArtifact("http-server");
                    httpserver.GenerateUnusualPath();
                    var httpserverpath = httpserver.GetUnusualPath().Combine("bin", "http-server");
                    Backend.Current.AddDependency(deployedGame.Path, httpserverpath);
                }
            }
            else
            {
                deployedGame = setupGame.DeployTo(deployPath);

                var dotNetAssembly = (DotNetAssembly)deployedGame;

                //Usually a dotnet runtime game does not have a static void main(), and instead references another "entrypoint asmdef" that provides it.
                //This is convenient, but what makes it weird is that you have to start YourEntryPoint.exe  instead of YourGame.exe.   Until we have a better
                //solution for this, we're going to copy YourEntryPoint.exe to YourGame.exe, so that it's easier to find, and so that when it runs and you look
                //at the process name you understand what it is.
                if (deployedGame.Path.HasExtension("dll"))
                {
                    var to = deployPath.Combine(deployedGame.Path.ChangeExtension("exe").FileName);
                    // Do an explicit check for the entrypoint.exe as a program may refer to other exes as assembly references
                    var from = dotNetAssembly.RecursiveRuntimeDependenciesIncludingSelf.SingleOrDefault(a => a.Path.FileName == "Unity.Runtime.EntryPoint.exe")?.Path;
                    if (from == null)
                    {
                        throw new InvalidProgramException($"Program {dotNetAssembly.Path} is an executable-like thing, but doesn't reference anything with Main");
                    }
                    Backend.Current.AddDependency(deployedGame.Path, CopyTool.Instance().Setup(to, from));
                    entryPointExecutable = to;
                }
                else
                {
                    entryPointExecutable = deployedGame.Path;
                }
            }

            //Because we use multidag, and try to not run all the setupcode when we just want to create projectfiles, we have a bit of a challenge.
            //Projectfiles require exact start and build commands. So we need to have a cheap way to calculate those. However, it's important that they
            //exactly match the actual place where the buildprogram is going to place our files. If these don't match things break down. The checks
            //in this block, they compare the "quick way to determine where the binary will be placed, and what the start executable is",  with the
            //actual return values returned from .DeployTo(), when we do run the actual buildcode.
            NPath deployedGamePath = GameDeployBinaryFor(gameProgram, config);

            //Identifier with slash means that this is complementary target and we should skip steps which are main target specific.
            //See comment in DotsConfigs.cs DotsConfigs.MakeConfigs() method for details.
            if (config.Identifier.IndexOf('/') != -1)
            {
                continue;
            }

            if (deployedGame.Path != deployedGamePath)
            {
                throw new InvalidProgramException($"We expected deployPath to be {deployedGamePath}, but in reality it was {deployedGame.Path}");
            }
            var expectedEntryPointExecutable = EntryPointExecutableFor(gameProgram, config);
            if (entryPointExecutable != expectedEntryPointExecutable)
            {
                throw new InvalidProgramException($"We expected entryPointExecutable to be {expectedEntryPointExecutable}, but in reality it was {entryPointExecutable}");
            }

            Backend.Current.AddAliasDependency(config.Identifier, deployedGamePath);
        }

        return(gameProgram);
    }
Example #18
0
    static void Main()
    {
        BeeRootValue = AsmDefConfigFile.AsmDefDescriptionFor("Unity.Runtime.EntryPoint").Path.Parent.Parent.Combine("bee~");

        Backend.Current.StevedoreSettings = new StevedoreSettings
        {
            // Manifest entries always override artifact IDs hard-coded in Bee
            // Setting EnforceManifest to true will also ensure no artifacts
            // are used without being listed in a manifest.
            EnforceManifest = true,
            Manifest        =
            {
                BeeRootValue.Combine("manifest.stevedore"),
            },
        };

        // When bee needs to run a second time because the Tundra graph has suggested a need to rerun,
        // you cannot use LazyStatics or Statics in cases where you construct a program that gets compiled in the first run.
        // This is because previously bee when it ran a second time would spawn a new process of the buildprogram but in the
        // new bee we actually run it in the same process which means that you need to construct new programs or clear out old state.
        TinyIO         = null;
        UnityTinyBurst = null;

        UnityLowLevel             = null;
        ZeroJobs                  = null;
        ILPostProcessorAssemblies = null;

        ILPostProcessorTool._ilPostProcessorRunnerProgramInternal = null;

        _cache.Clear();
        DotsConfigs.Clear();

        CSharpProgram.DefaultConfig = new CSharpProgramConfiguration(CSharpCodeGen.Release);

        PerConfigBuildSettings = DotsConfigs.MakeConfigs();
        foreach (var rootAssemblyName in PerConfigBuildSettings.Keys)
        {
            AsmDefConfigFile.AsmDefDescriptionFor(rootAssemblyName).IsTinyRoot = true;
        }

        //any asmdef that sits next to a .project file we will consider a tiny game.
        var asmDefDescriptions = AsmDefConfigFile.AssemblyDefinitions.ToArray();
        var burstAsmDef        = asmDefDescriptions.First(d => d.Name == "Unity.Burst");
        var tinyIOAsmDef       = asmDefDescriptions.First(d => d.Name == "Unity.Tiny.IO");

        UnityLowLevel = new DotsRuntimeCSharpProgram($"{LowLevelRoot}/Unity.LowLevel")
        {
            References = { UnsafeUtility.Program },
            Unsafe     = true
        };
        UnityLowLevel.NativeProgram.Libraries.Add(IsLinux, new SystemLibrary("dl"));
        UnityLowLevel.NativeProgram.Libraries.Add(c => c.Platform is AndroidPlatform, new SystemLibrary("log"));

        TinyIO = GetOrMakeDotsRuntimeCSharpProgramFor(tinyIOAsmDef);

        UnityTinyBurst = new DotsRuntimeCSharpProgram($"{LowLevelRoot}/Unity.Tiny.Burst")
        {
            References = { UnityLowLevel },
            Unsafe     = true
        };

        ZeroJobs = new DotsRuntimeCSharpProgram($"{LowLevelRoot}/Unity.ZeroJobs")
        {
            References = { UnityLowLevel, UnityTinyBurst, GetOrMakeDotsRuntimeCSharpProgramFor(burstAsmDef), TinyIO },
            Unsafe     = true
        };

        UnityCompilationPipeline = new DotNetAssembly(
            AsmDefConfigFile.UnityCompilationPipelineAssemblyPath,
            HackedFrameworkToUseForProjectFilesIfNecessary);

        var nunit = new StevedoreArtifact("nunit-framework");

        NUnitLite      = new DotNetAssembly(nunit.Path.Combine("bin", "net40", "nunitlite.dll"), Framework.Framework471);
        NUnitFramework = new DotNetAssembly(nunit.Path.Combine("bin", "net40", "nunit.framework.dll"), Framework.Framework471);

        BurstCompiler.BurstExecutable = GetBurstExecutablePath(burstAsmDef).QuoteForProcessStart();

        var ilPostProcessorPrograms = asmDefDescriptions
                                      .Where(d => d.IsILPostProcessorAssembly)
                                      .Select(GetOrMakeDotsRuntimeCSharpProgramFor);

        ILPostProcessorAssemblies = ilPostProcessorPrograms.Select(p =>
        {
            /*
             * We want to compile the ilpp's for hostdotnet, even though we might be compiling the actual game
             * for something else (e.g. wasm). The ilpp's may reference actual game assemblies, which may have
             * native code. We do not want to set up the native code for those game assemblies for hostdotnet,
             * because a) it makes no sense and b) the native toolchains might not be installed, and it would be
             * dumb to require that to build for an unrelated platform.
             *
             * So, set the NativeProgramConfiguration to null, and set up with that. But first, set the platform,
             * because normally the platform comes from the npc.
             */
            var tmp      = DotsConfigs.HostDotnet;
            tmp.Platform = DotsConfigs.HostDotnet.Platform;
            tmp.NativeProgramConfiguration = null;
            var ret = p.SetupSpecificConfiguration(tmp);
            return(ret);
        })
                                    .ToArray();

        var tinyMainAsmDefs = asmDefDescriptions.Where(a => a.IsTinyRoot);
        var gameAsmDefs     = tinyMainAsmDefs.Union(AsmDefConfigFile.TestableAssemblyDefinitions);

        foreach (var gameAsmdef in gameAsmDefs)
        {
            var gameProgram = GetOrMakeDotsRuntimeCSharpProgramFor(gameAsmdef);
            if (gameProgram.AsmDefDescription.NeedsEntryPointAdded())
            {
                gameProgram.References.Add(
                    GetOrMakeDotsRuntimeCSharpProgramFor(
                        AsmDefConfigFile.AsmDefDescriptionFor("Unity.Runtime.EntryPoint")));
            }
        }
        var gamePrograms = gameAsmDefs.Select(SetupGame).ExcludeNulls().ToArray();


        var vs = new VisualStudioSolution {
            Path = AsmDefConfigFile.UnityProjectPath.Combine($"{AsmDefConfigFile.ProjectName}-Dots.sln").RelativeTo(NPath.CurrentDirectory),
            DefaultSolutionFolderFor = file => (file.Name.Contains("Unity.") || file.Name == "mscorlib") ? "Unity" : ""
        };

        var unityToolsFolder            = "Unity/tools";
        var unityILPostProcessorsFolder = "Unity/ILPostProcessing";

        if (BeeRoot.IsChildOf(AsmDefConfigFile.UnityProjectPath))
        {
            var buildProjRef = new CSharpProjectFileReference("buildprogram.gen.csproj");
            vs.Projects.Add(buildProjRef, unityToolsFolder);
        }
        foreach (var gameProgram in gamePrograms)
        {
            vs.Projects.Add(gameProgram);
        }

        var toolPrograms = new[]
        { TypeRegistrationTool.EntityBuildUtils, TypeRegistrationTool.TypeRegProgram };

        foreach (var p in toolPrograms)
        {
            vs.Projects.Add(p, unityToolsFolder);
        }

        vs.Projects.Add(ILPostProcessorTool.ILPostProcessorRunnerProgram, unityILPostProcessorsFolder);
        foreach (var p in ilPostProcessorPrograms)
        {
            vs.Projects.Add(p, unityILPostProcessorsFolder);
        }

        foreach (var config in PerConfigBuildSettings.SelectMany(entry => entry.Value))
        {
            //we want dotnet to be the default, and we cannot have nice things: https://aras-p.info/blog/2017/03/23/How-does-Visual-Studio-pick-default-config/platform/
            var solutionConfigName = config.Identifier == "dotnet" ? "Debug (dotnet)": config.Identifier;

            vs.Configurations.Add(new SolutionConfiguration(solutionConfigName, (configurations, file) =>
            {
                var firstOrDefault = configurations.FirstOrDefault(c => c == config);
                return(new Tuple <IProjectConfiguration, bool>(
                           firstOrDefault ?? configurations.First(),
                           firstOrDefault != null || toolPrograms.Any(t => t.ProjectFile == file)));
            }));
        }

        VisualStudioSolution = vs;
        EditorToolsBuildProgram.Setup(BeeRoot);

        // Run this before solution setup, to potentially give this a chance to muck with the VisualStudioSolution
        DotsBuildCustomizer.RunAllCustomizers();

        if (!IsRequestedTargetExactlySingleAppSingleConfig())
        {
            Backend.Current.AddAliasDependency("ProjectFiles", vs.Setup());
        }
    }