/// <summary>
        /// Fetches the right target from the targets section in a lock file, or attempts to find a "best match" if allowed. The "best match" logic
        /// is there to allow a design time build for the IDE to generally work even if something isn't quite right. Throws an exception
        /// if either the preferred isn't there and fallbacks aren't allowed, or fallbacks are allowed but nothing at all could be found.
        /// </summary>
        /// <param name="lockFile">The lock file JSON.</param>
        /// <param name="needsRuntimeIdentifier">Whether we must find targets that include the runtime identifier or one without the runtime identifier.</param>
        private JObject GetTargetOrAttemptFallback(JObject lockFile, bool needsRuntimeIdentifier)
        {
            var targets = (JObject)lockFile["targets"];

            foreach (var preferredTargetMoniker in TargetMonikers)
            {
                var preferredTargetMonikerWithOptionalRuntimeIdentifier = GetTargetMonikerWithOptionalRuntimeIdentifier(preferredTargetMoniker, needsRuntimeIdentifier);
                var target = (JObject)targets[preferredTargetMonikerWithOptionalRuntimeIdentifier];

                if (target != null)
                {
                    return(target);
                }
            }

            // If we need a runtime identifier, let's see if we have the framework targeted. If we do,
            // then we can give a better error message.
            bool onlyNeedsRuntimeInProjectJson = false;

            if (needsRuntimeIdentifier)
            {
                foreach (var targetMoniker in TargetMonikers)
                {
                    var targetMonikerWithoutRuntimeIdentifier = GetTargetMonikerWithOptionalRuntimeIdentifier(targetMoniker, needsRuntimeIdentifier: false);
                    if (targets[targetMonikerWithoutRuntimeIdentifier] != null)
                    {
                        // We do have a TXM being targeted, so we just are missing the runtime
                        onlyNeedsRuntimeInProjectJson = true;
                        break;
                    }
                }
            }

            if (onlyNeedsRuntimeInProjectJson)
            {
                GiveErrorForMissingRuntimeIdentifier();
            }
            else
            {
                ThrowExceptionIfNotAllowingFallback(nameof(Strings.MissingFramework), TargetMonikers.First().ItemSpec);
            }

            // If we're still here, that means we're allowing fallback, so let's try
            foreach (var fallback in TargetMonikers)
            {
                var target = (JObject)targets[GetTargetMonikerWithOptionalRuntimeIdentifier(fallback, needsRuntimeIdentifier: false)];

                if (target != null)
                {
                    return(target);
                }
            }

            // Anything goes
            var enumerableTargets = targets.Cast <KeyValuePair <string, JToken> >();
            var firstTarget       = (JObject)enumerableTargets.FirstOrDefault().Value;

            if (firstTarget == null)
            {
                throw new ExceptionFromResource(nameof(Strings.NoTargetsInLockFile));
            }

            return(firstTarget);
        }
예제 #2
0
        /// <summary>
        /// Generates a table in markdown that lists the API version supported by
        /// various packages at all levels of NETStandard.
        /// </summary>
        /// <returns></returns>
        public override bool Execute()
        {
            if (PackageAssets == null || PackageAssets.Length == 0)
            {
                Log.LogError("PackageAssets argument must be specified");
                return(false);
            }

            if (TargetMonikers == null || TargetMonikers.Length == 0)
            {
                Log.LogError("TargetMoniker argument must be specified");
                return(false);
            }

            NuGetFramework[] compileFxs = TargetMonikers.Select(fx => NuGetFramework.Parse(fx)).ToArray();
            NuGetFramework[] runtimeFxs = compileFxs;

            if (RuntimeTargetMonikers != null && RuntimeTargetMonikers.Length > 0)
            {
                runtimeFxs = RuntimeTargetMonikers.Select(fx => NuGetFramework.Parse(fx)).ToArray();
            }

            LoadFiles();

            CompileAssets = null;
            // find the best framework
            foreach (var compileFx in compileFxs)
            {
                var compileAssets = _resolver.ResolveCompileAssets(compileFx);

                if (compileAssets.Any())
                {
                    CompileAssets = compileAssets.Where(ca => !NuGetAssetResolver.IsPlaceholder(ca))
                                    .Select(ca => PackageItemAsResolvedAsset(_targetPathToPackageItem[ca]))
                                    .ToArray();
                    Log.LogMessage($"Resolved compile assets from {compileFx.ToString()}: {String.Join(";", CompileAssets.Select(c => c.ItemSpec))}");
                    break;
                }
            }

            if (CompileAssets == null)
            {
                Log.LogError($"Could not locate compile assets for any of the frameworks {String.Join(";", compileFxs.Select(fx => fx.ToString()))}");
            }

            RuntimeAssets = null;
            foreach (var runtimeFx in runtimeFxs)
            {
                var runtimeAssets = _resolver.ResolveRuntimeAssets(runtimeFx, TargetRuntime);

                if (runtimeAssets.Any())
                {
                    RuntimeAssets = runtimeAssets.Where(ra => !NuGetAssetResolver.IsPlaceholder(ra))
                                    .SelectMany(ra => PackageItemAndSymbolsAsResolvedAsset(_targetPathToPackageItem[ra]))
                                    .ToArray();

                    Log.LogMessage($"Resolved runtime assets from {runtimeFx.ToString()}: {String.Join(";", RuntimeAssets.Select(r => r.ItemSpec))}");
                    break;
                }
            }

            if (RuntimeAssets == null)
            {
                Log.LogError($"Could not locate runtime assets for any of the frameworks {String.Join(";", runtimeFxs.Select(fx => fx.ToString()))}");
            }

            return(!Log.HasLoggedErrors);
        }
예제 #3
0
        /// <summary>
        /// Fetches the right target from the targets section in a lock file, or attempts to find a "best match" if allowed. The "best match" logic
        /// is there to allow a design time build for the IDE to generally work even if something isn't quite right. Throws an exception
        /// if either the preferred isn't there and fallbacks aren't allowed, or fallbacks are allowed but nothing at all could be found.
        /// </summary>
        /// <param name="lockFile">The lock file JSON.</param>
        /// <param name="needsRuntimeIdentifier">Whether we must find targets that include the runtime identifier or one without the runtime identifier.</param>
        private JObject GetTargetOrAttemptFallback(JObject lockFile, bool needsRuntimeIdentifier)
        {
            var targets = (JObject)lockFile["targets"];

            foreach (var preferredTargetMoniker in TargetMonikers)
            {
                var preferredTargetMonikerWithOptionalRuntimeIdentifier = GetTargetMonikerWithOptionalRuntimeIdentifier(preferredTargetMoniker, needsRuntimeIdentifier);
                var target = (JObject)targets[preferredTargetMonikerWithOptionalRuntimeIdentifier];

                if (target != null)
                {
                    return(target);
                }
            }

            var preferredForErrorMessages = GetTargetMonikerWithOptionalRuntimeIdentifier(TargetMonikers.First(), needsRuntimeIdentifier);

            if (!AllowFallbackOnTargetSelection)
            {
                // If we're not falling back then abort the build
                throw new ExceptionFromResource("MissingEntryInLockFile", preferredForErrorMessages);
            }

            // We are allowing fallback, so we'll still give a warning but allow us to continue
            // In production ResolveNuGetPackageAssets, this call is LogWarningFromResources.
            // In our current use in dotnet\buildtools, we rely on the fallback behavior, so we just log
            // this as a message.
            Log.LogMessageFromResources("MissingEntryInLockFile", preferredForErrorMessages);

            foreach (var fallback in TargetMonikers)
            {
                var target = (JObject)targets[GetTargetMonikerWithOptionalRuntimeIdentifier(fallback, needsRuntimeIdentifier: false)];

                if (target != null)
                {
                    return(target);
                }
            }

            // Anything goes
            var enumerableTargets = targets.Cast <KeyValuePair <string, JToken> >();
            var firstTarget       = (JObject)enumerableTargets.FirstOrDefault().Value;

            if (firstTarget == null)
            {
                throw new ExceptionFromResource("NoTargetsInLockFile");
            }

            return(firstTarget);
        }