public override SdkResult ResolveSdk(int submissionId, SdkReference sdk, LoggingContext loggingContext, ElementLocation sdkReferenceLocation, string solutionPath, string projectPath, bool interactive, bool isRunningInVisualStudio)
        {
            bool wasResultCached = true;

            MSBuildEventSource.Log.OutOfProcSdkResolverServiceRequestSdkPathFromMainNodeStart(submissionId, sdk.Name, solutionPath, projectPath);

            // Get a cached response if possible, otherwise send the request
            Lazy <SdkResult> sdkResultLazy = _responseCache.GetOrAdd(
                sdk.Name,
                key => new Lazy <SdkResult>(() =>
            {
                wasResultCached = false;

                return(RequestSdkPathFromMainNode(submissionId, sdk, loggingContext, sdkReferenceLocation, solutionPath, projectPath, interactive, isRunningInVisualStudio));
            }));

            SdkResult sdkResult = sdkResultLazy.Value;

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

            MSBuildEventSource.Log.OutOfProcSdkResolverServiceRequestSdkPathFromMainNodeStop(submissionId, sdk.Name, solutionPath, projectPath, _lastResponse.Success, wasResultCached);

            return(sdkResult);
        }
        /// <summary>
        /// Processes all requests that are currently in the queue.
        /// </summary>
        private void ProcessRequests()
        {
            // Store a list of threads which are resolving SDKs
            List <Task> tasks = new List <Task>(_requests.Count);

            SdkResolverRequest item;

            while (_requests.TryDequeue(out item))
            {
                SdkResolverRequest request = item;

                // Start a thread to resolve an SDK and add it to the list of threads
                tasks.Add(Task.Run(() =>
                {
                    // Create an SdkReference from the request
                    SdkReference sdkReference = new SdkReference(request.Name, request.Version, request.MinimumVersion);

                    ILoggingService loggingService = Host.GetComponent(BuildComponentType.LoggingService) as ILoggingService;

                    // This call is usually cached so is very fast but can take longer for a new SDK that is downloaded.  Other queued threads for different SDKs will complete sooner and continue on which unblocks evaluations
                    SdkResult result = GetSdkResultAndCache(request.SubmissionId, sdkReference, new EvaluationLoggingContext(loggingService, request.BuildEventContext, request.ProjectPath), request.ElementLocation, request.SolutionPath, request.ProjectPath);

                    // Create a response
                    SdkResolverResponse response = new SdkResolverResponse(result.Path, result.Version);

                    // Get the node manager and send the response back to the node that requested the SDK
                    INodeManager nodeManager = Host.GetComponent(BuildComponentType.NodeManager) as INodeManager;

                    nodeManager.SendData(request.NodeId, response);
                }));
            }

            // Wait for all tasks to complete
            Task.WaitAll(tasks.ToArray());
        }
        /// <summary>
        /// Handles a response from the main node.
        /// </summary>
        /// <param name="response"></param>
        private void HandleResponse(SdkResult response)
        {
            // Store the last response so the awaiting thread can use it
            _lastResponse = response;

            // Signal that a response has been received
            _responseReceivedEvent.Set();
        }
Exemplo n.º 4
0
            private SdkResult CloneSdkResult(SdkResult sdkResult)
            {
                if (!sdkResult.Success)
                {
                    return(new SdkResult(sdkResult.SdkReference, sdkResult.Warnings, sdkResult.Errors));
                }

                IEnumerable <string> sdkResultPaths;

                if (sdkResult.Path == null)
                {
                    sdkResultPaths = Enumerable.Empty <string>();
                }
                else
                {
                    List <string> pathList = new List <string>();
                    pathList.Add(sdkResult.Path);
                    if (sdkResult.AdditionalPaths != null)
                    {
                        pathList.AddRange(sdkResult.AdditionalPaths);
                    }
                    sdkResultPaths = pathList;
                }

                Dictionary <string, SdkResultItem> sdkResultItems;

                if (sdkResult.ItemsToAdd == null)
                {
                    sdkResultItems = null;
                }
                else
                {
                    sdkResultItems = new Dictionary <string, SdkResultItem>(StringComparer.OrdinalIgnoreCase);
                    foreach (var item in sdkResult.ItemsToAdd)
                    {
                        Dictionary <string, string> newMetadata = null;
                        if (item.Value.Metadata != null)
                        {
                            newMetadata = new Dictionary <string, string>(item.Value.Metadata, StringComparer.OrdinalIgnoreCase);
                        }
                        sdkResultItems.Add(item.Key, new SdkResultItem(item.Value.ItemSpec, newMetadata));
                    }
                }

                return(new SdkResult(sdkResult.SdkReference,
                                     sdkResultPaths,
                                     version: sdkResult.Version,
                                     sdkResult.PropertiesToAdd == null ? null : new Dictionary <string, string>(sdkResult.PropertiesToAdd, StringComparer.OrdinalIgnoreCase),
                                     sdkResultItems,
                                     sdkResult.Warnings));
            }
        /// <summary>
        /// Resolves the specified SDK without caching the result.
        /// </summary>
        /// <param name="submissionId">The current build submission ID that is resolving an SDK.</param>
        /// <param name="sdk">The <see cref="SdkReference"/> containing information about the SDK to resolve.</param>
        /// <param name="loggingContext">The <see cref="LoggingContext"/> to use when logging messages during resolution.</param>
        /// <param name="sdkReferenceLocation">The <see cref="ElementLocation"/> of the element that referenced the SDK.</param>
        /// <param name="solutionPath">The full path to the solution, if any, that is being built.</param>
        /// <param name="projectPath">The full path to the project that referenced the SDK.</param>
        /// <returns>An <see cref="SdkResult"/> containing information about the SDK if one was resolved, otherwise <code>null</code>.</returns>
        private SdkResult GetSdkResult(int submissionId, SdkReference sdk, LoggingContext loggingContext, ElementLocation sdkReferenceLocation, string solutionPath, string projectPath)
        {
            SdkResult sdkResult = SdkResolverService.Instance.GetSdkResult(submissionId, sdk, loggingContext, sdkReferenceLocation, solutionPath, projectPath);

            if (sdkResult != null)
            {
                if (!SdkResolverService.IsReferenceSameVersion(sdk, sdkResult.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, sdkResult.Version);
                }

                // Associate the element location of the resolved SDK reference
                sdkResult.ElementLocation = sdkReferenceLocation;
            }

            return(sdkResult);
        }
        private SdkResult RequestSdkPathFromMainNode(int submissionId, SdkReference sdk, LoggingContext loggingContext, ElementLocation sdkReferenceLocation, string solutionPath, string projectPath, bool interactive)
        {
            // Clear out the last response for good measure
            _lastResponse = null;

            // Create the SdkResolverRequest packet to send
            INodePacket packet = SdkResolverRequest.Create(submissionId, sdk, loggingContext.BuildEventContext, sdkReferenceLocation, solutionPath, projectPath, interactive);

            SendPacket(packet);

            // Wait for either the response or a shutdown event.  Either event means this thread should return
            WaitHandle.WaitAny(new WaitHandle[] { _responseReceivedEvent, ShutdownEvent });

            // Keep track of the element location of the reference
            _lastResponse.ElementLocation = sdkReferenceLocation;

            // Return the response which was set by another thread.  In the case of shutdown, it should be null.
            return(_lastResponse);
        }
        public override void PacketReceived(int node, INodePacket packet)
        {
            if (packet is not SdkResolverRequest request)
            {
                return;
            }

            // Associate the node with the request
            request.NodeId = node;

            SdkResult response = null;

            try
            {
                // Create an SdkReference from the request
                SdkReference sdkReference = new SdkReference(request.Name, request.Version, request.MinimumVersion);

                ILoggingService loggingService = Host.GetComponent(BuildComponentType.LoggingService) as ILoggingService;

                // This call is usually cached so is very fast but can take longer for a new SDK that is downloaded.  Other queued threads for different SDKs will complete sooner and continue on which unblocks evaluations
                response = ResolveSdk(request.SubmissionId, sdkReference, new EvaluationLoggingContext(loggingService, request.BuildEventContext, request.ProjectPath), request.ElementLocation, request.SolutionPath, request.ProjectPath, request.Interactive, request.IsRunningInVisualStudio);
            }
            catch (Exception e)
            {
                ILoggingService loggingService = Host.GetComponent(BuildComponentType.LoggingService) as ILoggingService;

                EvaluationLoggingContext loggingContext = new EvaluationLoggingContext(loggingService, request.BuildEventContext, request.ProjectPath);

                loggingService.LogFatalBuildError(loggingContext.BuildEventContext, e, new BuildEventFileInfo(request.ElementLocation));
            }
            finally
            {
                // Get the node manager and send the response back to the node that requested the SDK
                INodeManager nodeManager = Host.GetComponent(BuildComponentType.NodeManager) as INodeManager;

                nodeManager.SendData(request.NodeId, response);
            }
        }
        private static void LogWarnings(LoggingContext loggingContext, ElementLocation location, SdkResult result)
        {
            if (result.Warnings == null)
            {
                return;
            }

            foreach (string warning in result.Warnings)
            {
                loggingContext.LogWarningFromText(null, null, null, new BuildEventFileInfo(location), warning);
            }
        }
        /// <inheritdoc cref="ISdkResolverService.ResolveSdk"/>
        public override string ResolveSdk(int submissionId, SdkReference sdk, LoggingContext loggingContext, ElementLocation sdkReferenceLocation, string solutionPath, string projectPath)
        {
            SdkResult result = GetSdkResultAndCache(submissionId, sdk, loggingContext, sdkReferenceLocation, solutionPath, projectPath);

            return(result?.Path);
        }
Exemplo n.º 10
0
 public ConfigurableMockSdkResolver(SdkResult result)
 {
     _resultMap = new Dictionary <string, SdkResult> {
         [result.SdkReference.Name] = result
     };
 }
Exemplo n.º 11
0
        private bool TryResolveSdkUsingSpecifiedResolvers(IList <SdkResolver> resolvers, int submissionId, SdkReference sdk, LoggingContext loggingContext, ElementLocation sdkReferenceLocation, string solutionPath, string projectPath, bool interactive, bool isRunningInVisualStudio, out SdkResult sdkResult)
        {
            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, projectPath, solutionPath, ProjectCollection.Version, interactive, isRunningInVisualStudio)
                {
                    State = GetResolverState(submissionId, sdkResolver)
                };

                SdkResultFactory resultFactory = new SdkResultFactory(sdk);

                SdkResult result;

                try
                {
                    MSBuildEventSource.Log.SdkResolverResolveSdkStart();
                    result = (SdkResult)sdkResolver.Resolve(sdk, context, resultFactory);
                    MSBuildEventSource.Log.SdkResolverResolveSdkStop(sdkResolver.Name, sdk.Name, solutionPath, projectPath, result?.Path, result?.Success ?? false);
                }
                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
                    // 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}
                    throw new SdkResolverException("CouldNotRunNuGetSdkResolver", sdkResolver, sdk, e, MSBuildConstants.NuGetAssemblyPathEnvironmentVariableName, e.ToString());
                }
                catch (Exception e)
                {
                    // The SDK resolver "{0}" failed while attempting to resolve the SDK "{1}": {2}
                    throw new SdkResolverException("SDKResolverFailed", sdkResolver, sdk, e, sdkResolver.Name, sdk.ToString(), e.ToString());
                }

                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;

                    sdkResult = result;
                    return(true);
                }

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

            sdkResult = new SdkResult(sdk, null, null);
            return(false);
        }