Example #1
0
 private List <SdkResolver> InitSdkResolvers(SdkEnv sdkEnv, List <SdkResolver> resolvers)
 {
     if (!sdkEnv.toolsOptions.DisablePredefinedSdkResolvers)
     {
         resolvers.AddRange(GetPredefinedSdkResolvers());
         return(resolvers);
     }
     return(resolvers);
 }
Example #2
0
        /// <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));
        }
Example #3
0
        /// <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));
        }
Example #4
0
        private void Initialize(LoggingContext loggingContext, ElementLocation location, SdkEnv sdkEnv)
        {
            lock (_lockObject)
            {
                if (_resolvers != null)
                {
                    return;
                }

                _resolvers = _sdkResolverLoader.LoadResolvers(loggingContext, location, sdkEnv);
            }
        }
Example #5
0
 /// <inheritdoc cref="ISdkResolverService.ResolveSdk"/>
 public abstract SdkResult ResolveSdk(int submissionId, SdkReference sdk, LoggingContext loggingContext, ElementLocation sdkReferenceLocation, SdkEnv sdkEnv, bool interactive);
Example #6
0
        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));
        }
Example #7
0
        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);
        }
Example #8
0
        /// <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);
        }