Пример #1
0
        public async Task LoadProjectAsync(Path recipeFilePath)
        {
            var loadResult = await RecipeExtensions.TryLoadRecipeFromFileAsync(recipeFilePath);

            if (loadResult.IsSuccess)
            {
                var packageDirectory = recipeFilePath.GetParent();
                var targetPath       = await GetTargetPathAsync(packageDirectory);

                var soupTargetDirectory = targetPath + new Path(".soup/");

                var generateInfoStateFile = soupTargetDirectory + BuildConstants.GenerateTaskInfoFileName;
                if (!ValueTableManager.TryLoadState(generateInfoStateFile, out var generateInfoTable))
                {
                    NotifyError($"Failed to load Value Table: {generateInfoStateFile}");
                    return;
                }

                Graph = BuildGraph(generateInfoTable);
            }
            else
            {
                NotifyError($"Failed to load Recipe file: {recipeFilePath}");
            }
        }
Пример #2
0
        /// <summary>
        /// Using the parameters to resolve the dependency output folders, load up the shared state table and
        /// combine them into a single value table to be used as input the this generate phase.
        /// </summary>
        private ValueTable LoadDependenciesSharedState(IValueTable parametersTable)
        {
            var sharedDependenciesTable = new ValueTable();

            if (parametersTable.TryGetValue("Dependencies", out var dependencyTableValue))
            {
                var dependenciesTable = dependencyTableValue.AsTable();
                foreach (var dependencyTypeValue in dependenciesTable)
                {
                    var dependencyType = dependencyTypeValue.Key;
                    var dependencies   = dependencyTypeValue.Value.AsTable();
                    foreach (var dependencyValue in dependencies)
                    {
                        var dependencyName      = dependencyValue.Key;
                        var dependency          = dependencyValue.Value.AsTable();
                        var soupTargetDirectory = new Path(dependency["SoupTargetDirectory"].AsString());
                        var sharedStateFile     = soupTargetDirectory + BuildConstants.GenerateSharedStateFileName;

                        // Load the shared state file
                        if (!ValueTableManager.TryLoadState(sharedStateFile, out var sharedStateTable))
                        {
                            Log.Error("Failed to load the shared state file: " + sharedStateFile.ToString());
                            throw new InvalidOperationException("Failed to load shared state file.");
                        }

                        // Add the shared build state from this child build into the correct
                        // table depending on the build type
                        var typedDependenciesTable = EnsureValueTable(sharedDependenciesTable, dependencyType);
                        typedDependenciesTable.Add(
                            dependencyName,
                            new Value(sharedStateTable));
                    }
                }
            }

            return(sharedDependenciesTable);
        }
Пример #3
0
        /// <summary>
        /// Execute the entire operation graph that is referenced by this build generate engine.
        /// </summary>
        public async Task GenerateAsync(Path soupTargetDirectory)
        {
            // Run all build operations in the correct order with incremental build checks
            Log.Diag("Build generate start");

            // Load the parameters file
            var parametersFile = soupTargetDirectory + BuildConstants.GenerateParametersFileName;

            if (!ValueTableManager.TryLoadState(parametersFile, out var parametersState))
            {
                Log.Error("Failed to load the parameter file: " + parametersFile.ToString());
                throw new InvalidOperationException("Failed to load parameter file.");
            }

            // Load the read access file
            var readAccessFile = soupTargetDirectory + BuildConstants.GenerateReadAccessFileName;
            var readAccessList = new List <Path>();

            if (!await PathListManager.TryLoadFileAsync(readAccessFile, readAccessList))
            {
                Log.Error("Failed to load the read access file: " + readAccessFile.ToString());
                throw new InvalidOperationException("Failed to load read access file.");
            }

            // Load the write access file
            var writeAccessFile = soupTargetDirectory + BuildConstants.GenerateWriteAccessFileName;
            var writeAccessList = new List <Path>();

            if (!await PathListManager.TryLoadFileAsync(writeAccessFile, writeAccessList))
            {
                Log.Error("Failed to load the write access file: " + writeAccessFile.ToString());
                throw new InvalidOperationException("Failed to load write access file.");
            }

            // Get the required input state from the parameters
            var targetDirectory  = new Path(parametersState["TargetDirectory"].AsString().ToString());
            var packageDirectory = new Path(parametersState["PackageDirectory"].AsString().ToString());

            // Load the recipe file
            var recipeFile = packageDirectory + BuildConstants.RecipeFileName;

            var(isSuccess, recipe) = await RecipeExtensions.TryLoadRecipeFromFileAsync(recipeFile);

            if (!isSuccess)
            {
                Log.Error("Failed to load the recipe: " + recipeFile.ToString());
                throw new InvalidOperationException("Failed to load recipe.");
            }

            // Combine all the dependencies shared state
            var dependenciesSharedState = LoadDependenciesSharedState(parametersState);

            // Generate the set of build extension libraries
            var buildExtensionLibraries = GenerateBuildExtensionSet(recipe, dependenciesSharedState);

            // Start a new active state that is initialized to the recipe itself
            var activeState = new ValueTable();

            // Initialize the Recipe Root Table
            var recipeState = recipe.Table;

            activeState.Add("Recipe", new Value(recipeState));

            // Initialize the Parameters Root Table
            activeState.Add("Parameters", new Value(parametersState));

            // Initialize the Dependencies Root Table
            activeState.Add("Dependencies", new Value(dependenciesSharedState));

            // Keep the extension libraries open while running the build system
            // to ensure their memory is kept alive
            var         evaluateGraph = new OperationGraph();
            IValueTable sharedState   = new ValueTable();

            {
                // Create a new build system for the requested build
                var buildTaskManager = new BuildTaskManager();

                // Run all build extension register callbacks
                foreach (var buildExtension in buildExtensionLibraries)
                {
                    var library = LoadPlugin(buildExtension);
                    FindAllCommands(library, buildTaskManager);
                }

                // Run the build
                var buildState = new BuildState(
                    activeState,
                    _fileSystemState,
                    readAccessList,
                    writeAccessList);
                buildTaskManager.Execute(buildState, soupTargetDirectory);

                // Grab the build results so the dependency libraries can be released asap
                evaluateGraph = buildState.BuildOperationGraph();
                sharedState   = buildState.SharedState;
            }

            // Save the operation graph so the evaluate phase can load it
            var evaluateGraphFile = soupTargetDirectory + BuildConstants.GenerateEvaluateOperationGraphFileName;

            OperationGraphManager.SaveState(evaluateGraphFile, evaluateGraph, _fileSystemState);

            // Save the shared state that is to be passed to the downstream builds
            var sharedStateFile = soupTargetDirectory + BuildConstants.GenerateSharedStateFileName;

            ValueTableManager.SaveState(sharedStateFile, sharedState);
            Log.Diag("Build generate end");
        }