/// <summary> /// Loads configured symlink definitions (if not already loaded) /// Stores to cache for use by workers in distributed build /// Eagerly creates symlinks if lazy symlink creation is disabled /// </summary> public static async Task <Possible <SymlinkDefinitions> > TryPrepareSymlinkDefinitionsAsync( LoggingContext loggingContext, GraphReuseResult reuseResult, IConfiguration configuration, MasterService masterService, CacheInitializationTask cacheInitializerTask, PipExecutionContext context, ITempDirectoryCleaner tempDirectoryCleaner = null) { var pathTable = context.PathTable; bool isDistributedMaster = configuration.Distribution.BuildRole == DistributedBuildRoles.Master; Possible <SymlinkDefinitions> maybeSymlinkDefinitions = new Possible <SymlinkDefinitions>((SymlinkDefinitions)null); if (reuseResult?.IsFullReuse == true) { maybeSymlinkDefinitions = reuseResult.EngineSchedule.Scheduler.SymlinkDefinitions; } else if (configuration.Layout.SymlinkDefinitionFile.IsValid) { var symlinkFilePath = configuration.Layout.SymlinkDefinitionFile.ToString(pathTable); Logger.Log.SymlinkFileTraceMessage(loggingContext, I($"Loading symlink file from location '{symlinkFilePath}'.")); maybeSymlinkDefinitions = await SymlinkDefinitions.TryLoadAsync( loggingContext, pathTable, symlinkFilePath, symlinksDebugPath : configuration.Logging.LogsDirectory.Combine(pathTable, "DebugSymlinksDefinitions.log").ToString(pathTable), tempDirectoryCleaner : tempDirectoryCleaner); } if (!maybeSymlinkDefinitions.Succeeded || maybeSymlinkDefinitions.Result == null) { return(maybeSymlinkDefinitions); } // Need to store symlinks to cache for workers if (configuration.Distribution.BuildRole == DistributedBuildRoles.Master) { var possibleCacheInitializer = await cacheInitializerTask; if (!possibleCacheInitializer.Succeeded) { return(possibleCacheInitializer.Failure); } Logger.Log.SymlinkFileTraceMessage(loggingContext, I($"Storing symlink file for use by workers.")); var symlinkFile = configuration.Layout.SymlinkDefinitionFile.Expand(pathTable); var possibleStore = await TryStoreToCacheAsync( loggingContext, cache : possibleCacheInitializer.Result.CreateCacheForContext(context).ArtifactContentCache, symlinkFile : symlinkFile); if (!possibleStore.Succeeded) { return(possibleStore.Failure); } masterService.SymlinkFileContentHash = possibleStore.Result; Logger.Log.SymlinkFileTraceMessage(loggingContext, I($"Stored symlink file for use by workers.")); } if (!configuration.Schedule.UnsafeLazySymlinkCreation || configuration.Engine.PopulateSymlinkDirectories.Count != 0) { // Symlink definition file is defined, and BuildXL intends to create it eagerly. // At this point master and worker should have had its symlink definition file, if specified. if (!FileContentManager.CreateSymlinkEagerly(loggingContext, configuration, pathTable, maybeSymlinkDefinitions.Result, context.CancellationToken)) { return(new Failure <string>("Failed eagerly creating symlinks")); } } return(maybeSymlinkDefinitions); }