private List <SdkResolver> InitSdkResolvers(SdkEnv sdkEnv, List <SdkResolver> resolvers) { if (!sdkEnv.toolsOptions.DisablePredefinedSdkResolvers) { resolvers.AddRange(GetPredefinedSdkResolvers()); return(resolvers); } return(resolvers); }
/// <inheritdoc cref="ISdkResolverService.ResolveSdk"/> public override SdkResult ResolveSdk(int submissionId, SdkReference sdk, LoggingContext loggingContext, ElementLocation sdkReferenceLocation, SdkEnv sdkEnv, bool interactive) { ErrorUtilities.VerifyThrowInternalNull(sdk, nameof(sdk)); ErrorUtilities.VerifyThrowInternalNull(loggingContext, nameof(loggingContext)); ErrorUtilities.VerifyThrowInternalNull(sdkReferenceLocation, nameof(sdkReferenceLocation)); ErrorUtilities.VerifyThrowInternalLength(sdkEnv.projectPath, nameof(sdkEnv.projectPath)); return(_cachedSdkResolver.ResolveSdk(submissionId, sdk, loggingContext, sdkReferenceLocation, sdkEnv, interactive)); }
/// <inheritdoc cref="ISdkResolverService.ResolveSdk"/> public virtual SdkResult ResolveSdk(int submissionId, SdkReference sdk, LoggingContext loggingContext, ElementLocation sdkReferenceLocation, SdkEnv sdkEnv, bool interactive) { // Lazy initialize the SDK resolvers if (_resolvers == null) { Initialize(loggingContext, sdkReferenceLocation, sdkEnv); } List <SdkResult> results = new List <SdkResult>(); // Loop through resolvers which have already been sorted by priority, returning the first result that was successful SdkLogger buildEngineLogger = new SdkLogger(loggingContext); loggingContext.LogComment(MessageImportance.Low, "SdkResolving", sdk.ToString()); foreach (SdkResolver sdkResolver in _resolvers) { SdkResolverContext context = new SdkResolverContext(buildEngineLogger, sdkEnv.projectPath, sdkEnv.solutionPath, ProjectCollection.Version, interactive) { State = GetResolverState(submissionId, sdkResolver) }; SdkResultFactory resultFactory = new SdkResultFactory(sdk); SdkResult result; try { result = (SdkResult)sdkResolver.Resolve(sdk, context, resultFactory); } catch (Exception e) when(e is FileNotFoundException || e is FileLoadException && sdkResolver.GetType().GetTypeInfo().Name.Equals("NuGetSdkResolver", StringComparison.Ordinal)) { // Since we explicitly add the NuGetSdkResolver, we special case this. The NuGetSdkResolver has special logic // to load NuGet assemblies at runtime which could fail if the user is not running installed MSBuild. Rather // than give them a generic error, we want to give a more specific message. This exception cannot be caught by // the resolver itself because it is usually thrown before the class is loaded // MSB4243: The NuGet-based SDK resolver failed to run because NuGet assemblies could not be located. Check your installation of MSBuild or set the environment variable "{0}" to the folder that contains the required NuGet assemblies. {1} loggingContext.LogWarning(null, new BuildEventFileInfo(sdkReferenceLocation), "CouldNotRunNuGetSdkResolver", MSBuildConstants.NuGetAssemblyPathEnvironmentVariableName, e.Message); continue; } catch (Exception e) { // MSB4242: The SDK resolver "{0}" failed to run. {1} loggingContext.LogWarning(null, new BuildEventFileInfo(sdkReferenceLocation), "CouldNotRunSdkResolver", sdkResolver.Name, e.Message); continue; } SetResolverState(submissionId, sdkResolver, context.State); if (result == null) { continue; } if (result.Success) { LogWarnings(loggingContext, sdkReferenceLocation, result); if (!IsReferenceSameVersion(sdk, result.Version)) { // MSB4241: The SDK reference "{0}" version "{1}" was resolved to version "{2}" instead. You could be using a different version than expected if you do not update the referenced version to match. loggingContext.LogWarning(null, new BuildEventFileInfo(sdkReferenceLocation), "SdkResultVersionDifferentThanReference", sdk.Name, sdk.Version, result.Version); } // Associate the element location of the resolved SDK reference result.ElementLocation = sdkReferenceLocation; return(result); } results.Add(result); } foreach (SdkResult result in results) { LogWarnings(loggingContext, sdkReferenceLocation, result); if (result.Errors != null) { foreach (string error in result.Errors) { loggingContext.LogErrorFromText(subcategoryResourceName: null, errorCode: null, helpKeyword: null, file: new BuildEventFileInfo(sdkReferenceLocation), message: error); } } } return(new SdkResult(sdk, null, null)); }
private void Initialize(LoggingContext loggingContext, ElementLocation location, SdkEnv sdkEnv) { lock (_lockObject) { if (_resolvers != null) { return; } _resolvers = _sdkResolverLoader.LoadResolvers(loggingContext, location, sdkEnv); } }
/// <inheritdoc cref="ISdkResolverService.ResolveSdk"/> public abstract SdkResult ResolveSdk(int submissionId, SdkReference sdk, LoggingContext loggingContext, ElementLocation sdkReferenceLocation, SdkEnv sdkEnv, bool interactive);
internal virtual IList <SdkResolver> LoadResolvers(LoggingContext loggingContext, ElementLocation location, SdkEnv sdkEnv) { ErrorUtilities.VerifyThrowArgumentNull(sdkEnv.toolsOptions, nameof(sdkEnv.toolsOptions)); var resolvers = InitSdkResolvers(sdkEnv, new List <SdkResolver>(sdkEnv.toolsOptions.SdkResolvers) { new DefaultSdkResolver() // Always add the default resolver }); var potentialResolvers = new List <string>(); foreach (var sdkpath in sdkEnv.toolsOptions.SdkResolversPaths) { potentialResolvers.AddRange(FindPotentialSdkResolvers(sdkpath, location)); } if (potentialResolvers.Count == 0) { return(Order(resolvers)); } foreach (var potentialResolver in potentialResolvers) { LoadResolvers(potentialResolver, loggingContext, location, resolvers); } return(Order(resolvers)); }
public override SdkResult ResolveSdk(int submissionId, SdkReference sdk, LoggingContext loggingContext, ElementLocation sdkReferenceLocation, SdkEnv sdkEnv, bool interactive) { SdkResult result; if (Traits.Instance.EscapeHatches.DisableSdkResolutionCache) { result = base.ResolveSdk(submissionId, sdk, loggingContext, sdkReferenceLocation, sdkEnv, interactive); } else { // Get the dictionary for the specified submission if one is already added otherwise create a new dictionary for the submission. ConcurrentDictionary <string, Lazy <SdkResult> > cached = _cache.GetOrAdd(submissionId, new ConcurrentDictionary <string, Lazy <SdkResult> >(MSBuildNameIgnoreCaseComparer.Default)); /* * Get a Lazy<SdkResult> if available, otherwise create a Lazy<SdkResult> which will resolve the SDK with the SdkResolverService.Instance. If multiple projects are attempting to resolve * the same SDK, they will all get back the same Lazy<SdkResult> which ensures that a single build submission resolves each unique SDK only one time. */ Lazy <SdkResult> resultLazy = cached.GetOrAdd( sdk.Name, key => new Lazy <SdkResult>(() => base.ResolveSdk(submissionId, sdk, loggingContext, sdkReferenceLocation, sdkEnv, interactive))); // Get the lazy value which will block all waiting threads until the SDK is resolved at least once while subsequent calls get cached results. result = resultLazy.Value; } if (result != null && !SdkResolverService.IsReferenceSameVersion(sdk, result.SdkReference.Version) && !SdkResolverService.IsReferenceSameVersion(sdk, result.Version)) { // MSB4240: Multiple versions of the same SDK "{0}" cannot be specified. The previously resolved SDK version "{1}" from location "{2}" will be used and the version "{3}" will be ignored. loggingContext.LogWarning(null, new BuildEventFileInfo(sdkReferenceLocation), "ReferencingMultipleVersionsOfTheSameSdk", sdk.Name, result.Version, result.ElementLocation, sdk.Version); } return(result); }
/// <inheritdoc cref="ISdkResolverService.ResolveSdk"/> public override SdkResult ResolveSdk(int submissionId, SdkReference sdk, LoggingContext loggingContext, ElementLocation sdkReferenceLocation, SdkEnv sdkEnv, bool interactive) { // Get a cached response if possible, otherwise send the request var sdkResult = _responseCache.GetOrAdd( sdk.Name, key => { var result = RequestSdkPathFromMainNode(submissionId, sdk, loggingContext, sdkReferenceLocation, sdkEnv.solutionPath, sdkEnv.projectPath, interactive); return(new SdkResult(null, result.Path, result.Version, null)); }); if (sdkResult.Version != null && !SdkResolverService.IsReferenceSameVersion(sdk, sdkResult.Version)) { // MSB4240: Multiple versions of the same SDK "{0}" cannot be specified. The SDK version "{1}" already specified by "{2}" will be used and the version "{3}" will be ignored. loggingContext.LogWarning(null, new BuildEventFileInfo(sdkReferenceLocation), "ReferencingMultipleVersionsOfTheSameSdk", sdk.Name, sdkResult.Version, sdkResult.ElementLocation, sdk.Version); } return(sdkResult); }