Skip to content

Commit cd8654a

Browse files
authored
Merge pull request #18672 from tarekgh/PredefinedCulturesOnlySupport
Initial Support for PredefinedCultureOnly property
2 parents b169e69 + 0c1ac14 commit cd8654a

File tree

4 files changed

+83
-21
lines changed

4 files changed

+83
-21
lines changed

src/Assets/TestProjects/KitchenSink/TestApp/TestApp.csproj

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
<DebuggerSupport>true</DebuggerSupport>
1414
<EventSourceSupport>false</EventSourceSupport>
1515
<InvariantGlobalization>true</InvariantGlobalization>
16+
<PredefinedCulturesOnly>true</PredefinedCulturesOnly>
1617
<ConcurrentGarbageCollection>false</ConcurrentGarbageCollection>
1718
<ServerGarbageCollection>true</ServerGarbageCollection>
1819
<RetainVMGarbageCollection>false</RetainVMGarbageCollection>
@@ -59,7 +60,7 @@
5960
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
6061
<CopyToPublishDirectory>Never</CopyToPublishDirectory>
6162
</Content>
62-
63+
6364
<None Include="NoneCopyOutputAlways.txt">
6465
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
6566
</None>
@@ -74,7 +75,7 @@
7475
<ProjectReference Include="../TestLibrary/TestLibrary.csproj" />
7576
</ItemGroup>
7677
<ItemGroup>
77-
<!--
78+
<!--
7879
The TestLibrary has a hard dependency on Newtonsoft.Json.
7980
The TestApp has a PrivateAssets=All dependency on Microsoft.Extensions.DependencyModel.
8081
Microsoft.Extensions.DependencyModel depends on Newtonsoft.Json.

src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.targets

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@ Copyright (c) .NET Foundation. All rights reserved.
7272
<UserProfileRuntimeStorePath Condition="'$(UserProfileRuntimeStorePath)' == ''">$(_DefaultUserProfileRuntimeStorePath)</UserProfileRuntimeStorePath>
7373
</PropertyGroup>
7474

75+
<PropertyGroup Condition="'$(TargetFrameworkIdentifier)' == '.NETCoreApp' and $([MSBuild]::VersionGreaterThanOrEquals($(TargetFrameworkVersion), '6.0'))">
76+
<PredefinedCulturesOnly Condition="'$(PredefinedCulturesOnly)' == '' and '$(InvariantGlobalization)' == 'true'">true</PredefinedCulturesOnly>
77+
</PropertyGroup>
78+
7579
<!-- Opt into .NET Core resource-serialization strategy by default when targeting frameworks
7680
that support it by default.
7781
-->
@@ -394,6 +398,11 @@ Copyright (c) .NET Foundation. All rights reserved.
394398
Value="$(InvariantGlobalization)"
395399
Trim="true" />
396400

401+
<RuntimeHostConfigurationOption Include="System.Globalization.PredefinedCulturesOnly"
402+
Condition="'$(PredefinedCulturesOnly)' != ''"
403+
Value="$(PredefinedCulturesOnly)"
404+
Trim="true" />
405+
397406
<RuntimeHostConfigurationOption Include="System.Net.Http.EnableActivityPropagation"
398407
Condition="'$(HttpActivityPropagationSupport)' != ''"
399408
Value="$(HttpActivityPropagationSupport)"
@@ -961,7 +970,7 @@ Copyright (c) .NET Foundation. All rights reserved.
961970
============================================================
962971
-->
963972

964-
<UsingTask TaskName="CheckForUnsupportedWinMDReferences" AssemblyFile="$(MicrosoftNETBuildTasksAssembly)" />
973+
<UsingTask TaskName="CheckForUnsupportedWinMDReferences" AssemblyFile="$(MicrosoftNETBuildTasksAssembly)" />
965974

966975
<Target Name="_BlockWinMDsOnUnsupportedTFMs"
967976
AfterTargets="PreBuildEvent"
@@ -972,7 +981,7 @@ Copyright (c) .NET Foundation. All rights reserved.
972981
TargetFrameworkMoniker="$(TargetFrameworkMoniker)"
973982
ReferencePaths="@(ReferencePath)"
974983
/>
975-
984+
976985
<NETSdkError Condition="'$(OutputType)' == 'winmdobj'"
977986
ResourceName="WinMDObjNotSupportedOnTargetFramework"
978987
FormatArguments="$(TargetFrameworkMoniker)" />
@@ -1052,7 +1061,7 @@ Copyright (c) .NET Foundation. All rights reserved.
10521061
IsExecutable="$(_IsExecutable)"
10531062
ReferencedProjects="@(_MSBuildProjectReferenceExistent)"
10541063
/>
1055-
1064+
10561065
</Target>
10571066

10581067
<!--
@@ -1105,7 +1114,7 @@ Copyright (c) .NET Foundation. All rights reserved.
11051114
<PropertyGroup Condition=" '$(ImportWindowsDesktopTargets)' == 'true'">
11061115
<AfterMicrosoftNETSdkTargets>$(AfterMicrosoftNETSdkTargets);$(MSBuildThisFileDirectory)../../Microsoft.NET.Sdk.WindowsDesktop/targets/Microsoft.NET.Sdk.WindowsDesktop.targets</AfterMicrosoftNETSdkTargets>
11071116
</PropertyGroup>
1108-
1117+
11091118
<!-- Note: Once WindowsDesktop is a workload this will be moved to WorkloadManifest.targets -->
11101119
<ItemGroup Condition="'$(MicrosoftNETWindowsWorkloadInstalled)' == 'true' and
11111120
'$(TargetFrameworkIdentifier)' == '.NETCoreApp' and

src/Tests/Microsoft.NET.Build.Tests/GivenThatWeWantToBuildALibrary.cs

Lines changed: 62 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,10 @@ internal static List<string> GetValuesFromTestLibrary(
7575
ITestOutputHelper log,
7676
TestAssetsManager testAssetsManager,
7777
string itemTypeOrPropertyName,
78-
Action<GetValuesCommand> setup = null,
78+
Action<GetValuesCommand> setup = null,
7979
string[] msbuildArgs = null,
80-
GetValuesCommand.ValueType valueType = GetValuesCommand.ValueType.Item,
81-
[CallerMemberName] string callingMethod = "",
80+
GetValuesCommand.ValueType valueType = GetValuesCommand.ValueType.Item,
81+
[CallerMemberName] string callingMethod = "",
8282
Action<XDocument> projectChanges = null,
8383
string identifier = null)
8484
{
@@ -316,14 +316,14 @@ public void It_implicitly_defines_compilation_constants_for_the_configuration(st
316316
[InlineData("netstandard1.6", new[] { "NETSTANDARD", "NETSTANDARD1_6", "NETSTANDARD1_0_OR_GREATER", "NETSTANDARD1_1_OR_GREATER", "NETSTANDARD1_2_OR_GREATER",
317317
"NETSTANDARD1_3_OR_GREATER", "NETSTANDARD1_4_OR_GREATER", "NETSTANDARD1_5_OR_GREATER", "NETSTANDARD1_6_OR_GREATER" })]
318318
[InlineData("net45", new[] { "NETFRAMEWORK", "NET45", "NET20_OR_GREATER", "NET30_OR_GREATER", "NET35_OR_GREATER", "NET40_OR_GREATER", "NET45_OR_GREATER" })]
319-
[InlineData("net461", new[] { "NETFRAMEWORK", "NET461", "NET20_OR_GREATER", "NET30_OR_GREATER", "NET35_OR_GREATER", "NET40_OR_GREATER", "NET45_OR_GREATER",
319+
[InlineData("net461", new[] { "NETFRAMEWORK", "NET461", "NET20_OR_GREATER", "NET30_OR_GREATER", "NET35_OR_GREATER", "NET40_OR_GREATER", "NET45_OR_GREATER",
320320
"NET451_OR_GREATER", "NET452_OR_GREATER", "NET46_OR_GREATER", "NET461_OR_GREATER" })]
321-
[InlineData("net48", new[] { "NETFRAMEWORK", "NET48", "NET20_OR_GREATER", "NET30_OR_GREATER", "NET35_OR_GREATER", "NET40_OR_GREATER", "NET45_OR_GREATER",
321+
[InlineData("net48", new[] { "NETFRAMEWORK", "NET48", "NET20_OR_GREATER", "NET30_OR_GREATER", "NET35_OR_GREATER", "NET40_OR_GREATER", "NET45_OR_GREATER",
322322
"NET451_OR_GREATER", "NET452_OR_GREATER", "NET46_OR_GREATER", "NET461_OR_GREATER", "NET462_OR_GREATER", "NET47_OR_GREATER", "NET471_OR_GREATER", "NET472_OR_GREATER", "NET48_OR_GREATER" })]
323323
[InlineData("netcoreapp1.0", new[] { "NETCOREAPP", "NETCOREAPP1_0", "NETCOREAPP1_0_OR_GREATER" })]
324-
[InlineData("netcoreapp3.0", new[] { "NETCOREAPP", "NETCOREAPP3_0", "NETCOREAPP1_0_OR_GREATER", "NETCOREAPP1_1_OR_GREATER", "NETCOREAPP2_0_OR_GREATER",
324+
[InlineData("netcoreapp3.0", new[] { "NETCOREAPP", "NETCOREAPP3_0", "NETCOREAPP1_0_OR_GREATER", "NETCOREAPP1_1_OR_GREATER", "NETCOREAPP2_0_OR_GREATER",
325325
"NETCOREAPP2_1_OR_GREATER", "NETCOREAPP2_2_OR_GREATER", "NETCOREAPP3_0_OR_GREATER" })]
326-
[InlineData("net5.0", new[] { "NETCOREAPP", "NETCOREAPP1_0_OR_GREATER", "NETCOREAPP1_1_OR_GREATER", "NETCOREAPP2_0_OR_GREATER", "NETCOREAPP2_1_OR_GREATER",
326+
[InlineData("net5.0", new[] { "NETCOREAPP", "NETCOREAPP1_0_OR_GREATER", "NETCOREAPP1_1_OR_GREATER", "NETCOREAPP2_0_OR_GREATER", "NETCOREAPP2_1_OR_GREATER",
327327
"NETCOREAPP2_2_OR_GREATER", "NETCOREAPP3_0_OR_GREATER", "NETCOREAPP3_1_OR_GREATER", "NET", "NET5_0", "NET5_0_OR_GREATER" })]
328328
[InlineData(".NETPortable,Version=v4.5,Profile=Profile78", new string[] { })]
329329
[InlineData(".NETFramework,Version=v4.0,Profile=Client", new string[] { "NETFRAMEWORK", "NET40", "NET20_OR_GREATER", "NET30_OR_GREATER", "NET35_OR_GREATER", "NET40_OR_GREATER" })]
@@ -366,7 +366,7 @@ public void It_implicitly_defines_compilation_constants_for_the_target_framework
366366
targetFrameworkProperties.Single().SetValue(targetFramework);
367367
}
368368
});
369-
369+
370370
var libraryProjectDirectory = Path.Combine(testAsset.TestRoot, "TestLibrary");
371371

372372
var getValuesCommand = new GetValuesCommand(Log, libraryProjectDirectory,
@@ -423,7 +423,7 @@ public void It_implicitly_defines_compilation_constants_for_the_target_platform(
423423
}
424424
});
425425

426-
AssertDefinedConstantsOutput(testAsset, targetFramework,
426+
AssertDefinedConstantsOutput(testAsset, targetFramework,
427427
new[] { "NETCOREAPP", "NETCOREAPP1_0_OR_GREATER", "NETCOREAPP1_1_OR_GREATER", "NETCOREAPP2_0_OR_GREATER", "NETCOREAPP2_1_OR_GREATER", "NETCOREAPP2_2_OR_GREATER", "NETCOREAPP3_0_OR_GREATER", "NETCOREAPP3_1_OR_GREATER", "NET", "NET5_0", "NET5_0_OR_GREATER" }
428428
.Concat(expectedDefines).ToArray());
429429
}
@@ -841,6 +841,59 @@ public void It_marks_package_references_as_externally_resolved(bool? markAsExter
841841
}
842842
}
843843

844+
[Theory]
845+
[InlineData("net5.0", false, false, false, null)] // Pre .NET 6.0 predefinedCulturesOnly is not supported.
846+
[InlineData("net5.0", true, false, false, null)] // Pre .NET 6.0 predefinedCulturesOnly is not supported.
847+
[InlineData("net5.0", false, true, true, "True")] // Pre .NET 6.0 predefinedCulturesOnly can end up in the runtime config file but with no effect at runtime.
848+
[InlineData("net5.0", true, true, true, "True")] // Pre .NET 6.0 predefinedCulturesOnly can end up in the runtime config file but with no effect at runtime.
849+
[InlineData("net6.0", false, false, false, null)] // predefinedCulturesOnly will not be included in the runtime config file if invariant is not defined.
850+
[InlineData("net6.0", false, false, true, "False")] // predefinedCulturesOnly explicitly defined as false.
851+
[InlineData("net6.0", false, true, true, "True")] // predefinedCulturesOnly explicitly defined as true.
852+
[InlineData("net6.0", true, false, false, "True")] // predefinedCulturesOnly default value is true when Invariant is true.
853+
[InlineData("net6.0", true, false, true, "False")] // predefinedCulturesOnly explicitly defined as false.
854+
[InlineData("net6.0", true, true, true, "True")] // predefinedCulturesOnly explicitly defined as true.
855+
public void It_can_implicitly_define_predefined_Cultures_only(string targetFramework, bool invariantValue, bool predefinedCulturesOnlyValue, bool definePredefinedCulturesOnly, string expectedPredefinedValue)
856+
{
857+
var testProj = new TestProject()
858+
{
859+
Name = "CheckPredefineCulturesOnly",
860+
TargetFrameworks = targetFramework,
861+
IsExe = true,
862+
};
863+
864+
testProj.AdditionalProperties["InvariantGlobalization"] = invariantValue ? "true" : "false";
865+
866+
if (definePredefinedCulturesOnly)
867+
{
868+
testProj.AdditionalProperties["PredefinedCulturesOnly"] = predefinedCulturesOnlyValue ? "true" : "false";
869+
}
870+
871+
var testAsset = _testAssetsManager.CreateTestProject(testProj, identifier: $"{targetFramework}{invariantValue}{predefinedCulturesOnlyValue}{definePredefinedCulturesOnly}");
872+
var buildCommand = new BuildCommand(testAsset);
873+
buildCommand
874+
.Execute()
875+
.Should()
876+
.Pass();
877+
878+
string runtimeConfigName = $"{testProj.Name}.runtimeconfig.json";
879+
var outputDirectory = buildCommand.GetOutputDirectory(testProj.TargetFrameworks);
880+
outputDirectory.Should().HaveFile(runtimeConfigName);
881+
882+
string runtimeConfigFile = Path.Combine(outputDirectory.FullName, runtimeConfigName);
883+
string runtimeConfigContents = File.ReadAllText(runtimeConfigFile);
884+
JObject runtimeConfig = JObject.Parse(runtimeConfigContents);
885+
JToken predefinedCulturesOnly = runtimeConfig["runtimeOptions"]["configProperties"]["System.Globalization.PredefinedCulturesOnly"];
886+
887+
if (expectedPredefinedValue is null)
888+
{
889+
predefinedCulturesOnly.Should().BeNull();
890+
}
891+
else
892+
{
893+
predefinedCulturesOnly.Value<string>().Should().Be(expectedPredefinedValue);
894+
}
895+
}
896+
844897
[Theory]
845898
[InlineData("netcoreapp2.2", null, false, null, false)]
846899
[InlineData("netcoreapp3.0", null, true, null, true)]
@@ -905,8 +958,6 @@ public void It_can_build_with_dynamic_loading_enabled(string targetFramework, st
905958
{
906959
rollForward.Should().BeNull();
907960
}
908-
909-
910961
}
911962

912963
[Theory]

src/Tests/Microsoft.NET.Publish.Tests/GivenThatWeWantToPublishAProjectWithAllFeatures.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ public void It_publishes_the_project_correctly(string targetFramework, string []
7171
""System.Diagnostics.Debugger.IsSupported"": true,
7272
""System.Diagnostics.Tracing.EventSource.IsSupported"": false,
7373
""System.Globalization.Invariant"": true,
74+
""System.Globalization.PredefinedCulturesOnly"": true,
7475
""System.GC.Concurrent"": false,
7576
""System.GC.Server"": true,
7677
""System.GC.RetainVM"": false,
@@ -101,7 +102,7 @@ public void It_publishes_the_project_correctly(string targetFramework, string []
101102
}
102103
}");
103104
baselineConfigJsonObject["runtimeOptions"]["tfm"] = targetFramework;
104-
baselineConfigJsonObject["runtimeOptions"]["framework"]["version"] =
105+
baselineConfigJsonObject["runtimeOptions"]["framework"]["version"] =
105106
targetFramework == "netcoreapp1.0" ? "1.0.5" : "1.1.2";
106107

107108
runtimeConfigJsonObject
@@ -146,7 +147,7 @@ public void It_does_not_build_when_nobuild_is_set(string targetFramework, string
146147
{
147148
File.GetLastWriteTimeUtc(file)
148149
.Should().Be(
149-
modificationTime,
150+
modificationTime,
150151
because: $"Publish with NoBuild=true should not overwrite {file}");
151152
}
152153
}
@@ -209,7 +210,7 @@ private static void VerifyDependency(
209210
library.RuntimeAssemblyGroups[0].Runtime.Should().Be(string.Empty);
210211
library.RuntimeAssemblyGroups[0].AssetPaths.Count.Should().Be(1);
211212
library.RuntimeAssemblyGroups[0].AssetPaths[0].Should().Be($"{path}{dllName}.dll");
212-
213+
213214
foreach (string locale in locales)
214215
{
215216
// Try to get the locale as part of a dependency package: Humanizer.Core.af
@@ -221,7 +222,7 @@ private static void VerifyDependency(
221222
{
222223
localeLibrary = library;
223224
}
224-
225+
225226
localeLibrary
226227
.ResourceAssemblies
227228
.FirstOrDefault(r => r.Locale == locale && r.Path == $"{path}{locale}/{dllName}.resources.dll")

0 commit comments

Comments
 (0)