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 evaluateGraphFile = soupTargetDirectory + BuildConstants.GenerateEvaluateOperationGraphFileName; var fileSystemState = new FileSystemState(); if (!OperationGraphManager.TryLoadState(evaluateGraphFile, fileSystemState, out var evaluateGraph)) { NotifyError($"Failed to load Operation Graph: {evaluateGraphFile}"); return; } Graph = BuildGraph(fileSystemState, evaluateGraph); } else { NotifyError($"Failed to load Recipe file: {recipeFilePath}"); } }
/// <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"); }