Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multi target type reuse #5300

Merged
merged 5 commits into from
Mar 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 10 additions & 15 deletions src/dotnet-svcutil/lib/src/Bootstrapper/SvcutilBootstrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -123,22 +123,17 @@ internal async Task GenerateProjectAsync(bool keepBootstrapperDir, ILogger logge
this.MSBuildProj = await MSBuildProj.DotNetNewAsync(projectFullPath, logger, cancellationToken).ConfigureAwait(false);
this.MSBuildProj.AddDependency(svcutilPkgRef, true);

// Comment out code below for reasons: 1. it never used for .net core later than V2.1 since when the approach is always use TF from the generated project.
// 2. with below code applied when target framework is netstandard2.0 client machine require netcoreapp2.0 (obsolete) for bootstrapper to work
// 3. keep it here for future reference in case when we need definite bootstrapper TF version

// NOTE: If post v2.0 NetStandard ships a different version from NetCore the table below needs to be updated!
//var targetFramework = frameworkInfo.FullName;
//if (isSupportedTFM && frameworkInfo.IsKnownDnx)
//{
// if (frameworkInfo.Name == FrameworkInfo.Netstandard)
// {
// targetFramework = FrameworkInfo.Netcoreapp + TargetFrameworkHelper.NetStandardToNetCoreVersionMap[frameworkInfo.Version];
// }
// this.MSBuildProj.TargetFramework = targetFramework;
//}
var targetFramework = frameworkInfo.FullName;
if (isSupportedTFM && frameworkInfo.Name != FrameworkInfo.Netstandard && frameworkInfo.Version.CompareTo(new Version(6, 0)) >= 0)
HongGit marked this conversation as resolved.
Show resolved Hide resolved
{
this.MSBuildProj.TargetFramework = targetFramework;
if(targetFramework.ToLowerInvariant().Contains("net7.0-windows10"))
{
this.MSBuildProj.SetEnableMsixTooling();
}
}
// else
// The TFM is unknown: either, it was not provided or it is a version not yet known to the tool,
// The TFM is Netstandard or version lower than 6.0 or unknown: either, it was not provided or it is a version not yet known to the tool,
// we will use the default TF from the generated project.
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public void WsdlImported(WsdlImporter importer, Collection<ServiceEndpoint> endp

foreach (var binding in bindings)
{
if (binding is NetNamedPipeBinding && _options.Project != null && !_options.Project.TargetFrameworks.FirstOrDefault().ToLower().Contains("windows"))
if (binding is NetNamedPipeBinding && _options.Project != null && !_options.Project.TargetFrameworks.Any(t => t.ToLower().Contains("windows")))
{
MetadataConversionError error = new MetadataConversionError(SR.WrnTargetFrameworkNotSupported_NetNamedPipe, isWarning: true);
if (!importer.Errors.Contains(error))
Expand Down
21 changes: 15 additions & 6 deletions src/dotnet-svcutil/lib/src/Shared/FrameworkInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ public static FrameworkInfo Parse(string fullFrameworkName)
// framework spec form: 'net5.0'
// framework spec form: '.NETCoreApp,Version=v6.0'
// framework spec form: '.NETFramework,Version=v4.8'
// framework spec form: 'net7.0-windows10.0.19041.0', 'net7.0-windows'
for (int i = 0; i < fullFrameworkName.Length; i++)
{
char c = fullFrameworkName[i];
Expand All @@ -49,17 +50,25 @@ public static FrameworkInfo Parse(string fullFrameworkName)

// Version ctr requires at least Major and Minor parts
string versionString = fullFrameworkName.Substring(i);
if ((name == Netfx) && !versionString.Contains("."))
if ((name == Netfx))
{
// net452
StringBuilder sb = new StringBuilder(versionString);
for (int j = 1; j < sb.Length; j += 2)
if(!versionString.Contains("."))
{
sb.Insert(j, '.');
StringBuilder sb = new StringBuilder(versionString);
for (int j = 1; j < sb.Length; j += 2)
{
sb.Insert(j, '.');
}
versionString = sb.ToString();
}
versionString = sb.ToString();
// net7.0-windows10.0.19041.0
if (versionString.Contains("-"))
{
versionString = versionString.Substring(0, versionString.IndexOf("-"));
}
}

version = new Version(versionString);
break;
}
Expand Down
31 changes: 18 additions & 13 deletions src/dotnet-svcutil/lib/src/Shared/MSBuildProj.cs
Original file line number Diff line number Diff line change
Expand Up @@ -221,14 +221,9 @@ public static async Task<MSBuildProj> ParseAsync(string projectText, string proj
if (targetFrameworksElements.Count() > 0)
{
var targetFrameworks = targetFrameworksElements.Last().Value;
if (targetFrameworks.ToString().StartsWith("$"))
{
targetFrameworks = GetValueFromDirBuildProps(targetFrameworks, msbuildProj.DirectoryPath);
}

foreach (var targetFx in targetFrameworks.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries).Select(p => p.Trim()))
{
if (!string.IsNullOrWhiteSpace(targetFx))
if (!string.IsNullOrEmpty(targetFx) && !targetFx.ToString().StartsWith("$"))
{
msbuildProj._targetFrameworks.Add(targetFx);
}
Expand Down Expand Up @@ -591,6 +586,14 @@ public bool AddDependency(ProjectDependency dependency, bool copyInternalAssets
return addDependency;
}

public void SetEnableMsixTooling()
{
// workaround for https://github.com/microsoft/WindowsAppSDK/issues/3548: dotnet build fails when WindowsAppSDK is referenced in console application.
// affects MAUI project targeting net7.0-windows10.0xxx, not reproduce in net8.0-window10.0xxx
// ref: https://github.com/dotnet/maui/issues/5886
SetPropertyValue("EnableMsixTooling", "true");
}

// Sets the property value in a PropertyGroup. Returns true if the value was changed, and false if it was already set to that value.
private bool SetPropertyValue(string propertyName, string value)
{
Expand Down Expand Up @@ -759,7 +762,7 @@ public async Task<IEnumerable<ProjectDependency>> ResolveProjectReferencesAsync(

using (var safeLogger = await SafeLogger.WriteStartOperationAsync(logger, "Resolving project references ...").ConfigureAwait(false))
{
if (_targetFrameworks.Count == 1 && TargetFrameworkHelper.IsSupportedFramework(this.TargetFramework, out var frameworkInfo) && frameworkInfo.IsDnx)
if (_targetFrameworks.Count >= 1 && TargetFrameworkHelper.IsSupportedFramework(this.TargetFramework, out var frameworkInfo) && frameworkInfo.IsDnx)
{
await this.RestoreAsync(logger, cancellationToken).ConfigureAwait(false);

Expand Down Expand Up @@ -794,15 +797,17 @@ await AsyncHelper.RunAsync(async () =>
try
{
var assetsFile = new FileInfo(Path.Combine(this.DirectoryPath, "obj", "project.assets.json")).FullName;
if (File.Exists(assetsFile))
if (File.Exists(assetsFile) && !(this.TargetFramework.Contains("-") && !this.TargetFramework.ToLower().Contains("windows")))
{
LockFile lockFile = LockFileUtilities.GetLockFile(assetsFile, logger as NuGet.Common.ILogger);

if (lockFile != null)
{
if (lockFile.Targets.Count == 1)
LockFileTarget target = lockFile.Targets.Count == 1 ? lockFile.Targets[0] : lockFile.Targets.FirstOrDefault(t =>
t.Name.StartsWith(this.TargetFramework, StringComparison.InvariantCultureIgnoreCase) //this.TargetFramework:net7.0-windows, targets:net7.0-windows7.0
|| this.TargetFramework.StartsWith(t.Name, StringComparison.InvariantCultureIgnoreCase));//this.TargetFramework:net7.0-windows10.0.19041.0, targets:net7.0-windows10.0.19041
if (target != null)
{
foreach (var lib in lockFile.Targets[0].Libraries)
foreach (var lib in target.Libraries)
{
bool isPackage = StringComparer.OrdinalIgnoreCase.Compare(lib.Type, "package") == 0;

Expand Down Expand Up @@ -970,7 +975,7 @@ public async Task<IEnumerable<KeyValuePair<string, string>>> ResolveProperyValue

if (propertyTable.Count() != propertyNames.Count())
{
propertyTable = await _propertyResolver.EvaluateProjectPropertiesAsync(this.FullPath, this.TargetFrameworks.FirstOrDefault(), propertyNames, this.GlobalProperties, logger, cancellationToken).ConfigureAwait(false);
propertyTable = await _propertyResolver.EvaluateProjectPropertiesAsync(this.FullPath, this.TargetFramework, propertyNames, this.GlobalProperties, logger, cancellationToken).ConfigureAwait(false);

foreach (var entry in propertyTable)
{
Expand Down Expand Up @@ -1000,7 +1005,7 @@ private async Task<string> ResolveDepsFilePathFromBuildConfigAsync(string output
{
var depsFiles = Directory.GetFiles(binFolder, "*", SearchOption.AllDirectories)
.Where(d => Path.GetFileName(d).Equals(fileName, RuntimeEnvironmentHelper.FileStringComparison))
.Where(f => PathHelper.GetFolderName(Path.GetDirectoryName(f)) == this.TargetFrameworks.FirstOrDefault())
.Where(f => PathHelper.GetFolderName(Path.GetDirectoryName(f)) == this.TargetFramework || Directory.GetParent(Directory.GetParent(f).FullName).Name == this.TargetFramework)
.Select(f => new FileInfo(f))
.OrderByDescending(f => f.CreationTimeUtc);

Expand Down
11 changes: 0 additions & 11 deletions src/dotnet-svcutil/lib/src/Shared/TargetFrameworkHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -160,11 +160,6 @@ public static string GetBestFitTargetFramework(IEnumerable<string> targetFramewo
}
}

if (fxInfo != null)
{
return fxInfo.FullName;
}

return targetFramework;
}

Expand Down Expand Up @@ -222,12 +217,6 @@ public static bool IsSupportedFramework(string fullFrameworkName, out FrameworkI
{
bool isSupported = false;

var tfx = fullFrameworkName.Split('-');
if (tfx.Length > 1)
{
fullFrameworkName = tfx[0];
}

if (FrameworkInfo.TryParse(fullFrameworkName, out frameworkInfo))
{
isSupported = (frameworkInfo.Name == FrameworkInfo.Netstandard && frameworkInfo.Version >= MinSupportedNetStandardVersion) ||
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

namespace ServiceReference
{
using System.Runtime.Serialization;


[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "99.99.99")]
[System.Runtime.Serialization.DataContractAttribute(Name="TypeReuseCompositeType", Namespace="http://schemas.datacontract.org/2004/07/TypesLib")]
public partial class TypeReuseCompositeType : object
{

private bool BoolValueField;

private string StringValueField;

[System.Runtime.Serialization.DataMemberAttribute()]
public bool BoolValue
{
get
{
return this.BoolValueField;
}
set
{
this.BoolValueField = value;
}
}

[System.Runtime.Serialization.DataMemberAttribute()]
public string StringValue
{
get
{
return this.StringValueField;
}
set
{
this.StringValueField = value;
}
}
}

[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "99.99.99")]
[System.ServiceModel.ServiceContractAttribute(ConfigurationName="ServiceReference.ITypeReuseSvc")]
public interface ITypeReuseSvc
{

[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/ITypeReuseSvc/GetData", ReplyAction="http://tempuri.org/ITypeReuseSvc/GetDataResponse")]
System.Threading.Tasks.Task<BinLib.BinLibrary> GetDataAsync(int value);

[System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/ITypeReuseSvc/GetDataUsingDataContract", ReplyAction="http://tempuri.org/ITypeReuseSvc/GetDataUsingDataContractResponse")]
System.Threading.Tasks.Task<ServiceReference.TypeReuseCompositeType> GetDataUsingDataContractAsync(ServiceReference.TypeReuseCompositeType composite);
}

[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "99.99.99")]
public interface ITypeReuseSvcChannel : ServiceReference.ITypeReuseSvc, System.ServiceModel.IClientChannel
{
}

[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.Tools.ServiceModel.Svcutil", "99.99.99")]
public partial class TypeReuseSvcClient : System.ServiceModel.ClientBase<ServiceReference.ITypeReuseSvc>, ServiceReference.ITypeReuseSvc
{

/// <summary>
/// Implement this partial method to configure the service endpoint.
/// </summary>
/// <param name="serviceEndpoint">The endpoint to configure</param>
/// <param name="clientCredentials">The client credentials</param>
static partial void ConfigureEndpoint(System.ServiceModel.Description.ServiceEndpoint serviceEndpoint, System.ServiceModel.Description.ClientCredentials clientCredentials);

public TypeReuseSvcClient() :
base(TypeReuseSvcClient.GetDefaultBinding(), TypeReuseSvcClient.GetDefaultEndpointAddress())
{
this.Endpoint.Name = EndpointConfiguration.BasicHttpBinding_ITypeReuseSvc.ToString();
ConfigureEndpoint(this.Endpoint, this.ClientCredentials);
}

public TypeReuseSvcClient(EndpointConfiguration endpointConfiguration) :
base(TypeReuseSvcClient.GetBindingForEndpoint(endpointConfiguration), TypeReuseSvcClient.GetEndpointAddress(endpointConfiguration))
{
this.Endpoint.Name = endpointConfiguration.ToString();
ConfigureEndpoint(this.Endpoint, this.ClientCredentials);
}

public TypeReuseSvcClient(EndpointConfiguration endpointConfiguration, string remoteAddress) :
base(TypeReuseSvcClient.GetBindingForEndpoint(endpointConfiguration), new System.ServiceModel.EndpointAddress(remoteAddress))
{
this.Endpoint.Name = endpointConfiguration.ToString();
ConfigureEndpoint(this.Endpoint, this.ClientCredentials);
}

public TypeReuseSvcClient(EndpointConfiguration endpointConfiguration, System.ServiceModel.EndpointAddress remoteAddress) :
base(TypeReuseSvcClient.GetBindingForEndpoint(endpointConfiguration), remoteAddress)
{
this.Endpoint.Name = endpointConfiguration.ToString();
ConfigureEndpoint(this.Endpoint, this.ClientCredentials);
}

public TypeReuseSvcClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) :
base(binding, remoteAddress)
{
}

public System.Threading.Tasks.Task<BinLib.BinLibrary> GetDataAsync(int value)
{
return base.Channel.GetDataAsync(value);
}

public System.Threading.Tasks.Task<ServiceReference.TypeReuseCompositeType> GetDataUsingDataContractAsync(ServiceReference.TypeReuseCompositeType composite)
{
return base.Channel.GetDataUsingDataContractAsync(composite);
}

public virtual System.Threading.Tasks.Task OpenAsync()
{
return System.Threading.Tasks.Task.Factory.FromAsync(((System.ServiceModel.ICommunicationObject)(this)).BeginOpen(null, null), new System.Action<System.IAsyncResult>(((System.ServiceModel.ICommunicationObject)(this)).EndOpen));
}

private static System.ServiceModel.Channels.Binding GetBindingForEndpoint(EndpointConfiguration endpointConfiguration)
{
if ((endpointConfiguration == EndpointConfiguration.BasicHttpBinding_ITypeReuseSvc))
{
System.ServiceModel.BasicHttpBinding result = new System.ServiceModel.BasicHttpBinding();
result.MaxBufferSize = int.MaxValue;
result.ReaderQuotas = System.Xml.XmlDictionaryReaderQuotas.Max;
result.MaxReceivedMessageSize = int.MaxValue;
result.AllowCookies = true;
return result;
}
throw new System.InvalidOperationException(string.Format("Could not find endpoint with name \'{0}\'.", endpointConfiguration));
}

private static System.ServiceModel.EndpointAddress GetEndpointAddress(EndpointConfiguration endpointConfiguration)
{
if ((endpointConfiguration == EndpointConfiguration.BasicHttpBinding_ITypeReuseSvc))
{
return new System.ServiceModel.EndpointAddress("http://localhost:51074/TypeReuseSvc.svc");
}
throw new System.InvalidOperationException(string.Format("Could not find endpoint with name \'{0}\'.", endpointConfiguration));
}

private static System.ServiceModel.Channels.Binding GetDefaultBinding()
{
return TypeReuseSvcClient.GetBindingForEndpoint(EndpointConfiguration.BasicHttpBinding_ITypeReuseSvc);
}

private static System.ServiceModel.EndpointAddress GetDefaultEndpointAddress()
{
return TypeReuseSvcClient.GetEndpointAddress(EndpointConfiguration.BasicHttpBinding_ITypeReuseSvc);
}

public enum EndpointConfiguration
{

BasicHttpBinding_ITypeReuseSvc,
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"providerId": "Microsoft.Tools.ServiceModel.Svcutil",
"version": "99.99.99",
"options": {
"inputs": [
"$testCasesPath$/wsdl/TypeReuseSvc.wsdl"
],
"namespaceMappings": [
"*, ServiceReference"
],
"outputFile": "Reference.cs",
"references": [
"$TEMP$MultiTargetTypeReuse//TypeReuseClient//bin//Debug//net6.0//BinLib.dll"
],
"targetFramework": "N.N",
"typeReuseMode": "All"
}
}
Loading
Loading