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}"); } }
/// <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); }
/// <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"); }