Ejemplo n.º 1
0
    private static string ComputeCustomLocation()
    {
        string path = null; // Set local il2cpp path here

        if (path != null)
        {
            return(path);
        }

        string envPath = Environment.GetEnvironmentVariable("IL2CPP_FROM_LOCAL"); // Set in CI for testing

        if (envPath != null)
        {
            return(envPath);
        }

        // look for a magic asmdef for devmode
        var asmdef = AsmDefConfigFile.AsmDefDescriptionFor("Il2Cpp.Devmode");

        if (asmdef != null)
        {
            // make sure it's configured
            var il2cppPath = asmdef.Path.Parent.Parent.Parent;
            var exePath    = il2cppPath.Combine("build/deploy/net471/il2cpp.exe");
            if (!exePath.Exists())
            {
                throw new ArgumentException(
                          $"You have an Il2Cpp.Devmode asmdef in a package you have referenced, but we couldn't find an il2cpp.exe at {exePath}.  Either il2cpp isn't actually under devmode (don't reference the package if not), or you didn't build it (run perl build.sh inside PackageSources/il2cpp)");
            }
            return(il2cppPath.ToString());
        }

        return(null);
    }
Ejemplo n.º 2
0
    public void AddPlatformImplementationFor(string baseFeatureAsmDefName, string platformImplAsmDefName)
    {
        if (AsmDefDescription.Name == platformImplAsmDefName)
        {
            return;
        }

        if (AsmDefDescription.References.Any(r => r.Name == baseFeatureAsmDefName))
        {
            var impl = AsmDefConfigFile.CSharpProgramFor(platformImplAsmDefName);
            if (impl == null)
            {
                Console.WriteLine($"Missing assembly for {platformImplAsmDefName}, named in a customizer for {baseFeatureAsmDefName}.  Are you missing a package, or is the customizer in the wrong place?");
                return;
            }
            References.Add(c => impl.IsSupportedFor(c), impl);
        }
    }
Ejemplo n.º 3
0
    //Run ./bee build-lib-webp to compile the webp library located in Unity.Tiny.Image2D.Native.cpp~/libwebp and copy it to Unity.Tiny.Image2D.Authoring/libwebp
    public override void Customize()
    {
        var           asmdefRoot      = AsmDefConfigFile.AsmDefDescriptionFor("Unity.Tiny.Image2D.Native").Directory;
        var           outputDirectory = AsmDefConfigFile.AsmDefDescriptionFor("Unity.Tiny.Image2D.Authoring").Directory;
        NativeProgram WebPLib         = new NativeProgram("libwebp")
        {
            Sources =
            {
                asmdefRoot.Combine("cpp~/libwebp"),
            },
            IncludeDirectories = { asmdefRoot.Combine("cpp~/libwebp") },
            OutputDirectory    = { outputDirectory.Combine("libwebp") }
        };

        DotsRuntimeNativeProgramConfiguration config = DotsConfigs.HostDotnet.NativeProgramConfiguration;
        var builtWebPLib = WebPLib.SetupSpecificConfiguration(config, config.ToolChain.DynamicLibraryFormat);

        Backend.Current.AddAliasDependency("build-lib-webp", builtWebPLib.Path);
    }
Ejemplo n.º 4
0
    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));
    }
    public static Dictionary <string, List <DotsRuntimeCSharpProgramConfiguration> > MakeConfigs()
    {
        var platformList = DotsBuildSystemTargets;

        var settingsDir = new NPath("settings");

        if (settingsDir.Exists())
        {
            foreach (var settingsRelative in settingsDir.Files("*.json"))
            {
                var settingsFile = settingsRelative.MakeAbsolute();
                if (settingsFile.Exists())
                {
                    Backend.Current.RegisterFileInfluencingGraph(settingsFile);
                    var settingsObject = new FriendlyJObject {
                        Content = JObject.Parse(settingsFile.ReadAllText())
                    };

                    if (settingsObject.GetInt("Version", 0) != AsmDefConfigFile.BuildSettingsFileVersion ||
                        AsmDefConfigFile.AsmDefDescriptionFor(settingsObject.GetString("RootAssembly")) == null)
                    {
                        Console.WriteLine($"Found old settings file '{settingsFile}', removing...");
                        settingsFile.Delete();
                        continue;
                    }

                    var id = settingsObject.GetString("PlatformTargetIdentifier");

                    var target = platformList.Single(t => t.Identifier == id);

                    if (!target.ToolChain.CanBuild)
                    {
                        continue;
                    }

                    // Need to know this prior to determining need for burst
                    var mdb = ShouldEnableDevelopmentOptionForSetting("EnableManagedDebugging", new[] { DotsConfiguration.Debug, DotsConfiguration.Develop }, settingsObject);
                    if (!target.ValidateManagedDebugging(ref mdb))
                    {
                        continue;
                    }
                    if (mdb && DotsConfigForSettings(settingsObject, out var codeGen) == DotsConfiguration.Debug && target.ScriptingBackend == ScriptingBackend.TinyIl2cpp)
                    {
                        Errors.PrintWarning("Debug builds with managed debugging are very slow. It's recommended to use the Develop configuration instead.");
                    }

                    var multithreading  = settingsObject.GetBool("EnableMultithreading");
                    var targetUsesBurst = settingsObject.GetBool("EnableBurst");
                    if (!targetUsesBurst && multithreading)
                    {
                        // We currently do not support multithreaded debugging anywhere except .NET Framework and CoreCLR (so, Windows only)
                        // or il2cpp full profile
                        bool isFullIl2cpp = target.ScriptingBackend == ScriptingBackend.TinyIl2cpp && mdb;
                        bool isWindows    = target.ToolChain.Platform is WindowsPlatform;
                        if (!(isFullIl2cpp || isWindows))
                        {
                            Errors.PrintWarning($"BuildConfiguration '{settingsFile.FileNameWithoutExtension}' " +
                                                $"specified 'EnableBurst=False', but 'Multithreading=True'. Multithreading requires Burst, therefore enabling Burst.");
                            targetUsesBurst = true;
                        }
                    }

                    var dotsCfg        = DotsConfigForSettings(settingsObject, out var codegen);
                    var enableProfiler = ShouldEnableDevelopmentOptionForSetting("EnableProfiler", new [] { DotsConfiguration.Develop }, settingsObject);
                    var enableUnityCollectionsChecks = ShouldEnableDevelopmentOptionForSetting("EnableSafetyChecks", new[] { DotsConfiguration.Debug, DotsConfiguration.Develop }, settingsObject);

                    if (!target.CanUseBurst && targetUsesBurst)
                    {
                        Console.WriteLine($"Warning: BuildConfiguration '{settingsFile.FileNameWithoutExtension}' " +
                                          $"specified 'EnableBurst', but target ({target.Identifier}) does not support burst yet. Not using burst.");
                        targetUsesBurst = false;
                    }

                    // Workaround to disable burst in web debug builds since it will fail to compile
                    // https://unity3d.atlassian.net/browse/DOTSR-1886
                    if (targetUsesBurst && target is DotsWebTarget && codegen == CSharpCodeGen.Debug)
                    {
                        Console.WriteLine($"Warning: Web currently does not support building in debug configuration with Burst. Disabling burst....");
                        targetUsesBurst = false;
                    }

                    var waitForManagedDebugger = settingsObject.GetBool("WaitForManagedDebugger");

                    var    rootAssembly   = settingsObject.GetString("RootAssembly");
                    string finalOutputDir = null;
                    if (settingsObject.Content.TryGetValue("FinalOutputDirectory", out var finalOutputToken))
                    {
                        finalOutputDir = finalOutputToken.Value <string>();
                    }

                    var defines = new List <string>();
                    if (settingsObject.Content.TryGetValue("ScriptingDefines", out var definesJToken))
                    {
                        defines = ((JArray)definesJToken).Select(token => token.Value <string>()).ToList();
                    }

                    if (!PerConfigBuildSettings.ContainsKey(rootAssembly))
                    {
                        PerConfigBuildSettings[rootAssembly] = new List <DotsRuntimeCSharpProgramConfiguration>();
                    }

                    var identifier = settingsFile.FileNameWithoutExtension;
                    do
                    {
                        PerConfigBuildSettings[rootAssembly]
                        .Add(
                            target.CustomizeConfigForSettings(new DotsRuntimeCSharpProgramConfiguration(
                                                                  csharpCodegen: codegen,
                                                                  cppCodegen: codegen == CSharpCodeGen.Debug ? CodeGen.Debug : CodeGen.Release,
                                                                  nativeToolchain: target.ToolChain,
                                                                  scriptingBackend: target.ScriptingBackend,
                                                                  targetFramework: target.TargetFramework,
                                                                  identifier: identifier,
                                                                  enableUnityCollectionsChecks: enableUnityCollectionsChecks,
                                                                  enableManagedDebugging: mdb,
                                                                  waitForManagedDebugger: waitForManagedDebugger,
                                                                  multiThreadedJobs: multithreading,
                                                                  dotsConfiguration: dotsCfg,
                                                                  enableProfiler: enableProfiler,
                                                                  useBurst: targetUsesBurst,
                                                                  defines: defines,
                                                                  finalOutputDirectory: finalOutputDir),
                                                              settingsObject));

                        //We have to introduce the concept of "complementary targets" to accommodate building "fat" binaries on Android,
                        //for both armv7 and arm64 architectures. This means we have to build two copies of the final binaries, and then do one
                        //packaging step to package both steps into a single apk. But also, since C# code is allowed to do #if UNITY_DOTSRUNTIME64
                        //(and indeed we need that ability for the static type registry to generate correct sizes of things), we need to compile
                        //two sets of c# assemblies, one per architecture, and run il2cpp and burst on each one separately, in order to produce
                        //these two sets of final binaries.
                        //For that purpose, we associate a second DotsRuntimeCSharpProgramConfiguration (known as the complementary target) to
                        //specify the build for the other architecture we wish to compile against, and we do all the building steps up to the final
                        //packaging step for that config as well as the main one. We skip the final packaging step for the complementary config,
                        //and make the packaging step for the main config consume both sets of binaries.
                        //This is a crazy scheme, and we theorize and hope that when we adopt the incremental buildpipeline, we will be able
                        //to use their concept of per-platform custom graph build steps to make this be more reasonable.
                        target = target.ComplementaryTarget;

                        //We use "identifier" as a directory name for all intermediate files.
                        //For complementary target these files will be generated in "target.Identifier" subdirectory.
                        //So for example in case of arm64 complemenary target a path would be
                        //"{target.Identifiler}/android_complementary_arm64".
                        if (target != null)
                        {
                            identifier += "/" + target.Identifier;
                        }
                    } while (target != null);
                }
            }
        }

        return(PerConfigBuildSettings);
    }
        private NPath GenerateXCodeProject(NPath mainLibPath)
        {
            var outputPath      = mainLibPath.Parent;
            var iosPlatformPath = AsmDefConfigFile.AsmDefDescriptionFor("Unity.Build.iOS.DotsRuntime").Path.Parent;
            var xcodeSrcPath    = iosPlatformPath.Combine(TinyProjectName + "~");
            var xcodeprojPath   = outputPath.Combine($"{TinyProjectName}.xcodeproj");

            // copy and patch pbxproj file
            var pbxPath         = xcodeprojPath.Combine("project.pbxproj");
            var pbxTemplatePath = xcodeSrcPath.Combine($"{TinyProjectName}.xcodeproj", "project.pbxproj");
            var result          = SetupXCodeProject(pbxTemplatePath);

            Backend.Current.AddWriteTextAction(pbxPath, result);
            m_projectFiles.Add(pbxPath);
            m_projectFiles.Add(mainLibPath);

            // copy and patch xcscheme file
            var xcschemePath         = xcodeprojPath.Combine("xcshareddata", "xcschemes", "Tiny-iPhone.xcscheme");
            var xcschemeTemplatePath = xcodeSrcPath.Combine($"{TinyProjectName}.xcodeproj", "xcshareddata", "xcschemes", "Tiny-iPhone.xcscheme");

            result = SetupXcScheme(xcschemeTemplatePath, m_config == DotsConfiguration.Release);
            Backend.Current.AddWriteTextAction(xcschemePath, result);
            m_projectFiles.Add(xcschemePath);

            // copy and patch Info.plist file
            var plistPath         = outputPath.Combine("Sources", "Info.plist");
            var plistTemplatePath = xcodeSrcPath.Combine("Sources", "Info.plist");

            result = SetupInfoPlist(plistTemplatePath);
            Backend.Current.AddWriteTextAction(plistPath, result);
            m_projectFiles.Add(plistPath);

            // copy xcodeproj files
            foreach (var r in xcodeSrcPath.Files(true))
            {
                if (r.Extension != "pbxproj" && r.Extension != "xcscheme" && r.FileName != "Info.plist" && !r.HasDirectory("AppIcon.appiconset"))
                {
                    var destPath = outputPath.Combine(r.RelativeTo(xcodeSrcPath));
                    destPath = CopyTool.Instance().Setup(destPath, r);
                    m_projectFiles.Add(destPath);
                }
            }

            // copy icon files
            var icons = IOSAppToolchain.Config.Icons;

            CopyIcon(xcodeSrcPath, outputPath, "Icon-iPhone-120.png", icons.iPhone2x);
            CopyIcon(xcodeSrcPath, outputPath, "Icon-iPhone-180.png", icons.iPhone3x);
            CopyIcon(xcodeSrcPath, outputPath, "Icon-iPad-152.png", icons.iPad2x);
            CopyIcon(xcodeSrcPath, outputPath, "Icon-iPad-167.png", icons.iPadPro2x);
            CopyIcon(xcodeSrcPath, outputPath, "AppStore-1024.png", icons.AppStore);
            CopyIcon(xcodeSrcPath, outputPath, "Contents.json", null);

            for (int i = 0; i < Deployables.Length; ++i)
            {
                var r = Deployables[i];
                if (r is DeployableFile && r.Path.FileName == "testconfig.json")
                {
                    var path = CopyTool.Instance().Setup(outputPath.Combine(r.Path.FileName), r.Path);
                    m_projectFiles.Add(path);
                    break;
                }
            }
            return(pbxPath);
        }
Ejemplo n.º 7
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());
        }
    }
Ejemplo n.º 8
0
    public AsmDefCSharpProgram(AsmDefDescription asmDefDescription)
        : base(asmDefDescription.Directory,
               asmDefDescription.IncludedAsmRefs.Select(asmref => asmref.Path.Parent),
               deferConstruction: true)
    {
        AsmDefDescription = asmDefDescription;

        var asmDefReferences = AsmDefDescription.References.Select(asmDefDescription1 => BuildProgram.GetOrMakeDotsRuntimeCSharpProgramFor(asmDefDescription1)).ToList();
        var isExe            = asmDefDescription.DefineConstraints.Contains("UNITY_DOTS_ENTRYPOINT") || asmDefDescription.Name.EndsWith(".Tests");

        Construct(asmDefDescription.Name, isExe);

        ProjectFile.AdditionalFiles.Add(asmDefDescription.Path);

        IncludePlatforms = AsmDefDescription.IncludePlatforms;
        ExcludePlatforms = AsmDefDescription.ExcludePlatforms;
        Unsafe           = AsmDefDescription.AllowUnsafeCode;
        References.Add(config =>
        {
            if (config is DotsRuntimeCSharpProgramConfiguration dotsConfig)
            {
                if (dotsConfig.TargetFramework == TargetFramework.Tiny)
                {
                    return(asmDefReferences.Where(rp => rp.IsSupportedFor(dotsConfig) && !IncompatibleTinyBCLAsmDefs.Contains(rp.FileName)));
                }
                else
                {
                    return(asmDefReferences.Where(rp => rp.IsSupportedFor(dotsConfig)));
                }
            }

            //this codepath will be hit for the bindgem invocation
            return(asmDefReferences);
        });

        if (AsmDefDescription.IsTinyRoot || isExe)
        {
            AsmDefCSharpProgramCustomizer.RunAllAddPlatformImplementationReferences(this);
        }

        if (BuildProgram.UnityTinyBurst != null)
        {
            References.Add(BuildProgram.UnityTinyBurst);
        }
        if (BuildProgram.ZeroJobs != null)
        {
            References.Add(BuildProgram.ZeroJobs);
        }
        if (BuildProgram.UnityLowLevel != null)
        {
            References.Add(BuildProgram.UnityLowLevel);
        }
        if (BuildProgram.TinyIO != null)
        {
            References.Add(BuildProgram.TinyIO);
        }

        // Add in any precompiled references found in the asmdef directory or sub-directory
        foreach (var pcr in asmDefDescription.PrecompiledReferences)
        {
            var files = asmDefDescription.Path.Parent.Files(pcr, true);
            if (files.Any())
            {
                References.Add(files);
            }
        }

        if (IsTestAssembly)
        {
            var nunitLiteMain = BuildProgram.BeeRoot.Combine("CSharpSupport/NUnitLiteMain.cs");
            Sources.Add(nunitLiteMain);

            // Setup for IL2CPP
            var tinyTestFramework = BuildProgram.BeeRoot.Parent.Combine("TinyTestFramework");
            Sources.Add(c => ((DotsRuntimeCSharpProgramConfiguration)c).ScriptingBackend == ScriptingBackend.TinyIl2cpp || ((DotsRuntimeCSharpProgramConfiguration)c).TargetFramework == TargetFramework.Tiny, tinyTestFramework);
            Defines.Add(c => ((DotsRuntimeCSharpProgramConfiguration)c).ScriptingBackend == ScriptingBackend.TinyIl2cpp || ((DotsRuntimeCSharpProgramConfiguration)c).TargetFramework == TargetFramework.Tiny, "UNITY_PORTABLE_TEST_RUNNER");

            // Setup for dotnet
            References.Add(c => ((DotsRuntimeCSharpProgramConfiguration)c).ScriptingBackend == ScriptingBackend.Dotnet && ((DotsRuntimeCSharpProgramConfiguration)c).TargetFramework != TargetFramework.Tiny, BuildProgram.NUnitFramework);
            ProjectFile.AddCustomLinkRoot(nunitLiteMain.Parent, "TestRunner");
            References.Add(c => ((DotsRuntimeCSharpProgramConfiguration)c).ScriptingBackend == ScriptingBackend.Dotnet && ((DotsRuntimeCSharpProgramConfiguration)c).TargetFramework != TargetFramework.Tiny, BuildProgram.NUnitLite);

            // General setup
            References.Add(BuildProgram.GetOrMakeDotsRuntimeCSharpProgramFor(AsmDefConfigFile.AsmDefDescriptionFor("Unity.Entities")));
            References.Add(BuildProgram.GetOrMakeDotsRuntimeCSharpProgramFor(AsmDefConfigFile.AsmDefDescriptionFor("Unity.Tiny.Core")));
            References.Add(BuildProgram.GetOrMakeDotsRuntimeCSharpProgramFor(AsmDefConfigFile.AsmDefDescriptionFor("Unity.Tiny.UnityInstance")));
            References.Add(BuildProgram.GetOrMakeDotsRuntimeCSharpProgramFor(AsmDefConfigFile.AsmDefDescriptionFor("Unity.Collections")));
        }
        else if (IsILPostProcessorAssembly)
        {
            References.Add(BuildProgram.UnityCompilationPipeline);
            References.Add(MonoCecil.Paths);
            References.Add(Il2Cpp.Distribution.Path.Combine("build/deploy/net471/Unity.Cecil.Awesome.dll"));
        }
    }
Ejemplo n.º 9
0
        private NPath PackageApp(NPath buildPath, NPath mainLibPath)
        {
            var deployedPath = buildPath.Combine(m_gameName + ".apk");

            if (m_apkToolchain == null)
            {
                Console.WriteLine($"Error: not Android APK toolchain");
                return(deployedPath);
            }

            var gradleProjectPath = mainLibPath.Parent.Parent.Parent.Parent.Parent;
            var pathToRoot        = new NPath(string.Concat(Enumerable.Repeat("../", gradleProjectPath.Depth)));
            var apkSrcPath        = AsmDefConfigFile.AsmDefDescriptionFor("Unity.Platforms.Android").Path.Parent.Combine("AndroidProjectTemplate~/");

            var javaLaunchPath         = m_apkToolchain.JavaPath.Combine("bin").Combine("java");
            var gradleLaunchPath       = m_apkToolchain.GetGradleLaunchJarPath();
            var releaseApk             = m_codeGen == CodeGen.Release;
            var gradleCommand          = releaseApk ? "assembleRelease" : "assembleDebug";
            var deleteCommand          = Unity.BuildTools.HostPlatform.IsWindows ? $"del /f /q {deployedPath.InQuotes(SlashMode.Native)} 2> nul" : $"rm -f {deployedPath.InQuotes(SlashMode.Native)}";
            var gradleExecutableString = $"{deleteCommand} && cd {gradleProjectPath.InQuotes()} && {javaLaunchPath.InQuotes()} -classpath {gradleLaunchPath.InQuotes()} org.gradle.launcher.GradleMain {gradleCommand} && cd {pathToRoot.InQuotes()}";

            var apkPath = gradleProjectPath.Combine("build/outputs/apk").Combine(releaseApk ? "release/gradle-release.apk" : "debug/gradle-debug.apk");

            Backend.Current.AddAction(
                actionName: "Build Gradle project",
                targetFiles: new[] { apkPath },
                inputs: m_apkToolchain.RequiredArtifacts.Append(mainLibPath).Concat(m_supportFiles.Select(d => d.Path)).ToArray(),
                executableStringFor: gradleExecutableString,
                commandLineArguments: Array.Empty <string>(),
                allowUnexpectedOutput: false,
                allowedOutputSubstrings: new[] { ":*", "BUILD SUCCESSFUL in *" }
                );

            var templateStrings = new Dictionary <string, string>
            {
                { "**TINYNAME**", m_gameName.Replace("-", "").ToLower() },
                { "**GAMENAME**", m_gameName },
            };

            // copy and patch project files
            foreach (var r in apkSrcPath.Files(true))
            {
                var destPath = gradleProjectPath.Combine(r.RelativeTo(apkSrcPath));
                if (r.Extension == "template")
                {
                    destPath = destPath.ChangeExtension("");
                    var code = r.ReadAllText();
                    foreach (var t in templateStrings)
                    {
                        if (code.IndexOf(t.Key) != -1)
                        {
                            code = code.Replace(t.Key, t.Value);
                        }
                    }
                    Backend.Current.AddWriteTextAction(destPath, code);
                }
                else
                {
                    destPath = CopyTool.Instance().Setup(destPath, r);
                }
                Backend.Current.AddDependency(apkPath, destPath);
            }

            var localProperties = new StringBuilder();

            localProperties.AppendLine($"sdk.dir={m_apkToolchain.SdkPath}");
            localProperties.AppendLine($"ndk.dir={m_apkToolchain.Sdk.Path.MakeAbsolute()}");
            var localPropertiesPath = gradleProjectPath.Combine("local.properties");

            Backend.Current.AddWriteTextAction(localPropertiesPath, localProperties.ToString());
            Backend.Current.AddDependency(apkPath, localPropertiesPath);

            // copy additional resources and Data files
            // TODO: better to use move from main lib directory
            foreach (var r in m_supportFiles)
            {
                var targetAssetPath = gradleProjectPath.Combine("src/main/assets");
                if (r.Path.FileName == "testconfig.json")
                {
                    targetAssetPath = buildPath.Combine(r.Path.FileName);
                }
                else if (r is DeployableFile && (r as DeployableFile).RelativeDeployPath != null)
                {
                    targetAssetPath = targetAssetPath.Combine((r as DeployableFile).RelativeDeployPath);
                }
                else
                {
                    targetAssetPath = targetAssetPath.Combine(r.Path.FileName);
                }
                Backend.Current.AddDependency(apkPath, CopyTool.Instance().Setup(targetAssetPath, r.Path));
            }

            return(CopyTool.Instance().Setup(deployedPath, apkPath));
        }
Ejemplo n.º 10
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());
        }
    }
Ejemplo n.º 11
0
        public NPath PackageApp(NPath buildPath, NPath mainLibPath)
        {
            if (m_iosAppToolchain == null)
            {
                Console.WriteLine("Error: not IOS App toolchain");
                return(mainLibPath);
            }

            var iosPlatformPath  = AsmDefConfigFile.AsmDefDescriptionFor("Unity.Platforms.iOS").Path.Parent;
            var xcodeProjectPath = mainLibPath.Parent;
            var xcodeSrcPath     = iosPlatformPath.Combine(TinyProjectName + "~");
            var xcodeprojPath    = xcodeProjectPath.Combine($"{TinyProjectName}.xcodeproj");

            // copy and patch pbxproj file
            var pbxPath            = xcodeprojPath.Combine("project.pbxproj");
            var pbxTemplatePath    = xcodeSrcPath.Combine($"{TinyProjectName}.xcodeproj", "project.pbxproj");
            var exportManifestPath = new NPath(m_gameName).Combine("export.manifest");
            var result             = SetupXCodeProject(pbxTemplatePath, exportManifestPath.FileExists());

            Backend.Current.AddWriteTextAction(pbxPath, result);
            Backend.Current.AddDependency(pbxPath, mainLibPath);

            // copy and patch Info.plist file
            var plistPath         = xcodeProjectPath.Combine("Sources", "Info.plist");
            var plistTemplatePath = xcodeSrcPath.Combine("Sources", "Info.plist");

            result = SetupInfoPlist(plistTemplatePath);
            Backend.Current.AddWriteTextAction(plistPath, result);
            Backend.Current.AddDependency(pbxPath, plistPath);

            // copy xcodeproj files
            foreach (var r in xcodeSrcPath.Files(true))
            {
                if (r.Extension != "pbxproj" && r.FileName != "Info.plist")
                {
                    var destPath = xcodeProjectPath.Combine(r.RelativeTo(xcodeSrcPath));
                    destPath = CopyTool.Instance().Setup(destPath, r);
                    Backend.Current.AddDependency(pbxPath, destPath);
                }
            }

            foreach (var r in m_supportFiles)
            {
                if (r.Path.FileName == "testconfig.json")
                {
                    Backend.Current.AddDependency(pbxPath, CopyTool.Instance().Setup(buildPath.Combine(r.Path.FileName), r.Path));
                    break;
                }
            }

            // TODO probably it is required to keep previous project since it can be modified by user
            var outputPath = buildPath.Combine($"{m_gameName}");

            Console.WriteLine($"Move project to {outputPath}");
            Backend.Current.AddAction(
                actionName: "Open XCode project folder",
                targetFiles: new[] { outputPath },
                inputs: new[] { pbxPath },
                executableStringFor: $"rm -rf {outputPath} && mv {xcodeProjectPath} {outputPath} && open {outputPath}",
                commandLineArguments: Array.Empty <string>(),
                allowUnexpectedOutput: true
                );

            return(outputPath);
        }
        private void GenerateGradleProject(NPath gradleProjectPath)
        {
            var gradleSrcPath = AsmDefConfigFile.AsmDefDescriptionFor("Unity.Build.Android.DotsRuntime").Path.Parent.Combine("AndroidProjectTemplate~/");

            var hasGradleDependencies = false;
            var gradleDependencies    = new StringBuilder();

            gradleDependencies.AppendLine("    dependencies {");
            var hasKotlin = false;

            foreach (var d in Deployables.Where(d => (d is DeployableFile)))
            {
                var f = d as DeployableFile;
                if (f.Path.Extension == "aar" || f.Path.Extension == "jar")
                {
                    gradleDependencies.AppendLine($"        compile(name:'{f.Path.FileNameWithoutExtension}', ext:'{f.Path.Extension}')");
                    hasGradleDependencies = true;
                }
                else if (f.Path.Extension == "kt")
                {
                    hasKotlin = true;
                }
            }
            if (hasGradleDependencies)
            {
                gradleDependencies.AppendLine("    }");
            }
            else
            {
                gradleDependencies.Clear();
            }

            var kotlinClassPath = hasKotlin ? "        classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.11'" : "";
            var kotlinPlugin    = hasKotlin ? "apply plugin: 'kotlin-android'" : "";

            var  loadLibraries = new StringBuilder();
            bool useStaticLib  = Deployables.FirstOrDefault(l => l.ToString().Contains("lib_unity_tiny_android.so")) == default(IDeployable);

            if (useStaticLib)
            {
                loadLibraries.AppendLine($"        System.loadLibrary(\"{m_gameName}\");");
            }
            else
            {
                var rx = new Regex(@".*lib([\w\d_]+)\.so", RegexOptions.Compiled);
                foreach (var l in Deployables)
                {
                    var match = rx.Match(l.ToString());
                    if (match.Success)
                    {
                        loadLibraries.AppendLine($"        System.loadLibrary(\"{match.Groups[1].Value}\");");
                    }
                }
            }

            String abiFilters = "";

            if (AndroidApkToolchain.Config.Architectures.Architectures == AndroidArchitecture.ARM64)
            {
                abiFilters = "'arm64-v8a'";
            }
            else if (AndroidApkToolchain.Config.Architectures.Architectures == AndroidArchitecture.ARMv7)
            {
                abiFilters = "'armeabi-v7a'";
            }
            else if (AndroidApkToolchain.IsFatApk)
            {
                abiFilters = "'armeabi-v7a', 'arm64-v8a'";
            }
            else // shouldn't happen
            {
                Console.WriteLine($"Tiny android toolchain doesn't support {AndroidApkToolchain.Config.Architectures.Architectures.ToString()} architectures");
            }

            // Android docs say "density" value was added in API level 17, but it doesn't compile with target SDK level lower than 24.
            string configChanges         = ((int)AndroidApkToolchain.Config.APILevels.ResolvedTargetAPILevel > 23) ? AndroidConfigChanges + "|density" : AndroidConfigChanges;
            var    useKeystore           = BuildConfiguration.HasComponent <AndroidKeystore>();
            var    renderOutsideSafeArea = BuildConfiguration.HasComponent <AndroidRenderOutsideSafeArea>();

            var icons                         = AndroidApkToolchain.Config.Icons;
            var hasBackground                 = icons.Icons.Any(i => !String.IsNullOrEmpty(i.Background));
            var hasCustomIcons                = hasBackground || icons.Icons.Any(i => !String.IsNullOrEmpty(i.Foreground) || !String.IsNullOrEmpty(i.Legacy));
            var version                       = AndroidApkToolchain.Config.Settings.Version;
            var versionFieldCount             = version.Revision > 0 ? 4 : 3;
            var maxRatio                      = AndroidApkToolchain.Config.AspectRatio.GetMaxAspectRatio(AndroidApkToolchain.Config.APILevels.ResolvedTargetAPILevel);
            var additionalApplicationMetadata = "";
            var additionalPermissions         = "";
            var additionalFeatures            = "";

            if (!String.IsNullOrEmpty(maxRatio))
            {
                additionalApplicationMetadata += GetMetaDataString("android.max_aspect", maxRatio);
            }
            if (BuildConfiguration.HasComponent <ARCoreSettings>())
            {
                additionalPermissions += GetPermissionString("android.permission.CAMERA");
                if (AndroidApkToolchain.Config.ARCore.Requirement == Requirement.Optional)
                {
                    additionalApplicationMetadata += "\n" + GetMetaDataString("com.google.ar.core", "optional");
                }
                else
                {
                    additionalApplicationMetadata += "\n" + GetMetaDataString("com.google.ar.core", "required");
                    additionalFeatures            += GetFeatureString("android.hardware.camera.ar", true);
                }
                if (AndroidApkToolchain.Config.ARCore.DepthSupport == Requirement.Required)
                {
                    additionalFeatures += "\n" + GetFeatureString("com.google.ar.core.depth", true);
                }
            }
            var templateStrings = new Dictionary <string, string>
            {
                { "**LOADLIBRARIES**", loadLibraries.ToString() },
                { "**PACKAGENAME**", AndroidApkToolchain.Config.Identifier.PackageName },
                { "**PRODUCTNAME**", AndroidApkToolchain.Config.Settings.ProductName },
                { "**VERSIONNAME**", version.ToString(versionFieldCount) },
                { "**VERSIONCODE**", AndroidApkToolchain.Config.VersionCode.VersionCode.ToString() },
                { "**ORIENTATION**", GetOrientationAttr() },
                { "**INSTALLLOCATION**", AndroidApkToolchain.Config.InstallLocation?.PreferredInstallLocationAsString() },
                { "**CUTOUTMODE**", AndroidRenderOutsideSafeArea.CutoutMode(renderOutsideSafeArea) },
                { "**NOTCHCONFIG**", AndroidRenderOutsideSafeArea.NotchConfig(renderOutsideSafeArea) },
                { "**NOTCHSUPPORT**", AndroidRenderOutsideSafeArea.NotchSupport(renderOutsideSafeArea) },
                { "**GAMENAME**", m_gameName },
                { "**MINSDKVERSION**", ((int)AndroidApkToolchain.Config.APILevels.MinAPILevel).ToString() },
                { "**TARGETSDKVERSION**", ((int)AndroidApkToolchain.Config.APILevels.ResolvedTargetAPILevel).ToString() },
                { "**CONFIGCHANGES**", configChanges },
                { "**ACTIVITY_ASPECT**", String.IsNullOrEmpty(maxRatio) ? "" : $"android:maxAspectRatio=\"{maxRatio}\"" },
                { "**ADDITIONAL_APPLICATION_METADATA**", additionalApplicationMetadata },
                { "**ADDITIONAL_PERMISSIONS**", additionalPermissions },
                { "**ADDITIONAL_FEATURES**", additionalFeatures },
                { "**ABIFILTERS**", abiFilters },
                { "**SIGN**", AndroidApkToolchain.Config.Keystore.GetSigningConfigs(useKeystore) },
                { "**SIGNCONFIG**", AndroidApkToolchain.Config.Keystore.GetSigningConfig(useKeystore) },
                { "**DEPENDENCIES**", gradleDependencies.ToString() },
                { "**KOTLINCLASSPATH**", kotlinClassPath },
                { "**KOTLINPLUGIN**", kotlinPlugin },
                { "**ALLOWED_PORTRAIT**", AndroidApkToolchain.AllowedOrientationPortrait ? "true" : "false" },
                { "**ALLOWED_REVERSE_PORTRAIT**", AndroidApkToolchain.AllowedOrientationReversePortrait ? "true" : "false" },
                { "**ALLOWED_LANDSCAPE**", AndroidApkToolchain.AllowedOrientationLandscape ? "true" : "false" },
                { "**ALLOWED_REVERSE_LANDSCAPE**", AndroidApkToolchain.AllowedOrientationReverseLandscape ? "true" : "false" },
                { "**BACKGROUND_PATH**", hasBackground ? "mipmap" : "drawable" }
            };

            // copy icon files
            if (hasCustomIcons)
            {
                for (int i = 0; i < icons.Icons.Length; ++i)
                {
                    var dpi = ((ScreenDPI)i).ToString().ToLower();
                    if (AndroidApkToolchain.Config.APILevels.TargetSDKSupportsAdaptiveIcons)
                    {
                        CopyIcon(gradleProjectPath, dpi, "ic_launcher_foreground.png", icons.Icons[i].Foreground);
                        CopyIcon(gradleProjectPath, dpi, "ic_launcher_background.png", icons.Icons[i].Background);
                    }
                    CopyIcon(gradleProjectPath, dpi, "app_icon.png", icons.Icons[i].Legacy);
                }
            }

            // copy and patch project files
            var apiRx = new Regex(@".+res[\\|\/].+-v([0-9]+)$", RegexOptions.Compiled);

            foreach (var r in gradleSrcPath.Files(true))
            {
                if ((hasCustomIcons && r.HasDirectory("mipmap-mdpi")) ||
                    (hasBackground && r.HasDirectory("drawable"))) // skipping icons files if there are custom ones
                {
                    continue;
                }
                if (!AndroidApkToolchain.Config.APILevels.TargetSDKSupportsAdaptiveIcons && r.FileName.StartsWith("ic_launcher_"))
                {
                    continue;
                }
                var match = apiRx.Match(r.Parent.ToString());
                if (match.Success)
                {
                    var api = Int32.Parse(match.Groups[1].Value);
                    if (api > (int)AndroidApkToolchain.Config.APILevels.ResolvedTargetAPILevel)
                    {
                        continue;
                    }
                }

                var destPath = gradleProjectPath.Combine(r.RelativeTo(gradleSrcPath));
                if (r.Extension == "template")
                {
                    destPath = destPath.ChangeExtension("");
                    var code = r.ReadAllText();
                    foreach (var t in templateStrings)
                    {
                        if (code.IndexOf(t.Key) != -1)
                        {
                            code = code.Replace(t.Key, t.Value);
                        }
                    }
                    Backend.Current.AddWriteTextAction(destPath, code);
                }
                else
                {
                    destPath = CopyTool.Instance().Setup(destPath, r);
                }
                m_projectFiles.Add(destPath);
            }

            var localProperties = new StringBuilder();

            localProperties.AppendLine($"sdk.dir={new NPath(AndroidApkToolchain.Config.ExternalTools.SdkPath).ToString()}");
            localProperties.AppendLine($"ndk.dir={new NPath(AndroidApkToolchain.Config.ExternalTools.NdkPath).ToString()}");
            var localPropertiesPath = gradleProjectPath.Combine("local.properties");

            Backend.Current.AddWriteTextAction(localPropertiesPath, localProperties.ToString());
            m_projectFiles.Add(localPropertiesPath);
        }
Ejemplo n.º 13
0
    public AsmDefCSharpProgram(AsmDefDescription asmDefDescription)
        : base(asmDefDescription.Directory,
               asmDefDescription.IncludedAsmRefs.Select(asmref => asmref.Path.Parent),
               deferConstruction: true)
    {
        AsmDefDescription = asmDefDescription;

        var asmDefReferences = AsmDefDescription.References.Select(BuildProgram.GetOrMakeDotsRuntimeCSharpProgramFor).ToList();

        ReferencedPrograms = asmDefReferences.Where(r => !IncompatibleDotRuntimeAsmDefs.Contains(r.AsmDefDescription.Name)).ToArray();

        var isTinyRoot = AsmDefDescription.NamedReferences.Contains("Unity.Tiny.Main") ||
                         asmDefDescription.Path.Parent.Files("*.project").Any();

        var isExe = asmDefDescription.DefineConstraints.Contains("UNITY_DOTS_ENTRYPOINT") || asmDefDescription.Name.EndsWith(".Tests");

        Construct(asmDefDescription.Name, isExe);

        ProjectFile.AdditionalFiles.Add(asmDefDescription.Path);

        IncludePlatforms = AsmDefDescription.IncludePlatforms;
        ExcludePlatforms = AsmDefDescription.ExcludePlatforms;
        Unsafe           = AsmDefDescription.Unsafe;
        References.Add(config =>
        {
            if (config is DotsRuntimeCSharpProgramConfiguration dotsConfig)
            {
                return(ReferencedPrograms.Where(rp => rp.IsSupportedFor(dotsConfig)));
            }

            //this codepath will be hit for the bindgem invocation
            return(ReferencedPrograms);
        });

        if (isTinyRoot || isExe)
        {
            AsmDefCSharpProgramCustomizer.RunAllAddPlatformImplementationReferences(this);
        }

        if (BuildProgram.ZeroJobs != null)
        {
            References.Add(BuildProgram.ZeroJobs);
        }
        if (BuildProgram.UnityLowLevel != null)
        {
            References.Add(BuildProgram.UnityLowLevel);
        }

        if (IsTestAssembly)
        {
            References.Add(BuildProgram.NUnitFramework);
            var nunitLiteMain = BuildProgram.BeeRoot.Combine("CSharpSupport/NUnitLiteMain.cs");
            Sources.Add(nunitLiteMain);
            ProjectFile.AddCustomLinkRoot(nunitLiteMain.Parent, "TestRunner");
            References.Add(BuildProgram.NUnitLite);
            References.Add(BuildProgram.GetOrMakeDotsRuntimeCSharpProgramFor(AsmDefConfigFile.AsmDefDescriptionFor("Unity.Entities")));
        }
        else if (IsILPostProcessorAssembly)
        {
            References.Add(BuildProgram.UnityCompilationPipeline);
            References.Add(StevedoreUnityCecil.Paths);
        }
    }