public static ICommand Create( string project, string configuration, NuGetFramework framework, string buildBasePath, string output) { var args = new List<string>() { project, "--configuration", configuration, "--framework", framework.GetShortFolderName() }; if (buildBasePath != null) { args.Add("--build-base-path"); args.Add(buildBasePath); } if (output != null) { args.Add("--output"); args.Add(output); } return Command.CreateDotNet( "build", args, framework, configuration); }
public string GetLockFilePath(string packageId, NuGetVersion version, NuGetFramework framework) { return Path.Combine( GetBaseToolPath(packageId), version.ToNormalizedString(), framework.GetShortFolderName(), "project.lock.json"); }
public string GetLockFilePath(string packageId, NuGetVersion version, NuGetFramework framework) { if (version == null) { throw new ArgumentNullException(nameof(version)); } if (framework == null) { throw new ArgumentNullException(nameof(framework)); } return Path.Combine( GetBaseToolPath(packageId), version.ToNormalizedString(), framework.GetShortFolderName(), "project.lock.json"); }
// HACK(anurse): NuGet.Frameworks turns "dnxcore50" into "dnxcore5" :( public static string GetTwoDigitShortFolderName(this NuGetFramework self) { var original = self.GetShortFolderName(); var index = 0; for (; index < original.Length; index++) { if (char.IsDigit(original[index])) { break; } } var versionPart = original.Substring(index); if (versionPart.Length >= 2) { return(original); } // Assume if the version part was preserved then leave it alone if (versionPart.IndexOf('.') != -1) { return(original); } var name = original.Substring(0, index); var version = self.Version.ToString(2); if (self.Framework.Equals(FrameworkConstants.FrameworkIdentifiers.NetPlatform)) { return(name + version); } return(name + version.Replace(".", string.Empty)); }
private void LoadSupport() { _frameworks = new Dictionary<NuGetFramework, ValidationFramework>(); // determine which TxM:RIDs should be considered for support based on Frameworks item foreach (var framework in Frameworks) { NuGetFramework fx; try { fx = FrameworkUtilities.ParseNormalized(framework.ItemSpec); } catch (Exception ex) { Log.LogError($"Could not parse Framework {framework.ItemSpec}. {ex}"); continue; } if (fx.Equals(NuGetFramework.UnsupportedFramework)) { Log.LogError($"Did not recognize {framework.ItemSpec} as valid Framework."); continue; } string runtimeIdList = framework.GetMetadata("RuntimeIDs"); if (_frameworks.ContainsKey(fx)) { Log.LogError($"Framework {fx} has been listed in Frameworks more than once."); continue; } _frameworks[fx] = new ValidationFramework(fx); if (!String.IsNullOrWhiteSpace(runtimeIdList)) { _frameworks[fx].RuntimeIds = runtimeIdList.Split(';'); } } // keep a list of explicitly listed supported frameworks so that we can check for conflicts. HashSet<NuGetFramework> explicitlySupportedFrameworks = new HashSet<NuGetFramework>(); // determine what version should be supported based on SupportedFramework items foreach (var supportedFramework in SupportedFrameworks) { NuGetFramework fx; string fxString = supportedFramework.ItemSpec; bool isExclusiveVersion = fxString.Length > 1 && fxString[0] == '[' && fxString[fxString.Length - 1] == ']'; if (isExclusiveVersion) { fxString = fxString.Substring(1, fxString.Length - 2); } try { fx = FrameworkUtilities.ParseNormalized(fxString); } catch (Exception ex) { Log.LogError($"Could not parse TargetFramework {fxString} as a SupportedFramework. {ex}"); continue; } if (fx.Equals(NuGetFramework.UnsupportedFramework)) { Log.LogError($"Did not recognize TargetFramework {fxString} as a SupportedFramework."); continue; } Version supportedVersion; string version = supportedFramework.GetMetadata("Version"); try { supportedVersion = Version.Parse(version); } catch (Exception ex) { Log.LogError($"Could not parse Version {version} on SupportedFramework item {supportedFramework.ItemSpec}. {ex}"); continue; } ValidationFramework validationFramework = null; if (!_frameworks.TryGetValue(fx, out validationFramework)) { Log.LogError($"SupportedFramework {fx} was specified but is not part of the Framework list to use for validation."); continue; } if (explicitlySupportedFrameworks.Contains(fx)) { if (validationFramework.SupportedVersion != supportedVersion) { Log.LogError($"Framework {fx} has been listed in SupportedFrameworks more than once with different versions {validationFramework.SupportedVersion} and {supportedVersion}. Framework should only be listed once with the expected API version for that platform."); } continue; } explicitlySupportedFrameworks.Add(fx); validationFramework.SupportedVersion = supportedVersion; if (!isExclusiveVersion) { // find all frameworks of higher version, sorted by version ascending var higherFrameworks = _frameworks.Values.Where(vf => vf.Framework.Framework == fx.Framework && vf.Framework.Version > fx.Version).OrderBy(vf => vf.Framework.Version); foreach(var higherFramework in higherFrameworks) { if (higherFramework.SupportedVersion != null && higherFramework.SupportedVersion > supportedVersion) { // found an higher framework version a higher API version, stop applying this supported version break; } higherFramework.SupportedVersion = supportedVersion; } } } // determine which Frameworks should support inbox _frameworkSet = FrameworkSet.Load(FrameworkListsPath); foreach (IEnumerable<Framework> inboxFxGroup in _frameworkSet.Frameworks.Values) { foreach (Framework inboxFx in inboxFxGroup) { // get currently supported version to see if we have OOB'ed it Version inboxVersion = null; inboxFx.Assemblies.TryGetValue(ContractName, out inboxVersion); if (inboxVersion != null) { NuGetFramework fx = FrameworkUtilities.ParseNormalized(inboxFx.ShortName); ValidationFramework validationFramework = null; if (_frameworks.TryGetValue(fx, out validationFramework)) { Version supportedVersion = validationFramework.SupportedVersion; if (supportedVersion != null && (supportedVersion.Major > inboxVersion.Major || (supportedVersion.Major == inboxVersion.Major && supportedVersion.Minor > inboxVersion.Minor))) { // Higher major.minor Log.LogMessage(LogImportance.Low, $"Framework {fx} supported {ContractName} as inbox but the current supported version {supportedVersion} is higher in major.minor than inbox version {inboxVersion}. Assuming out of box."); continue; } else if (supportedVersion != null && supportedVersion < inboxVersion) { // Lower version Log.LogError($"Framework {fx} supports {ContractName} as inbox but the current supported version {supportedVersion} is lower than the inbox version {inboxVersion}"); } // equal major.minor, build.revision difference is permitted, prefer the version listed by ContractSupport item } if (validationFramework == null) { // we may not be explicitly validating for this framework so add it to validate inbox assets. _frameworks[fx] = validationFramework = new ValidationFramework(fx) { SupportedVersion = inboxVersion }; } validationFramework.IsInbox = true; } } } // for every framework we know about, also validate it's generation to ensure it can // be targeted by PCL. Even if a package only supports a single framework we still // want to include a portable reference assembly. This allows 3rd parties to add // their own implementation via a lineup/runtime.json. // only consider frameworks that support the contract at a specific version var portableFrameworks = _frameworks.Values.Where(fx => fx.SupportedVersion != null && fx.SupportedVersion != s_maxVersion).ToArray(); var genVersionSuppression = GetSuppressionValues(Suppression.PermitPortableVersionMismatch) ?? new HashSet<string>(); Dictionary<NuGetFramework, ValidationFramework> generationsToValidate = new Dictionary<NuGetFramework, ValidationFramework>(); foreach (var framework in portableFrameworks) { NuGetFramework generation = new NuGetFramework(_generationIdentifier, Generations.DetermineGenerationForFramework(framework.Framework, UseNetPlatform)); Log.LogMessage(LogImportance.Low, $"Validating {generation} for {ContractName}, {framework.SupportedVersion} since it is supported by {framework.Framework}"); ValidationFramework existingGeneration = null; if (generationsToValidate.TryGetValue(generation, out existingGeneration)) { if (!VersionUtility.IsCompatibleApiVersion(framework.SupportedVersion, existingGeneration.SupportedVersion) && !genVersionSuppression.Contains(framework.Framework.ToString())) { Log.LogError($"Framework {framework.Framework} supports {ContractName} at {framework.SupportedVersion} which is lower than {existingGeneration.SupportedVersion} supported by generation {generation.GetShortFolderName()}"); } } else { generationsToValidate.Add(generation, new ValidationFramework(generation) { SupportedVersion = framework.SupportedVersion }); } } foreach (var generation in generationsToValidate) { _frameworks.Add(generation.Key, generation.Value); } // for every generation supported explcitly in implementation, ensure // it can be targeted by PCL. foreach (var packageGroup in _resolver.GetAllRuntimeItems()) { var allGenerationalImplementations = packageGroup.Value .Where(contentGroup => FrameworkUtilities.IsGenerationMoniker(contentGroup.Properties[PropertyNames.TargetFrameworkMoniker] as NuGetFramework)) .SelectMany(contentGroup => contentGroup.Items.Select(item => _targetPathToPackageItem[AggregateNuGetAssetResolver.AsPackageSpecificTargetPath(packageGroup.Key, item.Path)])); foreach (var generationalImplementation in allGenerationalImplementations) { NuGetFramework generation = generationalImplementation.TargetFramework; if (_frameworks.ContainsKey(generation)) { continue; } Version supportedVersion = generationalImplementation.Version; Log.LogMessage(LogImportance.Low, $"Validating {generation} for {ContractName}, {supportedVersion} since it is supported by {generationalImplementation.TargetPath}"); _frameworks.Add(generation, new ValidationFramework(generation) { SupportedVersion = supportedVersion }); } } }
/// <summary> /// Sort PCLs using these criteria /// 1. Lowest number of frameworks (highest surface area) wins first /// 2. Profile with the highest version numbers wins next /// 3. String compare is used as a last resort /// </summary> private bool IsBetterPCL(NuGetFramework current, NuGetFramework considering) { Debug.Assert(considering.IsPCL && current.IsPCL, "This method should be used only to compare PCLs"); // Find all frameworks in the profile var consideringFrameworks = ExplodePortableFramework(considering, false); var currentFrameworks = ExplodePortableFramework(current, false); // The PCL with the least frameworks (highest surface area) goes first if (consideringFrameworks.Count() < currentFrameworks.Count()) { return(true); } else if (currentFrameworks.Count() < consideringFrameworks.Count()) { return(false); } // If both frameworks have the same number of frameworks take the framework that has the highest // overall set of framework versions // Find Frameworks that both profiles have in common var sharedFrameworkIds = consideringFrameworks.Select(f => f.Framework) .Where(f => currentFrameworks.Any(consideringFramework => StringComparer.OrdinalIgnoreCase.Equals(f, consideringFramework.Framework))); var consideringHighest = 0; var currentHighest = 0; // Determine which framework has the highest version of each shared framework foreach (var sharedId in sharedFrameworkIds) { var consideringFramework = consideringFrameworks.First(f => StringComparer.OrdinalIgnoreCase.Equals(f.Framework, sharedId)); var currentFramework = currentFrameworks.First(f => StringComparer.OrdinalIgnoreCase.Equals(f.Framework, sharedId)); if (consideringFramework.Version < currentFramework.Version) { currentHighest++; } else if (currentFramework.Version < consideringFramework.Version) { consideringHighest++; } } // Prefer the highest count if (currentHighest < consideringHighest) { return(true); } else if (consideringHighest < currentHighest) { return(false); } // Take the highest version of .NET if no winner could be determined, this is usually a good indicator of which is newer var consideringNet = consideringFrameworks.FirstOrDefault(f => StringComparer.OrdinalIgnoreCase.Equals(f.Framework, FrameworkConstants.FrameworkIdentifiers.Net)); var currentNet = currentFrameworks.FirstOrDefault(f => StringComparer.OrdinalIgnoreCase.Equals(f.Framework, FrameworkConstants.FrameworkIdentifiers.Net)); // Compare using .NET only if both frameworks have it. PCLs should always have .NET, but since users can make these strings up we should // try to handle that as best as possible. if (consideringNet != null && currentNet != null) { if (currentNet.Version < consideringNet.Version) { return(true); } else if (consideringNet.Version < currentNet.Version) { return(false); } } // In the very rare case that both frameworks are still equal, we have to pick one. // There is nothing but we need to be deterministic, so compare the profiles as strings. if (StringComparer.OrdinalIgnoreCase.Compare(considering.GetShortFolderName(_mappings), current.GetShortFolderName(_mappings)) < 0) { return(true); } return(false); }
private IEnumerable<string> GetRuntimeAssetFoldersForPromotion(ContentItemGroup runtimeAssets, NuGetFramework targetFramework, string targetFrameworkName) { if (runtimeAssets == null || runtimeAssets.Items.Count == 0) { return Enumerable.Empty<string>(); } if (runtimeAssets.Items.All(ci => NuGetAssetResolver.IsPlaceholder(ci.Path))) { return Enumerable.Empty<string>(); } if (targetFrameworkName == null) { targetFrameworkName = targetFramework.GetShortFolderName(); } var resolvedFramework = runtimeAssets.Properties["tfm"] as NuGetFramework; if (targetFramework.Equals(resolvedFramework)) { Log.LogMessage(LogImportance.Low, $"Not promoting explicit implementation for {targetFrameworkName}"); return Enumerable.Empty<string>(); } return NuGetAssetResolver.GetPackageTargetDirectories(runtimeAssets); }
private IEnumerable<string> GetObscuredAssetFolders(ContentItemGroup assets, ContentItemGroup obscuredAssets, NuGetFramework targetFramework, string targetFrameworkName, string expectedAssetFolder, string ignoredAssetFolder = null) { if (assets == null || assets.Items.Count == 0) { return Enumerable.Empty<string>(); } if (assets.Items.Any(ci => !NuGetAssetResolver.IsPlaceholder(ci.Path))) { return Enumerable.Empty<string>(); } if (targetFrameworkName == null) { targetFrameworkName = targetFramework.GetShortFolderName(); } var resolvedFramework = assets.Properties["tfm"] as NuGetFramework; if (targetFramework.Equals(resolvedFramework)) { Log.LogMessage(LogImportance.Low, $"Not overriding explicit placeholder for {targetFrameworkName}"); return Enumerable.Empty<string>(); } var obscuredAssetPaths = NuGetAssetResolver.GetPackageTargetDirectories(obscuredAssets); if (ignoredAssetFolder != null) { string ignoredFolder = ignoredAssetFolder + '/'; obscuredAssetPaths = obscuredAssetPaths.Where(i => -1 == i.IndexOf(ignoredFolder, StringComparison.OrdinalIgnoreCase)); } if (expectedAssetFolder != null) { var unexpectedAssetPaths = obscuredAssetPaths.Where(ri => !ri.StartsWith(expectedAssetFolder, StringComparison.OrdinalIgnoreCase)); foreach (var unexpectedAssetPath in unexpectedAssetPaths) { Log.LogWarning($"Unexpected targetPath {unexpectedAssetPath}. Expected only {expectedAssetFolder}."); } // filter after we've warned obscuredAssetPaths = obscuredAssetPaths.Except(unexpectedAssetPaths); } if (!obscuredAssetPaths.Any()) { // it's acceptable to have no override, this is the case for packages which // carry implementation in a runtime-specific package Log.LogMessage(LogImportance.Low, $"No {expectedAssetFolder} assets could be found to override inbox placeholder for {targetFrameworkName}."); } return obscuredAssetPaths; }
public static OutputPaths GetOutputPaths( Project project, NuGetFramework framework, string runtimeIdentifier, string configuration, string solutionRootPath, string buildBasePath, string outputPath) { string resolvedBuildBasePath; if (string.IsNullOrEmpty(buildBasePath)) { resolvedBuildBasePath = project.ProjectDirectory; } else { if (string.IsNullOrEmpty(solutionRootPath)) { resolvedBuildBasePath = Path.Combine(buildBasePath, project.Name); } else { resolvedBuildBasePath = project.ProjectDirectory.Replace(solutionRootPath, buildBasePath); } } var compilationOutputPath = PathUtility.EnsureTrailingSlash(Path.Combine(resolvedBuildBasePath, BinDirectoryName, configuration, framework.GetShortFolderName())); string runtimeOutputPath = null; if (string.IsNullOrEmpty(outputPath)) { if (!string.IsNullOrEmpty(runtimeIdentifier)) { runtimeOutputPath = PathUtility.EnsureTrailingSlash(Path.Combine(compilationOutputPath, runtimeIdentifier)); } else { // "Runtime" assets (i.e. the deps file) will be dropped to the compilation output path, because // we are building a RID-less target. runtimeOutputPath = compilationOutputPath; } } else { runtimeOutputPath = PathUtility.EnsureTrailingSlash(Path.GetFullPath(outputPath)); } var intermediateOutputPath = PathUtility.EnsureTrailingSlash(Path.Combine( resolvedBuildBasePath, ObjDirectoryName, configuration, framework.GetTwoDigitShortFolderName())); var compilationFiles = new CompilationOutputFiles(compilationOutputPath, project, configuration, framework); RuntimeOutputFiles runtimeFiles = null; if (runtimeOutputPath != null) { runtimeFiles = new RuntimeOutputFiles(runtimeOutputPath, project, configuration, framework); } return new OutputPaths(intermediateOutputPath, compilationOutputPath, runtimeOutputPath, compilationFiles, runtimeFiles); }
public DotNetFramework(NuGetFramework framework) { Name = framework.Framework; FriendlyName = framework.Framework; ShortName = framework.GetShortFolderName(); }
/// <summary> /// Возвращает информацию о файле пакета для указанного источника и фреймворка. /// </summary> /// <param name="packagePath">Путь к каталогу пакета.</param> /// <param name="sourcePath">Путь к файлу в каталоге пакетов.</param> /// <param name="sourcePart">Каталог файла пакета ('lib', 'content' и т.д.).</param> /// <param name="sourceFramework">Версия фремворка файла пакета.</param> private static PackageFile GetPackageItem(string packagePath, string sourcePath, string sourcePart, NuGetFramework sourceFramework) { // Путь файла в пакете обычно имеет вид 'lib/net45/some.dll' // или 'lib/some.dll' для NuGetFramework.AnyFramework sourcePath = sourcePath.Replace('/', Path.DirectorySeparatorChar); var installPath = sourcePath; // Определение части пути источника, которая указывает на NuGetFramework файла, // например, 'lib/net45/' или 'lib/' для NuGetFramework.AnyFramework var partFrameworkPath = sourcePart + Path.DirectorySeparatorChar; if (!Equals(sourceFramework, NuGetFramework.AnyFramework)) { partFrameworkPath += sourceFramework.GetShortFolderName() + Path.DirectorySeparatorChar; } // Определение относительного пути для установки файла, например, для источника // 'lib/net45/some.dll' путь для установки будет 'some.dll', а для источника // 'lib/net45/en-US/resources.dll' путь для установки будет 'en-US/resources.dll' if (sourcePath.StartsWith(partFrameworkPath, StringComparison.OrdinalIgnoreCase)) { installPath = sourcePath.Substring(partFrameworkPath.Length); } else if (!Equals(sourceFramework, NuGetFramework.AnyFramework)) { // Обработка нестандартных путей, например, 'lib/net45-full/log4net.dll' var index = sourcePath.IndexOf(Path.DirectorySeparatorChar, sourcePart.Length + 1); if (index >= 0) { installPath = sourcePath.Substring(index + 1); } } return new PackageFile(Path.Combine(packagePath, sourcePath), installPath); }
private void LoadSupport() { _frameworks = new Dictionary<NuGetFramework, ValidationFramework>(); // determine which TxM:RIDs should be considered for support based on Frameworks item foreach (var framework in Frameworks) { NuGetFramework fx; try { fx = FrameworkUtilities.ParseNormalized(framework.ItemSpec); } catch (Exception ex) { Log.LogError($"Could not parse Framework {framework.ItemSpec}. {ex}"); continue; } if (fx.Equals(NuGetFramework.UnsupportedFramework)) { Log.LogError($"Did not recognize {framework.ItemSpec} as valid Framework."); continue; } string runtimeIdList = framework.GetMetadata("RuntimeIDs"); if (_frameworks.ContainsKey(fx)) { Log.LogError($"Framework {fx} has been listed in Frameworks more than once."); continue; } _frameworks[fx] = new ValidationFramework(fx); if (!String.IsNullOrWhiteSpace(runtimeIdList)) { _frameworks[fx].RuntimeIds = runtimeIdList.Split(';'); } } // keep a list of explicitly listed supported frameworks so that we can check for conflicts. HashSet<NuGetFramework> explicitlySupportedFrameworks = new HashSet<NuGetFramework>(); // determine what version should be supported based on SupportedFramework items foreach (var supportedFramework in SupportedFrameworks) { NuGetFramework fx; string fxString = supportedFramework.ItemSpec; bool isExclusiveVersion = fxString.Length > 1 && fxString[0] == '[' && fxString[fxString.Length - 1] == ']'; if (isExclusiveVersion) { fxString = fxString.Substring(1, fxString.Length - 2); } try { fx = FrameworkUtilities.ParseNormalized(fxString); } catch (Exception ex) { Log.LogError($"Could not parse TargetFramework {fxString} as a SupportedFramework. {ex}"); continue; } if (fx.Equals(NuGetFramework.UnsupportedFramework)) { Log.LogError($"Did not recognize TargetFramework {fxString} as a SupportedFramework."); continue; } Version supportedVersion; string version = supportedFramework.GetMetadata("Version"); try { supportedVersion = Version.Parse(version); } catch (Exception ex) { Log.LogError($"Could not parse Version {version} on SupportedFramework item {supportedFramework.ItemSpec}. {ex}"); continue; } ValidationFramework validationFramework = null; if (!_frameworks.TryGetValue(fx, out validationFramework)) { Log.LogError($"SupportedFramework {fx} was specified but is not part of the Framework list to use for validation."); continue; } if (explicitlySupportedFrameworks.Contains(fx)) { if (supportedVersion <= validationFramework.SupportedVersion) { // if we've already picked up a higher/equal version, prefer it continue; } } else { explicitlySupportedFrameworks.Add(fx); } validationFramework.SupportedVersion = supportedVersion; if (!isExclusiveVersion) { // find all frameworks of higher version, sorted by version ascending IEnumerable<ValidationFramework> higherFrameworks = _frameworks.Values.Where(vf => vf.Framework.Framework == fx.Framework && vf.Framework.Version > fx.Version).OrderBy(vf => vf.Framework.Version); // netcore50 is the last `netcore` framework, after that we use `uap` if (fx.Framework == FrameworkConstants.FrameworkIdentifiers.NetCore) { var uapFrameworks = _frameworks.Values.Where(vf => vf.Framework.Framework == FrameworkConstants.FrameworkIdentifiers.UAP).OrderBy(vf => vf.Framework.Version); higherFrameworks = higherFrameworks.Concat(uapFrameworks); } foreach (var higherFramework in higherFrameworks) { if (higherFramework.SupportedVersion != null && higherFramework.SupportedVersion > supportedVersion) { // found an higher framework version a higher API version, stop applying this supported version break; } higherFramework.SupportedVersion = supportedVersion; } } } // determine which Frameworks should support inbox _frameworkSet = FrameworkSet.Load(FrameworkListsPath); foreach (IEnumerable<Framework> inboxFxGroup in _frameworkSet.Frameworks.Values) { foreach (Framework inboxFx in inboxFxGroup) { // get currently supported version to see if we have OOB'ed it Version inboxVersion = null; inboxFx.Assemblies.TryGetValue(ContractName, out inboxVersion); if (inboxVersion != null) { NuGetFramework fx = FrameworkUtilities.ParseNormalized(inboxFx.ShortName); ValidationFramework validationFramework = null; if (_frameworks.TryGetValue(fx, out validationFramework)) { Version supportedVersion = validationFramework.SupportedVersion; if (supportedVersion != null && (supportedVersion.Major > inboxVersion.Major || (supportedVersion.Major == inboxVersion.Major && supportedVersion.Minor > inboxVersion.Minor))) { // Higher major.minor Log.LogMessage(LogImportance.Low, $"Framework {fx} supported {ContractName} as inbox but the current supported version {supportedVersion} is higher in major.minor than inbox version {inboxVersion}. Assuming out of box."); continue; } else if (supportedVersion != null && supportedVersion < inboxVersion && inboxVersion != s_maxVersion) { // Lower version Log.LogError($"Framework {fx} supports {ContractName} as inbox but the current supported version {supportedVersion} is lower than the inbox version {inboxVersion}"); } // equal major.minor, build.revision difference is permitted, prefer the version listed by ContractSupport item } if (validationFramework == null) { // we may not be explicitly validating for this framework so add it to validate inbox assets. _frameworks[fx] = validationFramework = new ValidationFramework(fx) { SupportedVersion = inboxVersion }; } validationFramework.IsInbox = true; } } } // for every framework we know about, also infer it's netstandard version to ensure it can // be targeted by PCL. Even if a package only supports a single framework we still // want to include a portable reference assembly. This allows 3rd parties to add // their own implementation via a lineup/runtime.json. // only consider frameworks that support the contract at a specific version var inferFrameworks = _frameworks.Values.Where(fx => fx.SupportedVersion != null && fx.SupportedVersion != s_maxVersion).ToArray(); var genVersionSuppression = GetSuppressionValues(Suppression.PermitPortableVersionMismatch) ?? new HashSet<string>(); var inferNETStandardSuppression = GetSuppressionValues(Suppression.SuppressNETStandardInference) ?? new HashSet<string>(); Dictionary<NuGetFramework, ValidationFramework> generationsToValidate = new Dictionary<NuGetFramework, ValidationFramework>(); foreach (var inferFramework in inferFrameworks) { var inferFrameworkMoniker = inferFramework.Framework.ToString(); if (inferNETStandardSuppression.Contains(inferFrameworkMoniker)) { continue; } NuGetFramework generation = new NuGetFramework(_generationIdentifier, Generations.DetermineGenerationForFramework(inferFramework.Framework, UseNetPlatform)); Log.LogMessage(LogImportance.Low, $"Validating {generation} for {ContractName}, {inferFramework.SupportedVersion} since it is supported by {inferFrameworkMoniker}"); ValidationFramework existingGeneration = null; if (generationsToValidate.TryGetValue(generation, out existingGeneration)) { // the netstandard version should be the minimum version supported by all platforms that support that netstandard version. if (inferFramework.SupportedVersion < existingGeneration.SupportedVersion) { Log.LogMessage($"Framework {inferFramework.Framework} supports {ContractName} at {inferFramework.SupportedVersion} which is lower than {existingGeneration.SupportedVersion} supported by generation {generation.GetShortFolderName()}. Lowering the version supported by {generation.GetShortFolderName()}."); existingGeneration.SupportedVersion = inferFramework.SupportedVersion; } } else { generationsToValidate.Add(generation, new ValidationFramework(generation) { SupportedVersion = inferFramework.SupportedVersion }); } } foreach (var generation in generationsToValidate) { _frameworks.Add(generation.Key, generation.Value); } }
public static bool IsPortableMoniker(NuGetFramework nuGetFramework) { return nuGetFramework == null ? false : nuGetFramework.GetShortFolderName().StartsWith("portable-"); }
/// <summary> /// Sort PCLs using these criteria /// 1. Lowest number of frameworks (highest surface area) wins first /// 2. Profile with the highest version numbers wins next /// 3. String compare is used as a last resort /// </summary> private bool IsBetterPCL(NuGetFramework current, NuGetFramework considering) { Debug.Assert(considering.IsPCL && current.IsPCL, "This method should be used only to compare PCLs"); // Find all frameworks in the profile var consideringFrameworks = ExplodePortableFramework(considering, false); var currentFrameworks = ExplodePortableFramework(current, false); // The PCL with the least frameworks (highest surface area) goes first if (consideringFrameworks.Count() < currentFrameworks.Count()) { return true; } else if (currentFrameworks.Count() < consideringFrameworks.Count()) { return false; } // If both frameworks have the same number of frameworks take the framework that has the highest // overall set of framework versions // Find Frameworks that both profiles have in common var sharedFrameworkIds = consideringFrameworks.Select(f => f.Framework) .Where(f => currentFrameworks.Any(consideringFramework => StringComparer.OrdinalIgnoreCase.Equals(f, consideringFramework.Framework))); var consideringHighest = 0; var currentHighest = 0; // Determine which framework has the highest version of each shared framework foreach (var sharedId in sharedFrameworkIds) { var consideringFramework = consideringFrameworks.Where(f => StringComparer.OrdinalIgnoreCase.Equals(f.Framework, sharedId)).First(); var currentFramework = currentFrameworks.Where(f => StringComparer.OrdinalIgnoreCase.Equals(f.Framework, sharedId)).First(); if (consideringFramework.Version < currentFramework.Version) { currentHighest++; } else if (currentFramework.Version < consideringFramework.Version) { consideringHighest++; } } // Prefer the highest count if (currentHighest < consideringHighest) { return true; } else if (consideringHighest < currentHighest) { return false; } // Take the highest version of .NET if no winner could be determined, this is usually a good indicator of which is newer var consideringNet = consideringFrameworks.Where(f => StringComparer.OrdinalIgnoreCase.Equals(f.Framework, FrameworkConstants.FrameworkIdentifiers.Net)).First(); var currentNet = currentFrameworks.Where(f => StringComparer.OrdinalIgnoreCase.Equals(f.Framework, FrameworkConstants.FrameworkIdentifiers.Net)).First(); // Compare using .NET only if both frameworks have it. PCLs should always have .NET, but since users can make these strings up we should // try to handle that as best as possible. if (consideringNet != null && currentNet != null) { if (currentNet.Version < consideringNet.Version) { return true; } else if (consideringNet.Version < currentNet.Version) { return false; } } // In the very rare case that both frameworks are still equal, we have to pick one. // There is nothing but we need to be deterministic, so compare the profiles as strings. if (StringComparer.OrdinalIgnoreCase.Compare(considering.GetShortFolderName(_mappings), current.GetShortFolderName(_mappings)) < 0) { return true; } return false; }
public ITaskItem GetItemWithTargetFramework(NuGetFramework framework) { var newItem = new TaskItem(OriginalItem); newItem.SetMetadata("TargetFramework", framework.GetShortFolderName()); return newItem; }
private void Add(NuGetFramework framework, string runtime) { var path = new StringBuilder(); if (!String.IsNullOrEmpty(runtime) && !IsReferenceAssembly) { path.Append($"runtimes/{runtime}/"); } string folder = IsReferenceAssembly ? "ref" : "lib"; string fx = framework.GetShortFolderName(); path.Append($"{folder}/{fx}"); _packageDestinations.Add(CreatePackageDestination(path.ToString(), fx)); // RID-specific desktop libraries should also be packaged without a RID to work in packages.config projects if (framework.Framework == FrameworkConstants.FrameworkIdentifiers.Net) { if (!String.IsNullOrEmpty(runtime) && PackageDesktopAsLib) { _packageDestinations.Add(CreatePackageDestination($"lib/{fx}", fx)); } if (PackageDesktopAsRef) { _packageDestinations.Add(CreatePackageDestination($"ref/{fx}", fx)); IsReferenceAsset = true; } } }
private IEnumerable<ITaskItem> CopyDependencies(IEnumerable<Dependency> dependencies, NuGetFramework targetFramework) { foreach (var dependency in dependencies) { if (!Frameworks.IsInbox(FrameworkListsPath, targetFramework, dependency.Id, dependency.Version)) { var copiedDepenedency = new TaskItem(dependency.OriginalItem); copiedDepenedency.SetMetadata(TargetFrameworkMetadataName, targetFramework.GetShortFolderName()); yield return copiedDepenedency; } } }
public override bool Execute() { if (String.IsNullOrEmpty(PackageTargetFramework)) { Log.LogMessage(LogImportance.Low, $"Skipping validation since PackageTargetFramework is not defined"); return true; } NuGetFramework fx = null; try { fx = NuGetFramework.Parse(PackageTargetFramework); } catch(Exception ex) { Log.LogError($"Could not parse PackageTargetFramework {PackageTargetFramework}. {ex}"); return false; } Version assemblyVersion = null; if (!Version.TryParse(AssemblyVersion, out assemblyVersion)) { Log.LogError($"Could not parse AssemblyVersion {AssemblyVersion}."); return false; } if (UseNetPlatform) { if (fx.Framework == FrameworkConstants.FrameworkIdentifiers.NetStandard) { Log.LogError($"Validating for legacy 'dotnet' moniker but package targets new 'netstandard' moniker."); return false; } else if (fx.Framework != FrameworkConstants.FrameworkIdentifiers.NetPlatform) { Log.LogMessage(LogImportance.Low, $"Skipping validation since PackageTargetFramework {fx} is not {FrameworkConstants.FrameworkIdentifiers.NetPlatform}"); return true; } } else { if (fx.Framework == FrameworkConstants.FrameworkIdentifiers.NetPlatform) { if (fx.Version > new Version(5, 0)) { NuGetFramework netstandardFx = new NuGetFramework(FrameworkConstants.FrameworkIdentifiers.NetStandard, new Version(fx.Version.Major - 4, fx.Version.Minor - 1)); Log.LogError($"{fx.GetShortFolderName()} is no longer supported please update to {netstandardFx.GetShortFolderName()}. Validating as {netstandardFx.GetShortFolderName()}."); // update to netstandard so that we can get the right number of errors fx = netstandardFx; } else { Log.LogError($"Invalid framework version {fx.GetShortFolderName()} please update to appropriate netstandard version."); // update to nestandard so that we'll do the actual calculation fx = FrameworkConstants.CommonFrameworks.NetStandard; } } if (fx.Framework != FrameworkConstants.FrameworkIdentifiers.NetStandard) { Log.LogMessage(LogImportance.Low, $"Skipping validation since PackageTargetFramework {fx} is not {FrameworkConstants.FrameworkIdentifiers.NetStandard}"); return true; } } _generations = Generations.Load(GenerationDefinitionsFile, UseNetPlatform); Dictionary<string, string> candidateRefs = CandidateReferences.ToDictionary(r => r.GetMetadata("FileName"), r => r.GetMetadata("FullPath")); Version idealGeneration = _generations.DetermineGenerationFromSeeds(AssemblyName, assemblyVersion, Log) ?? new Version(0, 0, 0, 0); if (idealGeneration > fx.Version) { Log.LogError($"Assembly {AssemblyName}, Version={assemblyVersion} is generation {idealGeneration} based on the seed data in {GenerationDefinitionsFile} which is greater than project generation {fx.Version}."); } HashSet<string> ignoredRefs = null; if (IgnoredReferences != null) { ignoredRefs = new HashSet<string>(IgnoredReferences.Select(ir => ir.ItemSpec), StringComparer.OrdinalIgnoreCase); } Version defaultGeneration = UseNetPlatform ? FrameworkConstants.CommonFrameworks.DotNet.Version : FrameworkConstants.CommonFrameworks.NetStandard.Version; foreach (var reference in DirectReferences) { string path = reference.GetMetadata("FullPath"); // workaround issue where portable targeting pack design time facades // include dangling refs and refs to higher versions of contracts than // exist in the targeting pack. if (path.IndexOf(".NETPortable", StringComparison.OrdinalIgnoreCase) != -1 && designTimeFacades.Contains(Path.GetFileNameWithoutExtension(path))) { continue; } if (ignoredRefs != null && ignoredRefs.Contains(Path.GetFileNameWithoutExtension(path))) { continue; } if (!File.Exists(path)) { Log.LogError($"Reference {path} does not exist."); continue; } var dependencyGeneration = _generations.DetermineGenerationFromFile(path, Log, candidateRefs: candidateRefs, ignoredRefs: ignoredRefs) ?? defaultGeneration; if (dependencyGeneration > fx.Version) { Log.LogError($"Dependency {path} is generation {dependencyGeneration} which is greater than project generation {fx.Version}."); } if (dependencyGeneration > idealGeneration) { idealGeneration = dependencyGeneration; } } if (fx.Version > idealGeneration) { Log.LogMessage(LogImportance.Low, $"Generation {fx.Version} is higher than the ideal miniumum {idealGeneration}."); } return !Log.HasLoggedErrors; }