Пример #1
0
    private static IEnumerable <NPath> TargetPathsFor(NPath targetDirectory, DotNetAssembly inputAssembly)
    {
        yield return(targetDirectory.Combine(inputAssembly.Path.FileName));

        if (inputAssembly.DebugSymbolPath != null)
        {
            yield return(targetDirectory.Combine(inputAssembly.DebugSymbolPath.FileName));
        }
    }
        // Ajout de l'élément
        /// <summary>
        /// Alerts listeners that a rule has been used.
        /// </summary>
        /// <param name="e">An ElementAddedEventArgs that contains the event data.</param>
        public override void ElementAdded(ElementAddedEventArgs e)
        {
            #region Condition

            // Test the element
            DotnetAssemblyShape shape = e.ModelElement as DotnetAssemblyShape;
            if (shape == null)
            {
                return;
            }

            // Teste qu'elle est la source qui a générée l'événement
            if (shape.Store.TransactionManager.CurrentTransaction.TopLevelTransaction.IsSerializing ||
                shape.Store.InUndoRedoOrRollback)
            {
                return;
            }

            #endregion

            #region Traitement

            DotNetAssembly externalAssembly = shape.ModelElement as DotNetAssembly;
            if (externalAssembly != null && !String.IsNullOrEmpty(externalAssembly.FullName))
            {
                return;
            }

            using (
                Transaction transaction =
                    externalAssembly.Store.TransactionManager.BeginTransaction("Retrieve assembly infos"))
            {
                try
                {
                    IAssemblySelectorDialog selector = ServiceLocator.Instance.GetService <IAssemblySelectorDialog>();
                    if (selector.ShowDialog(1))
                    {
                        externalAssembly.InitFromAssembly(selector.SelectedAssemblies[0], true);
                        transaction.Commit();
                    }
                }
                catch (Exception ex)
                {
                    ILogger logger = ServiceLocator.Instance.GetService <ILogger>();
                    if (logger != null)
                    {
                        logger.WriteError("Import assembly", "Reflection error", ex);
                    }
                    transaction.Rollback();
                }
            }

            #endregion
        }
Пример #3
0
        private NPath[] SetupIL2CPPConversion(NPath[] linkerOutputFiles, NPath il2cppdata_destinationdir)
        {
            var il2cpp =
                new DotNetAssembly(
                    string.IsNullOrEmpty(CustomIL2CPPLocation) ?
                    $"{EditorApplication.applicationContentsPath}/il2cpp/build/deploy/net471/il2cpp.exe" :
                    $"{CustomIL2CPPLocation}/build/deploy/net471/il2cpp.exe",
                    Framework.Framework471);
            var netCoreRunRuntime = DotNetRuntime.FindFor(il2cpp); //NetCoreRunRuntime.FromSteve;
            var il2cppProgram     = new DotNetRunnableProgram(il2cpp, netCoreRunRuntime);

            var extraTypes = new HashSet <string>();

            foreach (var extraType in PlayerBuildInterface.ExtraTypesProvider?.Invoke() ?? Array.Empty <string>())
            {
                extraTypes.Add(extraType);
            }

            NPath extraTypesFile = Configuration.RootArtifactsPath.Combine("extra-types.txt").MakeAbsolute().WriteAllLines(extraTypes.ToArray());

            NPath il2cppOutputDir = Configuration.RootArtifactsPath.Combine("il2cpp");

            Backend.Current.AddAction("IL2CPP", Array.Empty <NPath>(),
                                      linkerOutputFiles
                                      .Concat(il2cpp.Path.Parent.Files()).Concat(netCoreRunRuntime.Inputs)
                                      .Concat(new[] { extraTypesFile })
                                      .ToArray(),
                                      il2cppProgram.InvocationString,
                                      new[]
            {
                "--convert-to-cpp",
                "--emit-null-checks",
                "--enable-array-bounds-check",
                "--dotnetprofile=\"unityaot\"",
                "--libil2cpp-static",
                $"--extra-types-file={extraTypesFile.InQuotes()}",
                "--profiler-report",
                $"--generatedcppdir={il2cppOutputDir.InQuotes(SlashMode.Native)}",
                $"--directory={linkerOutputFiles.First().Parent.InQuotes(SlashMode.Native)}",
            }, targetDirectories: new[] { il2cppOutputDir }, allowUnwrittenOutputFiles: true);

            var il2cppOutputFiles = GuessTargetDirectoryContentsFor(il2cppOutputDir, "dummy.cpp");

            var dataDir = il2cppOutputDir.Combine("Data");

            foreach (var il2cppdatafile in dataDir.FilesIfExists(recurse: true))
            {
                CopyTool.Instance().Setup(il2cppdata_destinationdir.Combine(il2cppdatafile.RelativeTo(dataDir)),
                                          il2cppdatafile);
            }

            return(il2cppOutputFiles);
        }
Пример #4
0
    public static NPath SetupBurst(NPath burstPackage, DotNetAssembly inputAssembly, NPath responseFile, ToolChain toolChain)
    {
        var bcl = new DotNetRunnableProgram(new DotNetAssembly(burstPackage.Combine(".Runtime/bcl.exe"), Framework.Framework471));

        var targetFile = inputAssembly.Path.Parent.Combine($"burst_output.{toolChain.CppCompiler.ObjectExtension}");
        var inputs     = Unity.BuildTools.EnumerableExtensions.Append(inputAssembly.RecursiveRuntimeDependenciesIncludingSelf.SelectMany(a => a.Paths), responseFile);

        Backend.Current.AddAction(
            "Burst",
            targetFiles: new[] { targetFile },
            inputs: inputs.ToArray(),
            executableStringFor: bcl.InvocationString,
            commandLineArguments: new[] { $"--assembly-folder={inputAssembly.Path.Parent}", $"--output={targetFile}", "--keep-intermediate-files", $"@{responseFile.ToString(SlashMode.Native)}" },
            allowUnexpectedOutput: false,
            allowedOutputSubstrings: new[] { "Link succesful", "Method:" });
        return(targetFile);
    }
Пример #5
0
    public void SetupInvocation(DotNetAssembly inputProgram, DotsRuntimeCSharpProgramConfiguration config)
    {
        var result = BindGemOutputFor(inputProgram, config);

        if (result == null)
        {
            return;
        }

        var assembly = inputProgram;

        var args = new List <string>
        {
            "-v",
            "-dots",
            assembly.RuntimeDependencies.Select(rd => $"-r {rd.Path.InQuotes()}"),
            assembly.RuntimeDependencies.Select(r => BindGemOutputFor(r, config)).ExcludeNulls().Select(bo => $"-cppInclude {bo.Header}"),
            $"-define_guard BUILD_{assembly.Path.FileName.ToUpper().Replace(".", "_")}",
            assembly.Path.InQuotes(),
            "-o",
            result.Cpp.Parent.Combine(result.Cpp.FileNameWithoutExtension).InQuotes()
        };

        var program = new DotNetRunnableProgram(BuiltBindGemProgram);

        var inputs = new List <NPath>
        {
            BuiltBindGemProgram.Path,
            assembly.RecursiveRuntimeDependenciesIncludingSelf.Select(d => d.Path)
        };

        // Note: the MakeAbsolute() below also takes care of changing slashes on Windows,
        // because Windows really hates forward slashes when used as an executable path
        // to cmd.exe
        Backend.Current.AddAction(
            actionName: "BindGem",
            targetFiles: result.Files,
            inputs: inputs.ToArray(),
            executableStringFor: program.InvocationString,
            commandLineArguments: args.ToArray(),
            supportResponseFile: false
            );
    }
Пример #6
0
        public DotNetAssembly SetupPostProcessorInvocation(DotNetAssembly inputAsm)
        {
            List <DotNetAssembly> inputAssemblyAndReferences;

            using (new ProfilerMarker(nameof(inputAsm.RecursiveRuntimeDependenciesIncludingSelf)).Auto())
                inputAssemblyAndReferences = inputAsm.RecursiveRuntimeDependenciesIncludingSelf.ToList();

            var inputFiles = _inputFilesFromPostProcessor.Concat(inputAssemblyAndReferences.Select(p => p.Path)).ToArray();

            var result = new DotNetAssembly(OutputDirectory.Combine(inputAsm.Path.FileName), inputAsm.Framework, debugSymbolPath: OutputDirectory.Combine(inputAsm.DebugSymbolPath.FileName))
                         .WithRuntimeDependencies(inputAsm.RuntimeDependencies.Select(r => _processedAssemblies.TryGetValue(r, out var processed) ? processed : r).ToArray());

            var processorPathsArg = _builtProcessors.Select(p => $"-p={p.Path.InQuotes(SlashMode.Native)}");

            var referenceAsmPaths = inputAssemblyAndReferences
                                    .Where(a => !a.Path.IsChildOf("post_ilprocessing"))
                                    .Select(a => a.Path)
                                    .Concat(_bclFiles);

            var args = new List <string>
            {
                "-a",
                inputAsm.Path.InQuotes(SlashMode.Native),
                $"--outputDir={OutputDirectory.InQuotes(SlashMode.Native)}",
                processorPathsArg,
                referenceAsmPaths.Select(r => $"-r={r.InQuotesResolved()}"),
                "-f=.",
            }.ToArray();

            Backend.Current.AddAction($"ILPostProcessorRunner",
                                      result.Paths,
                                      inputFiles,
                                      executableStringFor: _processorRunnableProgram.InvocationString,
                                      args,
                                      supportResponseFile: true
                                      );
            _processedAssemblies.Add(inputAsm, result);

            return(result);
        }
Пример #7
0
        public override DotNetAssembly SetupSpecificConfiguration(CSharpProgramConfiguration config)
        {
            var nonPatchedUnsafeUtility = base.SetupSpecificConfiguration(config);

            var builtPatcher = new CSharpProgram()
            {
                Path       = "artifacts/UnsafeUtilityPatcher/UnsafeUtilityPatcher.exe",
                Sources    = { $"{BuildProgram.LowLevelRoot}/UnsafeUtilityPatcher" },
                Defines    = { "NDESK_OPTIONS" },
                Framework  = { Bee.DotNet.Framework.Framework471 },
                References =
                {
                    MonoCecil.Paths,
                },
                LanguageVersion = "7.3"
            }.SetupDefault();

            var   outDir = nonPatchedUnsafeUtility.Path.Parent.Combine("patched");
            NPath nPath  = outDir.Combine(nonPatchedUnsafeUtility.Path.FileName);

            var builtPatcherProgram = new DotNetRunnableProgram(builtPatcher);
            var args = new[]
            {
                $"--output={nPath}",
                $"--assembly={nonPatchedUnsafeUtility.Path}",
            };

            var result = new DotNetAssembly(nPath, nonPatchedUnsafeUtility.Framework,
                                            nonPatchedUnsafeUtility.DebugFormat,
                                            nPath.ChangeExtension("pdb"), nonPatchedUnsafeUtility.RuntimeDependencies,
                                            nonPatchedUnsafeUtility.ReferenceAssemblyPath);

            Backend.Current.AddAction("Patch", result.Paths,
                                      nonPatchedUnsafeUtility.Paths.Concat(builtPatcher.Paths).ToArray(), builtPatcherProgram.InvocationString,
                                      args);

            return(result);
        }
Пример #8
0
        /// <summary>
        /// Accepts the dot net assembly.
        /// </summary>
        /// <param name="assembly">The assembly.</param>
        private void AcceptDotNetAssembly(DotNetAssembly assembly)
        {
            _projectPath.Push(CurrentModelPath);

            // Si l'assembly est dans le GAC
            if (assembly.IsInGac)
            {
                if (_scope == ReferenceScope.Compilation)
                {
                    _references.Add(assembly.FullName);
                }

                if (_scope != ReferenceScope.Publish) // == Runtime
                {
                    return;
                }
            }

            string assemblyName = assembly.AssemblyName;
            string fileName     = Path.Combine(_projectPath.Peek(), assemblyName);

            if (_initialModelIsInSolution && !IsExternalModel)
            {
                if (!File.Exists(fileName))
                {
                    // 1ère fois - Copie dans le répertoire local
                    Utils.CopyFile(assembly.InitialLocation, fileName);
                }

                if (!File.Exists(fileName)) // Toujours pas (même aprés copie éventuelle)
                {
                    fileName = assembly.AssemblyName;
                }
            }
            _references.Add(fileName);
        }
Пример #9
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);
    }
Пример #10
0
    public static BagOfObjectFilesLibrary SetupBurstCompilationForAssemblies(
        BurstCompiler compiler,
        DotNetAssembly unpatchedInputAssembly,
        NPath outputDirForObjectFile,
        NPath outputDirForPatchedAssemblies,
        string pinvokeName,
        out DotNetAssembly patchedAssembly)
    {
        var objectFile = outputDirForObjectFile.Combine("lib_burst_generated_part_0" + compiler.ObjectFileExtension);

        patchedAssembly = unpatchedInputAssembly.ApplyDotNetAssembliesPostProcessor(
            outputDirForPatchedAssemblies,
            (inputAssemblies, targetDir) =>
        {
            var inputPaths = inputAssemblies.SelectMany(asm =>
            {
                var ret = new List <NPath> {
                    asm.Path
                };
                if (asm.DebugSymbolPath != null)
                {
                    ret.Add(asm.DebugSymbolPath);
                }
                return(ret);
            });
            var commandLineArguments = new[]
            {
                $"--platform={compiler.TargetPlatform}",
                $"--backend=burst-llvm",
                $"--target={compiler.TargetArchitecture}",
                $"--format={compiler.ObjectFormat}",
                compiler.SafetyChecks ? "--safety-checks" : "",
                $"--dump=\"None\"",
                compiler.DisableVectors ? "--disable-vectors" : "",
                compiler.Link ? "" : "--nolink",
                $"--float-precision={compiler.FloatPrecision}",
                $"--keep-intermediate-files",
                "--verbose",
                $"--patch-assemblies-into={outputDirForPatchedAssemblies}",
                $"--output={objectFile.Parent.Combine(pinvokeName)}",
                $"--only-static-methods",
                "--method-prefix=burstedmethod_",
                $"--pinvoke-name={pinvokeName}"
            }.Concat(inputAssemblies.Select(asm => $"--root-assembly={asm.Path}"));
            if (!compiler.UseOwnToolchain)
            {
                commandLineArguments = commandLineArguments.Concat(new[] { "--no-native-toolchain" });
            }

            var executableStringFor = HostPlatform.IsWindows ? BurstExecutable.ToString(SlashMode.Native) : "mono";
            if (!HostPlatform.IsWindows)
            {
                commandLineArguments = new[] { BurstExecutable.ToString(SlashMode.Native) }
            }
            .Concat(commandLineArguments);

            var commandLineArgumentsArray = commandLineArguments.ToArray();

            Backend.Current.AddAction(
                "Burst",
                //todo: make burst process pdbs
                inputPaths.Select(p => targetDir.Combine(p.FileName)).Concat(new[] { objectFile }).ToArray(),
                inputPaths.Concat(new[] { BurstExecutable }).ToArray(),
                executableStringFor,
                commandLineArgumentsArray);
        });
Пример #11
0
    private static DotsRuntimeCSharpProgram SetupGame(AsmDefDescription game)
    {
        DotsRuntimeCSharpProgram gameProgram = GetOrMakeDotsRuntimeCSharpProgramFor(game);

        var   withoutExt     = new NPath(gameProgram.FileName).FileNameWithoutExtension;
        NPath exportManifest = new NPath(withoutExt + "/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(new DeployableFile(dataFile, "Data/" + dataFile.FileName));
            }
        }

        var configToSetupGame = DotsConfigs.Configs.ToDictionary(config => config, config =>
        {
            DotNetAssembly setupGame = gameProgram.SetupSpecificConfiguration(config);
            return(TypeRegistrationTool.SetupInvocation(setupGame, config));
        });

        var il2CppOutputProgram = new Il2Cpp.Il2CppOutputProgram(gameProgram.FileName + "_il2cpp");

        foreach (var kvp in configToSetupGame)
        {
            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);
            }
        }

        foreach (var kvp in configToSetupGame)
        {
            var   config     = kvp.Key;
            var   setupGame  = kvp.Value;
            NPath deployPath = $"build/{game.Name}/{game.Name}-{config.Identifier}";

            IDeployable deployedGame;

            if (config.ScriptingBackend == ScriptingBackend.TinyIl2cpp)
            {
                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());

                deployedGame = builtNativeProgram.DeployTo(deployPath);
            }
            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);
                    var from = dotNetAssembly.RecursiveRuntimeDependenciesIncludingSelf.Single(a => a.Path.HasExtension("exe")).Path;
                    Backend.Current.AddDependency(deployedGame.Path, CopyTool.Instance().Setup(to, from));
                }
            }

            NPath deployedGamePath = deployedGame.Path;

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

            Backend.Current.AddAliasDependency($"{game.Name.ToLower()}-{config.Identifier}", deployedGamePath);
            Backend.Current.AddAliasDependency($"{game.Name.ToLower()}-all", deployedGamePath);
        }

        return(gameProgram);
    }
Пример #12
0
    protected virtual DotNetAssembly SetupNativeProgram(CSharpProgramConfiguration config, DotNetAssembly result)
    {
        var dotsConfig = (DotsRuntimeCSharpProgramConfiguration)config;

        var npc = dotsConfig.NativeProgramConfiguration;

        if (NativeProgram != null && NativeProgram.Sources.ForAny().Any())
        {
            BuiltNativeProgram setupSpecificConfiguration = NativeProgram.SetupSpecificConfiguration(npc,
                                                                                                     npc.ToolChain.DynamicLibraryFormat ?? npc.ToolChain.StaticLibraryFormat);
            result = result.WithDeployables(setupSpecificConfiguration);
        }

        return(result);
    }
 protected override DotNetAssembly SetupNativeProgram(CSharpProgramConfiguration config, DotNetAssembly result)
 {
     BindGem.Instance().SetupInvocation(result, (DotsRuntimeCSharpProgramConfiguration)config);
     return(base.SetupNativeProgram(config, result));
 }
Пример #14
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);
    }
Пример #15
0
 public static DotNetAssembly SetupInvocation(DotNetAssembly inputGame, NPath outputPath, NativeProgramConfiguration config)
 {
     return(inputGame.ApplyDotNetAssembliesPostProcessor(outputPath, (inputAssemblies, targetDir) => AddActions(inputAssemblies, targetDir, config)
                                                         ));
 }
Пример #16
0
 static BindGemResult BindGemOutputFor(DotNetAssembly assembly, DotsRuntimeCSharpProgramConfiguration config) => SupportsBindgem(assembly.Path.FileName) ? MakeBindGemResultFor(assembly.Path.FileName, config) : null;
Пример #17
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());
        }
    }
Пример #18
0
        private static NPath[] SetupLinker(List <NPath> copiedAssemblies, List <DotNetAssembly> postProcessedPlayerAssemblies, BuildTarget buildTarget, NPath workingDirectory)
        {
            /*
             * Invoking UnityLinker with arguments: -out=C:/dots/Samples/Temp/StagingArea/Data/Managed/tempStrip -x=C:/Users/Lucas/AppData/Local/Temp/tmp5eb9e11d.tmp
             * -x=C:/dots/Samples/Temp/StagingArea/Data/Managed/TypesInScenes.xml -x=C:/dots/Samples/Temp/StagingArea/Data/Managed/DotsStripping.xml
             * -d=C:/dots/Samples/Temp/StagingArea/Data/Managed --include-unity-root-assembly=C:/dots/Samples/Temp/StagingArea/Data/Managed/Assembly-CSharp.dll
             * --include-unity-root-assembly=C:/dots/Samples/Temp/StagingArea/Data/Managed/RotateMe.dll --include-unity-root-assembly=C:/dots/Samples/Temp/StagingArea/Data/Managed/Unity.Scenes.Hybrid.dll
             * --include-unity-root-assembly=C:/dots/Samples/Temp/StagingArea/Data/Managed/Samples.GridPath.dll --include-unity-root-assembly=C:/dots/Samples/Temp/StagingArea/Data/Managed/Unity.Entities.Hybrid.dll
             * --include-unity-root-assembly=C:/dots/Samples/Temp/StagingArea/Data/Managed/SubsceneWithBuildSettings.dll --include-unity-root-assembly=C:/dots/Samples/Temp/StagingArea/Data/Managed/HelloCube.dll
             * --include-unity-root-assembly=C:/dots/Samples/Temp/StagingArea/Data/Managed/Samples.Boids.dll --dotnetruntime=il2cpp --dotnetprofile=unityaot --use-editor-options --include-directory=C:/dots/Samples/Temp/StagingArea/Data/Managed
             * --editor-settings-flag=Development --rule-set=Conservative --editor-data-file=C:/dots/Samples/Temp/StagingArea/Data/Managed/EditorToUnityLinkerData.json --platform=WindowsDesktop
             * --engine-modules-asset-file=C:/unity/build/WindowsStandaloneSupport/Whitelists/../modules.asset
             * C:\unity\build\WindowsEditor\Data\il2cpp\build/deploy/net471/UnityLinker.exe exited after 4100 ms.
             *
             * "C:\\code\\unity-src-git\\build\\WindowsEditor\\Data\\il2cpp\\build\\deploy\\net471\\UnityLinker.exe --dotnetruntime=mono --dotnetprofile=unityaot
             * --use-editor-options --include-directory=\"artifacts\\managedassemblies\" --editor-settings-flag=Development --rule-set=conservative --out=\"artifacts\\linkeroutput\"
             * --include-unity-root-assembly=\"C:/code/dots/Samples/Library/IncrementalClassicBuildPipeline/Win64-LiveLink/artifacts/UnityEngine.UI.dll/Release/UnityEngine.UI.dll\",
             \"C:/code/dots/Samples/Library/IncrementalClassicBuildPipeline/Win64-LiveLink/artifacts/Unity.Mathematics.dll/Release/Unity.Mathematics.dll\",
             \"C:/code/dots/Samples/Library/IncrementalClassicBuildPipeline/Win64-LiveLink/artifacts/Unity.Entities.StaticTypeRegistry.dll/Release/Unity.Entities.StaticTypeRegistry.dll\",
             \"C:/code/dots/Samples/Library/IncrementalClassicBuildPipeline/Win64-LiveLink/artifacts/Unity.Burst.dll/Release/Unity.Burst.dll\",
             \"C:/code/dots/Samples/Library/IncrementalClassicBuildPipeline/Win64-LiveLink/artifacts/Unity.ScriptableBuildPipeline.dll/Release/Unity.ScriptableBuildPipeline.dll\",
             \"C:/code/dots/Samples/Library/IncrementalClassicBuildPipeline/Win64-LiveLink/artifacts/Unity.Collections.dll/Release/Unity.Collections.dll\",
             \"C:/code/dots/Samples/Library/IncrementalClassicBuildPipeline/Win64-LiveLink/artifacts/Unity.Properties.dll/Release/Unity.Properties.dll\",
             \"C:/code/dots/Samples/Library/IncrementalClassicBuildPipeline/Win64-LiveLink/artifacts/Unity.Jobs.dll/Release/Unity.Jobs.dll\",
             \"C:/code/dots/Samples/Library/IncrementalClassicBuildPipeline/Win64-LiveLink/artifacts/Unity.Mathematics.Extensions.dll/Release/Unity.Mathematics.Extensions.dll\",
             \"C:/code/dots/Samples/Library/IncrementalClassicBuildPipeline/Win64-LiveLink/artifacts/Unity.Entities.dll/Release/Unity.Entities.dll\",
             \"C:/code/dots/Samples/Library/IncrementalClassicBuildPipeline/Win64-LiveLink/artifacts/Unity.Transforms.dll/Release/Unity.Transforms.dll\",
             \"C:/code/dots/Samples/Library/IncrementalClassicBuildPipeline/Win64-LiveLink/artifacts/Unity.Entities.Determinism.dll/Release/Unity.Entities.Determinism.dll\",
             \"C:/code/dots/Samples/Library/IncrementalClassicBuildPipeline/Win64-LiveLink/artifacts/Unity.Mathematics.Extensions.Hybrid.dll/Release/Unity.Mathematics.Extensions.Hybrid.dll\",
             \"C:/code/dots/Samples/Library/IncrementalClassicBuildPipeline/Win64-LiveLink/artifacts/Unity.Entities.Hybrid.dll/Release/Unity.Entities.Hybrid.dll\",
             \"C:/code/dots/Samples/Library/IncrementalClassicBuildPipeline/Win64-LiveLink/artifacts/Unity.Transforms.Hybrid.dll/Release/Unity.Transforms.Hybrid.dll\",
             \"C:/code/dots/Samples/Library/IncrementalClassicBuildPipeline/Win64-LiveLink/artifacts/Unity.Scenes.Hybrid.dll/Release/Unity.Scenes.Hybrid.dll\",
             \"C:/code/dots/Samples/Library/IncrementalClassicBuildPipeline/Win64-LiveLink/artifacts/Unity.Rendering.Hybrid.dll/Release/Unity.Rendering.Hybrid.dll\",
             \"C:/code/dots/Samples/Library/IncrementalClassicBuildPipeline/Win64-LiveLink/artifacts/Samples.Boids.dll/Release/Samples.Boids.dll\",
             \"C:/code/dots/Samples/Library/IncrementalClassicBuildPipeline/Win64-LiveLink/artifacts/HelloCube.dll/Release/HelloCube.dll\",
             \"C:/code/dots/Samples/Library/IncrementalClassicBuildPipeline/Win64-LiveLink/artifacts/Samples.GridPath.dll/Release/Samples.GridPath.dll\",
             \"C:/code/dots/Samples/Library/IncrementalClassicBuildPipeline/Win64-LiveLink/artifacts/SubsceneWithBuildSettings.dll/Release/SubsceneWithBuildSettings.dll\",
             \"C:/code/dots/Samples/Library/IncrementalClassicBuildPipeline/Win64-LiveLink/artifacts/Assembly-CSharp.dll/Release/Assembly-CSharp.dll\"
             * --include-unity-root-assembly=\"C:/code/unity-src-git/build/WindowsStandaloneSupport/Variations/win64_development_mono/Data/Managed/UnityEngine.dll\"",
             *
             */

            DotNetAssembly linker =
                new DotNetAssembly(
                    string.IsNullOrEmpty(CustomIL2CPPLocation) ?
                    $"{EditorApplication.applicationContentsPath}/il2cpp/build/deploy/net471/UnityLinker.exe" :
                    $"{CustomIL2CPPLocation}/build/deploy/net471/UnityLinker.exe",
                    Framework.Framework471);

            var linkerProgram = new DotNetRunnableProgram(linker);

            var linkXmlFiles = NPath.CurrentDirectory.Combine("Assets").Files("link.xml", true);

            var unityLinkerProcessors = TypeCacheHelper.ConstructTypesDerivedFrom <IUnityLinkerProcessor>();

            var linkerData = new UnityLinkerBuildPipelineData(buildTarget, workingDirectory.ToString());

            linkXmlFiles = linkXmlFiles.Concat(unityLinkerProcessors.Select(p => (NPath)p.GenerateAdditionalLinkXmlFile(null, linkerData))).ToArray();

            var inputFiles = copiedAssemblies
                             .Concat(postProcessedPlayerAssemblies.Select(p => p.Path))
                             .Concat(linker.Path.Parent.Files())
                             .Concat(linkXmlFiles)
                             //    .Concat(dotNetRuntime.Inputs)
                             .ToArray();

            var searchDirectories = new HashSet <NPath>();

            foreach (var file in copiedAssemblies)
            {
                searchDirectories.Add(file.Parent);
            }
            foreach (var file in postProcessedPlayerAssemblies)
            {
                searchDirectories.Add(file.Path.Parent);
            }
            searchDirectories.Add(_incrementalClassicSharedData.UnityEngineAssembliesDirectory.ToString());

            // Pass along the correct platform names for macOS and Windows desktop targets
            var platformName = _incrementalClassicSharedData.PlatformName == "Windows" ?
                               "WindowsDesktop" :
                               _incrementalClassicSharedData.PlatformName == "UniversalWindows" ?
                               "WinRT" :
                               _incrementalClassicSharedData.PlatformName;

            platformName = _incrementalClassicSharedData.PlatformName == "OSX" ? "MacOSX" : platformName;

            NPath linkerOutputDir = Configuration.RootArtifactsPath.Combine("linkeroutput");

            Backend.Current.AddAction("UnityLinker", Array.Empty <NPath>(), inputFiles,
                                      linkerProgram.InvocationString, new[]
            {
                $"--platform={platformName}",
                "--dotnetruntime=il2cpp",
                "--dotnetprofile=unityaot",
                "--use-editor-options",
                $"--include-directory={copiedAssemblies.First().Parent.InQuotes(SlashMode.Native)}",
                "--editor-settings-flag=Development",

                //if you want to boost up from conservative to aggressive, the linker will start to remove MonoBehaviours. We'd need to add a step that analyzes all assets
                //in the databuild, and build a list of actually used monobehaviours. this goes very much against the concept of incrementalness. Let's stick to conservative for now.t
                "--rule-set=Conservative",
                $"--out={linkerOutputDir.InQuotes(SlashMode.Native)}",
                $"--search-directory={searchDirectories.Select(d=>d.MakeAbsolute().ToString()).SeparateWithComma()}",
                $"--include-unity-root-assembly={postProcessedPlayerAssemblies.Where(a => a.Path.FileName != "Unity.Serialization.dll").Select(a => a.Path.MakeAbsolute()).InQuotes().SeparateWithComma()}",
                $"--engine-modules-asset-file={_incrementalClassicSharedData.PlayerPackageDirectory.Combine("modules.asset").InQuotes(SlashMode.Native)}",
                linkXmlFiles.Select(f => $"--include-link-xml={f}").SeparateWithSpace(),
            }, allowUnwrittenOutputFiles: true,
                                      supportResponseFile: true,
                                      targetDirectories: new[]
            {
                linkerOutputDir
            }
                                      );

            NPath[] linkerOutputFiles = GuessTargetDirectoryContentsFor(linkerOutputDir, "dummy.dll");

            return(linkerOutputFiles);
        }
Пример #19
0
 private static DotNetAssembly RemovePdbFromStaticTypeRegistry(DotNetAssembly input, DotNetAssembly suggestedOutput)
 {
     return(input.Path.FileName == "Unity.Entities.StaticTypeRegistry.dll"
         ? suggestedOutput.WithDebugSymbolPath(null)
         : suggestedOutput);
 }
Пример #20
0
        public (NPath runtimeInitializeOnLoadFile, NPath typeDBfile) SetupTypeDBAndRuntimeInitializeOnLoadFileFor(DotNetAssembly inputAsm)
        {
            var searchPathsOneLine    = inputAsm.RecursiveRuntimeDependenciesIncludingSelf.Select(x => x.Path.Parent).Distinct().InQuotes().SeparateWithComma();
            var inputAssemblyFileName = inputAsm.Path.FileNameWithoutExtension;

            var args = new[]
            {
                "-a", inputAsm.Path.InQuotes(),
                "-s", searchPathsOneLine,
                "-o", TypeDBOutputDirectory.InQuotes(),
                "-n", inputAssemblyFileName.InQuotes(),
                "-r", "True"
            };

            var runtimeInitializeOnLoadFile = TypeDBOutputDirectory.Combine($"RuntimeInitOnLoad-{inputAssemblyFileName}.json");
            var typeDBfile = TypeDBOutputDirectory.Combine($"TypeDb-{inputAssemblyFileName}.json");

            Backend.Current.AddAction($"TypeGenerator",
                                      new[]
            {
                typeDBfile,
                runtimeInitializeOnLoadFile,
            },
                                      inputAsm.Paths,
                                      executableStringFor: _typeGeneratorExecutable.InvocationString,
                                      args,
                                      supportResponseFile: true
                                      );

            return(runtimeInitializeOnLoadFile : runtimeInitializeOnLoadFile, typeDBfile : typeDBfile);
        }
Пример #21
0
 public void SetupConditionalSourcesAndLibrariesForConfig(DotsRuntimeCSharpProgramConfiguration config, DotNetAssembly setupGame)
 {
     NPath[] il2cppGeneratedFiles = SetupInvocation(setupGame);
     //todo: stop comparing identifier.
     Sources.Add(npc => ((DotsRuntimeNativeProgramConfiguration)npc).CSharpConfig == config, il2cppGeneratedFiles);
     Libraries.Add(npc => ((DotsRuntimeNativeProgramConfiguration)npc).CSharpConfig == config, setupGame.RecursiveRuntimeDependenciesIncludingSelf.SelectMany(r => r.Deployables.OfType <StaticLibrary>()));
 }
Пример #22
0
 public static NPath Il2CppTargetDirForAssembly(DotNetAssembly inputAssembly)
 {
     return(inputAssembly.Path.Parent.Combine(inputAssembly.Path.FileName + "-il2cpp-sources"));
 }
Пример #23
0
    private static DotNetAssembly Clone(NPath outputDir, DotNetAssembly a)
    {
        var debugSymbolPath = a.DebugSymbolPath == null ? null : outputDir.Combine(a.DebugSymbolPath.FileName);

        return(new DotNetAssembly(outputDir.Combine(a.Path.FileName), a.Framework, a.DebugFormat, debugSymbolPath));
    }
Пример #24
0
    public static NPath[] SetupInvocation(DotNetAssembly inputAssembly, DotsRuntimeCSharpProgramConfiguration config)
    {
        var profile         = "unitytiny";
        var il2CppTargetDir = Il2CppTargetDirForAssembly(inputAssembly);

        var args = new List <string>()
        {
            "--convert-to-cpp",
            "--disable-cpp-chunks",

            //  "--directory", $"{InputAssembly.Path.Parent}",
            "--generatedcppdir",
            $"{il2CppTargetDir}",

            // Make settings out of these
            $"--dotnetprofile={profile}", // Resolve from DotNetAssembly
            "--libil2cpp-static",
            "--emit-null-checks=0",
            "--enable-array-bounds-check=0",
            "--enable-predictable-output",
            //"--enable-stacktrace=1"
            //"--profiler-report",
            //"--enable-stats",
        };

        if (config.EnableManagedDebugging)
        {
            args.Add("--enable-debugger");
        }

        if (config.EnableUnityCollectionsChecks)
        {
            args.Add("--development-mode");
        }

        var iarrdis = MoveExeToFront(inputAssembly.RecursiveRuntimeDependenciesIncludingSelf);

        args.AddRange(
            iarrdis.SelectMany(a =>
                               new[] { "--assembly", a.Path.ToString() }));

        var sharedFileNames = new List <string>
        {
            // static files
            //"Il2CppComCallableWrappers.cpp",
            //"Il2CppProjectedComCallableWrapperMethods.cpp",
            "driver.cpp",
            "GenericMethods.cpp",
            "Generics.cpp",
            "Il2CppGenericComDefinitions.cpp",
            "ReversePInvokeWrappers.cpp",
        };

        var nonDebuggerExtraFileNames = new[]
        {
            "TinyTypes.cpp",
            "StaticConstructors.cpp",
            "StringLiterals.cpp",
            "StaticInitialization.cpp"
        };

        var debuggerExtraFileNames = new[]
        {
            "Il2CppGenericClassTable.c",
            "Il2CppGenericInstDefinitions.c",
            "Il2CppGenericMethodDefinitions.c",
            "Il2CppGenericMethodTable.c",
            "Il2CppMetadataRegistration.c",
            "Il2CppMetadataUsage.c",
            "Il2CppTypeDefinitions.c",
            "Il2CppAttributes.cpp",
            "Il2CppCodeRegistration.cpp",
            "Il2CppCompilerCalculateTypeValues.cpp",
            "Il2CppCompilerCalculateTypeValuesTable.cpp",
            "Il2CppGenericMethodPointerTable.cpp",
            "Il2CppInteropDataTable.cpp",
            "Il2CppInvokerTable.cpp",
            "Il2CppReversePInvokeWrapperTable.cpp",
            "UnresolvedVirtualCallStubs.cpp",
        };

        IEnumerable <string> il2cppOutputFileNames = sharedFileNames;


        if (config.EnableManagedDebugging)
        {
            il2cppOutputFileNames = il2cppOutputFileNames.Concat(debuggerExtraFileNames);
            il2cppOutputFileNames = il2cppOutputFileNames.Concat(iarrdis.Select(asm => asm.Path.FileNameWithoutExtension + "_Debugger.c"));
            il2cppOutputFileNames = il2cppOutputFileNames.Concat(iarrdis.Select(asm => asm.Path.FileNameWithoutExtension + "_Codegen.c"));
        }
        else
        {
            il2cppOutputFileNames = il2cppOutputFileNames.Concat(nonDebuggerExtraFileNames);
        }

        var il2cppOutputFiles = il2cppOutputFileNames.Concat(iarrdis.Select(asm => asm.Path.FileNameWithoutExtension + ".cpp"))
                                .Select(il2CppTargetDir.Combine).ToArray();

        var il2cppInputs = Distribution.GetFileList("build")
                           .Concat(iarrdis.SelectMany(a => a.Paths))
                           .Concat(new[] { Distribution.Path.Combine("libil2cpptiny", "libil2cpptiny.icalls") })
                           .Concat(new[] { Il2CppDependencies.GetFileList().First() });

        var finalOutputFiles = il2cppOutputFiles;

        if (config.EnableManagedDebugging)
        {
            finalOutputFiles = finalOutputFiles.Concat(new[] { il2CppTargetDir.Combine("Data/Metadata/global-metadata.dat") }).ToArray();
        }

        Backend.Current.AddAction(
            "Il2Cpp",
            targetFiles: finalOutputFiles,
            inputs: il2cppInputs.ToArray(),
            Il2CppRunnableProgram.InvocationString,
            args.ToArray());

        return(il2cppOutputFiles);
    }
Пример #25
0
        /// <summary>
        /// Execute the command
        /// </summary>
        public void Exec()
        {
            // Affiche la fenetre de dialogue permettant de choisir les assemblies
            IAssemblySelectorDialog selector = ServiceLocator.Instance.GetService <IAssemblySelectorDialog>();

            if (selector.ShowDialog(1)) // Une seule sélection possible
            {
                Assembly asm = selector.SelectedAssemblies[0];
                using (Transaction transaction = _element.Store.TransactionManager.BeginTransaction("Update model version"))
                {
                    // Mise à jour de la version du composant et son emplacement initial
                    // et création des nouvelles dépendances (les dépendances actuelles ne seront pas touchées
                    // mais il faudra s'assurer qu'elles soient bien à jour car la procédure ne vérifie que le nom
                    // et ignore la version)
                    _element.InitFromAssembly(asm, true /* creation des nouvelles dépendances*/);
                    transaction.Commit();
                }

                // Vérification si les assemblies existantes possédent la bonne version
                foreach (AssemblyName assemblyName in asm.GetReferencedAssemblies())
                {
                    // On ignore les assemblies systèmes
                    if (Utils.StringCompareEquals(assemblyName.Name, "mscorlib") ||
                        assemblyName.Name.StartsWith("System", StringComparison.CurrentCultureIgnoreCase))
                    {
                        continue;
                    }

                    // On regarde si cette assembly existe déjà dans le modèle
                    DotNetAssembly eam = _element.Component.FindDotNetAssemblyModelFromAssembly(assemblyName);
                    if (eam != null)
                    {
                        if (!assemblyName.Version.Equals((Version)eam.Version))
                        {
                            using (Transaction transaction = _element.Store.TransactionManager.BeginTransaction("Update assembly version"))
                            {
                                eam.Version = new VersionInfo(assemblyName.Version);
                                transaction.Commit();
                            }
                        }
                    }
                    else
                    {
                        // Idem pour les composants externes
                        ExternalComponent esm = _element.Component.Model.FindExternalComponentByName(assemblyName.Name);
                        if (esm != null && esm.MetaData != null && esm.MetaData.ComponentType == ComponentType.Library)
                        {
                            if (!assemblyName.Version.Equals((Version)esm.Version))
                            {
                                // Recherche si il existe un modèle avec la bonne version
                                List <ComponentModelMetadata> versions = RepositoryManager.Instance.ModelsMetadata.Metadatas.GetAllVersions(esm.Id);
                                ComponentModelMetadata        metadata = versions.Find(delegate(ComponentModelMetadata m) { return(assemblyName.Version.Equals(m.Version)); });
                                using (Transaction transaction = _element.Store.TransactionManager.BeginTransaction("Update model version"))
                                {
                                    if (metadata != null)
                                    {
                                        // OK on met a jour
                                        esm.Version = metadata.Version;
                                    }
                                    else // erreur On a pas trouvé de modéle
                                    {
                                        // Sauvegarde de la bonne version
                                        esm.Version = new VersionInfo(assemblyName.Version);
                                        // On force à null pour obliger l'utilisateur à sélectionner un
                                        // modéle
                                        esm.ModelMoniker = Guid.Empty;
                                    }
                                    transaction.Commit();
                                }
                            }
                        }
                    }
                }

                // Demande si il faut aussi mettre à jour le n° de version du composant
                if (_element.Visibility == Visibility.Public)
                {
                    if (MessageBox.Show(String.Format("Do you want to change the current version of the component from {0} to {1}",
                                                      _element.Component.Model.Version, _element.Version), "Component version change", MessageBoxButtons.YesNo) == DialogResult.Yes)
                    {
                        using (Transaction transaction = _element.Store.TransactionManager.BeginTransaction("Update model version"))
                        {
                            _element.Component.Model.Version = _element.Version;
                            transaction.Commit();
                        }
                    }
                }
            }
        }
Пример #26
0
        static void AddActions(DotNetAssembly[] inputAssemblies, NPath targetDirectory, NativeProgramConfiguration nativeProgramConfiguration)
        {
            var linkerAssembly = new DotNetAssembly(Distribution.Path.Combine("build/deploy/net471/UnityLinker.exe"), Framework.Framework471);
            var linker         = new DotNetRunnableProgram(linkerAssembly);


            var outputDir       = targetDirectory;
            var isFrameworkNone = inputAssemblies.First().Framework == Framework.FrameworkNone;

            var rootAssemblies = inputAssemblies.Where(a => a.Path.HasExtension("exe")).Concat(new[] { inputAssemblies.First() }).Distinct();

            var linkerArguments = new List <string>
            {
                $"--out={outputDir.InQuotes()}",
                "--use-dots-options",
                "--dotnetprofile=" + (isFrameworkNone ? "unitytiny" : "unityaot"),
            };

            linkerArguments.AddRange(rootAssemblies.Select(rootAssembly => $"--include-public-assembly={rootAssembly.Path.InQuotes()}"));

            foreach (var inputDirectory in inputAssemblies.Select(f => f.Path.Parent).Distinct())
            {
                linkerArguments.Add($"--include-directory={inputDirectory.InQuotes()}");
            }

            NPath bclDir = Il2CppDependencies.Path.Combine("MonoBleedingEdge/builds/monodistribution/lib/mono/unityaot");

            if (!isFrameworkNone)
            {
                linkerArguments.Add($"--search-directory={bclDir.InQuotes()}");
            }

            var targetPlatform = GetTargetPlatformForLinker(nativeProgramConfiguration.Platform);

            if (!string.IsNullOrEmpty(targetPlatform))
            {
                linkerArguments.Add($"--platform={targetPlatform}");
            }

            var targetArchitecture = GetTargetArchitectureForLinker(nativeProgramConfiguration.ToolChain.Architecture);

            if (!string.IsNullOrEmpty(targetPlatform))
            {
                linkerArguments.Add($"--architecture={targetArchitecture}");
            }

            if (ManagedDebuggingIsEnabled(nativeProgramConfiguration))
            {
                linkerArguments.Add("--rule-set=aggressive"); // Body modification causes debug symbols to be out of sync
                linkerArguments.Add("--enable-debugger");
            }
            else
            {
                linkerArguments.Add("--rule-set=experimental"); // This will enable modification of method bodies to further reduce size.
            }

            //          var targetFiles = Unity.BuildTools.EnumerableExtensions.Prepend(nonMainOutputs, mainTargetFile);
            //          targetFiles = targetFiles.Append(bcl);
            var targetFiles = inputAssemblies.SelectMany(a => a.Paths).Select(i => targetDirectory.Combine(i.FileName)).ToArray();

            Backend.Current.AddAction(
                "UnityLinker",
                targetFiles: targetFiles,
                inputs: inputAssemblies.SelectMany(a => a.Paths).Concat(linkerAssembly.Paths).ToArray(),
                executableStringFor: linker.InvocationString,
                commandLineArguments: linkerArguments.ToArray(),
                allowUnwrittenOutputFiles: false,
                allowUnexpectedOutput: false,
                allowedOutputSubstrings: new[] { "Output action" });
        }
Пример #27
0
        /// <summary>
        /// Importe des assemblies dans le modèle
        /// </summary>
        /// <param name="model">The model.</param>
        /// <param name="assemblies">Liste des assemblies à importer</param>
        internal static void ImportAssemblies(CandleModel model, List <Assembly> assemblies)
        {
            if (assemblies.Count == 0)
            {
                return;
            }

            // Si il y a plusieurs assemblies, on va demander lequel est le public
            Assembly mainAssembly = assemblies[0];

            if (assemblies.Count > 1)
            {
                if (assemblies.Count > 1)
                {
                    SelectAssemblyForm form = new SelectAssemblyForm(assemblies);
                    if (form.ShowDialog() == DialogResult.Cancel)
                    {
                        throw new CanceledByUser();
                    }
                    mainAssembly = form.SelectedAssembly;
                }
            }

            // D'abord le composant
            BinaryComponent component = model.Component as BinaryComponent;

            if (component == null)
            {
                component = CreateComponent(model, mainAssembly);
            }
            else if (component.Assemblies.Count > 0)
            {
                // Si il y avait dèjà des assemblies, on n'initialisera pas l'assembly public
                mainAssembly = null;
            }

            // Puis insertion des assemblies, en deux passages car il peut y avoir des dépendances entre assemblies
            //  - Insertion des assemblies
            //  - Création des dépendances
            //
            using (Transaction transaction = model.Store.TransactionManager.BeginTransaction("Adding component"))
            {
                // Insertion des assemblies internes
                foreach (Assembly assembly in assemblies)
                {
                    if (component.FindDotNetAssemblyModelFromAssembly(assembly.GetName()) == null)
                    {
                        DotNetAssembly dotnetAssembly = new DotNetAssembly(model.Store);
                        component.Assemblies.Add(dotnetAssembly);
                        dotnetAssembly.InitFromAssembly(assembly, false);

                        // C'est l'assembly public --> Création d'un port public
                        dotnetAssembly.Visibility = assembly == mainAssembly ? Visibility.Public : Visibility.Private;
                    }
                }

                transaction.Commit();
            }

            // Création des dépendances externes
            using (Transaction transaction = model.Store.TransactionManager.BeginTransaction("Adding references"))
            {
                model.Store.TransactionManager.CurrentTransaction.TopLevelTransaction.Context.ContextInfo.Add("Import assemblies", null);
                foreach (Assembly assembly in assemblies)
                {
                    DotNetAssembly externalAssembly = component.FindDotNetAssemblyModelFromAssembly(assembly.GetName());
                    Debug.Assert(externalAssembly != null);
                    externalAssembly.InsertDependencies(assembly);
                }

                transaction.Commit();
            }
        }
Пример #28
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());
        }
    }
Пример #29
0
        public BurstCompiler(string burstTarget, string burstPlatform, NPath outputDirectory)
        {
            BurstTarget     = burstTarget;
            BurstPlatform   = burstPlatform;
            OutputDirectory = outputDirectory;

            // On macOS the PlatformName is set as OSX in bee but it needs to be macOS for bcl.
            if (burstPlatform == "OSX")
            {
                BurstPlatform = "macOS";
            }

            if (burstPlatform == "IOS" && burstTarget == "ARMV8A_AARCH64")
            {
                BurstPlatform = "iOS";
            }

            NPath burstDir   = Path.GetFullPath("Packages/com.unity.burst/.Runtime");
            var   burstFiles = burstDir.Files(recurse: true);

            bool IsManagedBurstLibrary(NPath f)
            {
                if (!f.HasExtension(".dll"))
                {
                    return(false);
                }

                if (f.FileName.StartsWith("burst-llvm-"))
                {
                    return(false);
                }

                // These two libraries are not crossgen-compatible.
                if (f.FileName == "Unity.Cecil.Rocks.dll" || f.FileName == "Newtonsoft.Json.dll")
                {
                    return(false);
                }

                return(true);
            }

            var bclAssembly = new DotNetAssembly(burstDir.Combine("bcl.exe"), Framework.Framework471)
                              .WithRuntimeDependencies(burstFiles
                                                       .Where(IsManagedBurstLibrary)
                                                       .Select(f => new DotNetAssembly(f, Framework.Framework471))
                                                       .ToArray());

#if BURST_NETCORE
            //todo: turn this to true.  we cannot right now because NetCoreRuntime.SteveDore is implemented through a static field,
            //which is incompatible with our "create graph in editor, and maybe we will create two graphs during the same domain".  the creation
            //of the steve artifact happens only once,  but it needs to be registered in each backend. the fact that it doesn't means you can get into
            //ugly situations where on second builds the dependencies to netcorerun are not properly setup.
            bool useNetCore = false;

            if (useNetCore)
            {
                var runtime = NetCoreRunRuntime.FromSteve;
                _dotnetRuntime = runtime;

                var useCrossGen = false;
                if (useCrossGen)
                {
                    bclAssembly = runtime.SetupAheadOfTimeCompilation(bclAssembly, "artifacts/bcl-crossgen");

                    bclAssembly = bclAssembly.WithPath(bclAssembly.Path.MakeAbsolute(BeeProjectRoot));
                    foreach (var file in burstFiles.Where(x => !IsManagedBurstLibrary(x)))
                    {
                        var relative = file.RelativeTo(burstDir);

                        var temp = CopyTool.Instance().Setup(bclAssembly.Path.Parent.Combine(relative), file);
                        Backend.Current.AddDependency(temp, bclAssembly.Path);
                    }
                }
            }
            else
#else
            {
                _dotnetRuntime = DotNetRuntime.FindFor(bclAssembly);
            }
#endif

            { _burstRunnableProgram = new DotNetRunnableProgram(bclAssembly, _dotnetRuntime); }
            _burstCompilerInputFiles = burstFiles;

            var burstPackageInfo =
                UnityEditor.PackageManager.PackageInfo.FindForAssetPath("Packages/com.unity.burst/somefile");
            var burstPackageRawVersion = burstPackageInfo.version;

            // Remove everything after '-' if this is a preview package.
            var parts = burstPackageRawVersion.Split('-');
            if (parts.Length > 1)
            {
                burstPackageRawVersion = parts[0];
            }

            // Get the preview version number.
            // Default to max int to signal a very high preview number on release.
            var previewNumber = int.MaxValue;
            if (parts.Length > 1)
            {
                previewNumber = int.Parse(parts[1].Split('.')[1]);
            }

            var burstVersion = Version.Parse(burstPackageRawVersion);
            var burstVersionWithIncludeRootAssemblyReferencesFeature = new Version(1, 3);
            _installedBurstSupportsIncludeRootAssemblyReferencesFeature = burstVersion >= burstVersionWithIncludeRootAssemblyReferencesFeature;
            if (!_installedBurstSupportsIncludeRootAssemblyReferencesFeature)
            {
                Debug.Log($"Using burst 1.3 instead of {burstVersion.ToString()} will give much better build times. At the time of this writing it is only available by building manually on your machine.");
            }

            _installedBurstSupportsCaching =
                (burstVersion >= new Version(1, 3) && previewNumber > 7) ||
                burstVersion >= new Version(1, 4);
            if (!_installedBurstSupportsCaching)
            {
                Debug.Log($"Using burst 1.3 preview 8 or above instead of {burstVersion.ToString()} will give much better build times. At the time of this writing it is only available by building manually on your machine.");
            }

            _installedBurstIs1_3Preview10OrLater =
                (burstVersion >= new Version(1, 3) && previewNumber >= 10) ||
                burstVersion >= new Version(1, 4);
        }
Пример #30
0
    private static DotsRuntimeCSharpProgram SetupGame(AsmDefDescription game)
    {
        var gameProgram = GetOrMakeDotsRuntimeCSharpProgramFor(game);

        var   withoutExt     = new NPath(gameProgram.FileName).FileNameWithoutExtension;
        NPath exportManifest = new NPath(withoutExt + "/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(new DeployableFile(dataFile, "Data/" + dataFile.FileName));
            }
        }

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

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

        foreach (var config in PerConfigBuildSettings[game.Name].Where(config => !CanSkipSetupOf(game.Name, config)))
        {
            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());


            DotNetAssembly setupGame = gameProgram.SetupSpecificConfiguration(config).WithDeployables(new DotNetAssembly(
                                                                                                          Il2Cpp.Distribution.Path.Combine("build/profiles/Tiny/Facades/netstandard.dll"),
                                                                                                          Framework.FrameworkNone));

            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.Replace(".", "-") + ".il2cpp");

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

        BurstCompiler hostBurstCompiler = null;

        if (HostPlatform.IsWindows)
        {
            hostBurstCompiler      = new BurstCompilerForWindows64();
            hostBurstCompiler.Link = true;
            hostBurstCompiler.OnlyStaticMethods = true;
        }
        else if (HostPlatform.IsOSX)
        {
            hostBurstCompiler      = new BurstCompilerForMac();
            hostBurstCompiler.Link = true;
            hostBurstCompiler.OnlyStaticMethods = true;
        }
        else
        {
            Console.WriteLine("Tiny burst not yet supported on linux.");
        }
        var webBurstCompiler = new BurstCompilerForEmscripten();

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

            if (config.UseBurst)
            {
                var outputDir = $"artifacts/{game.Name}/{config.Identifier}_bursted";
                var isWebGL   = config.Platform is WebGLPlatform;
                var extension = config.NativeProgramConfiguration.ToolChain.DynamicLibraryFormat.Extension;

                //burst generates a .bundle on os x.
                if (config.Platform is MacOSXPlatform)
                {
                    extension = "bundle";
                }

                var burstlib = BurstCompiler.SetupBurstCompilationAndLinkForAssemblies(
                    isWebGL
                        ? webBurstCompiler
                        : hostBurstCompiler,
                    setupGame,
                    new NPath(outputDir).Combine(
                        $"lib_burst_generated{("."+extension) ?? ""}"),
                    outputDir,
                    out var burstedGame);

                if (isWebGL)
                {
                    il2CppOutputProgram.Libraries.Add(c => c.Equals(config.NativeProgramConfiguration), burstlib);
                }
                else
                {
                    burstedGame = burstedGame.WithDeployables(burstlib);
                }
                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 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.NativeProgramConfiguration.CodeGen, gameProgram.SupportFiles.For(config));
                }
                deployedGame         = builtNativeProgram.DeployTo(deployPath);
                entryPointExecutable = deployedGame.Path;
                if (config.EnableManagedDebugging)
                {
                    Backend.Current.AddDependency(deployedGame.Path, Il2Cpp.CopyIL2CPPMetadataFile(deployPath, setupGame));
                }
            }
            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);
                    var from = dotNetAssembly.RecursiveRuntimeDependenciesIncludingSelf.SingleOrDefault(a => a.Path.HasExtension("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);
            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);
    }