Skip to content

Commit a596f31

Browse files
Make it possible for featuredefault substitutions to only apply at publish time
Fixes dotnet#96539. Fixes dotnet#102303. Two possible approaches were discussed in dotnet#96539 but doing it in illinker feels more straightforward.
1 parent 39c4905 commit a596f31

File tree

10 files changed

+68
-11
lines changed

10 files changed

+68
-11
lines changed
+7-1
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
<linker>
22
<!-- System.Resources.UseSystemResourceKeys removes resource strings and instead uses the resource key as the exception message -->
33
<assembly fullname="{AssemblyName}" feature="System.Resources.UseSystemResourceKeys" featurevalue="true">
4-
<!-- System.Resources.UseSystemResourceKeys removes resource strings and instead uses the resource key as the exception message -->
54
<resource name="{StringResourcesName}.resources" action="remove" />
65
<type fullname="System.SR">
76
<method signature="System.Boolean UsingResourceKeys()" body="stub" value="true" />
7+
<method signature="System.Boolean GetUsingResourceKeysSwitchValue()" body="stub" value="true" />
8+
</type>
9+
</assembly>
10+
<assembly fullname="{AssemblyName}" feature="System.Resources.UseSystemResourceKeys" featurevalue="false" featuredefault="true">
11+
<type fullname="System.SR">
12+
<method signature="System.Boolean UsingResourceKeys()" body="stub" value="false" />
13+
<method signature="System.Boolean GetUsingResourceKeysSwitchValue()" body="stub" value="false" />
814
</type>
915
</assembly>
1016
</linker>

eng/illink.targets

+3-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
<ILLinkRewritePDBs Condition="'$(ILLinkRewritePDBs)' == ''">true</ILLinkRewritePDBs>
3838

3939
<ILLinkResourcesSubstitutionIntermediatePath>$(IntermediateOutputPath)ILLink.Resources.Substitutions.xml</ILLinkResourcesSubstitutionIntermediatePath>
40-
<GenerateResourcesSubstitutions Condition="'$(GenerateResourcesSubstitutions)' == '' and '$(StringResourcesPath)' != ''">true</GenerateResourcesSubstitutions>
40+
<GenerateResourcesSubstitutions Condition="'$(GenerateResourcesSubstitutions)' == '' and '$(StringResourcesPath)' != '' and '$(OmitResources)' != 'true'">true</GenerateResourcesSubstitutions>
4141
</PropertyGroup>
4242

4343
<ItemGroup>
@@ -222,6 +222,8 @@
222222
<LinkerNoWarn>$(LinkerNoWarn);IL2008;IL2009;IL2121;IL2025;IL2035</LinkerNoWarn>
223223
<ILLinkArgs>$(ILLinkArgs) --nowarn $(LinkerNoWarn)</ILLinkArgs>
224224
<ILLinkArgs Condition="'$(ILLinkDisableIPConstProp)' == 'true'">$(ILLinkArgs) --disable-opt ipconstprop</ILLinkArgs>
225+
<!-- Featuredefault for System.Resources.UseSystemResourceKeys would hardcode all libraries as not using resource keys, don't apply it -->
226+
<ILLinkArgs Condition="'$(GenerateResourcesSubstitutions)' == 'true'">$(ILLinkArgs) --ignore-featuredefault System.Resources.UseSystemResourceKeys</ILLinkArgs>
225227
</PropertyGroup>
226228

227229
<!-- Move the assembly into a subdirectory for ILLink -->

src/libraries/Common/src/System/SR.cs

+4-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@ namespace System
77
{
88
internal static partial class SR
99
{
10-
private static readonly bool s_usingResourceKeys = AppContext.TryGetSwitch("System.Resources.UseSystemResourceKeys", out bool usingResourceKeys) ? usingResourceKeys : false;
10+
private static readonly bool s_usingResourceKeys = GetUsingResourceKeysSwitchValue();
11+
12+
// This method is a target of ILLink substitution.
13+
private static bool GetUsingResourceKeysSwitchValue() => AppContext.TryGetSwitch("System.Resources.UseSystemResourceKeys", out bool usingResourceKeys) ? usingResourceKeys : false;
1114

1215
// This method is used to decide if we need to append the exception message parameters to the message when calling SR.Format.
1316
// by default it returns the value of System.Resources.UseSystemResourceKeys AppContext switch or false if not specified.

src/libraries/Common/src/System/SR.vb

+15-7
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,23 @@ Imports System.Resources
1111
Namespace System
1212

1313
Friend NotInheritable Class SR
14-
' This method is used to decide if we need to append the exception message parameters to the message when calling SR.Format.
15-
' by default it returns false.
14+
Private Shared ReadOnly s_usingResourceKeys As Boolean = GetUsingResourceKeysSwitchValue()
15+
16+
Private Shared Function GetUsingResourceKeysSwitchValue() As Boolean
17+
Dim usingResourceKeys As Boolean
18+
If (AppContext.TryGetSwitch("System.Resources.UseSystemResourceKeys", usingResourceKeys)) Then
19+
Return usingResourceKeys
20+
End If
21+
22+
Return False
23+
End Function
24+
25+
' This method Is used to decide if we need to append the exception message parameters to the message when calling SR.Format.
26+
' by default it returns the value of System.Resources.UseSystemResourceKeys AppContext switch Or false if Not specified.
1627
' Native code generators can replace the value this returns based on user input at the time of native code generation.
17-
' Marked as NoInlining because if this is used in an AoT compiled app that is not compiled into a single file, the user
18-
' could compile each module with a different setting for this. We want to make sure there's a consistent behavior
19-
' that doesn't depend on which native module this method got inlined into.
20-
<Global.System.Runtime.CompilerServices.MethodImpl(Global.System.Runtime.CompilerServices.MethodImplOptions.NoInlining)>
28+
' The trimming tools are also capable of replacing the value of this method when the application Is being trimmed.
2129
Public Shared Function UsingResourceKeys() As Boolean
22-
Return False
30+
Return s_usingResourceKeys
2331
End Function
2432

2533
Friend Shared Function GetResourceString(ByVal resourceKey As String, Optional ByVal defaultString As String = Nothing) As String

src/libraries/System.Diagnostics.FileVersionInfo/src/System.Diagnostics.FileVersionInfo.csproj

+2-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
<!-- DesignTimeBuild requires all the TargetFramework Derived Properties to not be present in the first property group. -->
1010
<PropertyGroup>
1111
<TargetPlatformIdentifier>$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)'))</TargetPlatformIdentifier>
12-
<GeneratePlatformNotSupportedAssemblyMessage Condition="'$(TargetPlatformIdentifier)' == ''">SR.DiagnosticsFileVersionInfo_PlatformNotSupported</GeneratePlatformNotSupportedAssemblyMessage>
12+
<GeneratePlatformNotSupportedAssemblyMessage Condition="'$(TargetPlatformIdentifier)' == ''">SR.DiagnosticsFileVersionInfo_PlatformNotSupported</GeneratePlatformNotSupportedAssemblyMessage>
13+
<OmitResources Condition="'$(GeneratePlatformNotSupportedAssemblyMessage)' == ''">true</OmitResources>
1314
</PropertyGroup>
1415

1516
<ItemGroup Condition="'$(TargetPlatformIdentifier)' != ''">

src/tools/illink/src/linker/Linker/Driver.cs

+8
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,14 @@ protected int SetupContext (ILogger? customLogger = null)
470470

471471
continue;
472472
}
473+
case "--ignore-featuredefault": {
474+
if (!GetStringParam (token, out string? featureName))
475+
return -1;
476+
477+
context.SetIgnoredFeatureDefault (featureName);
478+
479+
continue;
480+
}
473481
case "--new-mvid":
474482
//
475483
// This is not same as --deterministic which calculates MVID

src/tools/illink/src/linker/Linker/FeatureSettings.cs

+4
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ public static bool ShouldProcessElement (XPathNavigator nav, LinkContext context
3333
return false;
3434
}
3535

36+
if (bIsDefault && context.IgnoredFeatureDefaultSettings.Contains (feature)) {
37+
bIsDefault = false;
38+
}
39+
3640
if (!context.FeatureSettings.TryGetValue (feature, out bool featureSetting))
3741
return bIsDefault;
3842

src/tools/illink/src/linker/Linker/LinkContext.cs

+9
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,8 @@ public Pipeline Pipeline {
136136

137137
public Dictionary<string, bool> FeatureSettings { get; init; }
138138

139+
public HashSet<string> IgnoredFeatureDefaultSettings { get; init; }
140+
139141
public List<PInvokeInfo> PInvokes { get; private set; }
140142

141143
public string? PInvokesListFile;
@@ -218,6 +220,7 @@ protected LinkContext (Pipeline pipeline, ILogger logger, string outputDirectory
218220
_isTrimmable = new Dictionary<AssemblyDefinition, bool> ();
219221
OutputDirectory = outputDirectory;
220222
FeatureSettings = new Dictionary<string, bool> (StringComparer.Ordinal);
223+
IgnoredFeatureDefaultSettings = new HashSet<string> (StringComparer.Ordinal);
221224

222225
SymbolReaderProvider = new DefaultSymbolReaderProvider (false);
223226

@@ -264,6 +267,12 @@ public void SetFeatureValue (string feature, bool value)
264267
FeatureSettings[feature] = value;
265268
}
266269

270+
public void SetIgnoredFeatureDefault (string feature)
271+
{
272+
Debug.Assert (!string.IsNullOrEmpty (feature));
273+
IgnoredFeatureDefaultSettings.Add (feature);
274+
}
275+
267276
public bool HasFeatureValue (string feature, bool value)
268277
{
269278
return FeatureSettings.TryGetValue (feature, out bool fvalue) && value == fvalue;

src/tools/illink/test/Mono.Linker.Tests.Cases/FeatureSettings/FeatureDescriptors.cs

+4
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ namespace Mono.Linker.Tests.Cases.FeatureSettings
1515
[SetupLinkerArgument ("--feature", "FieldCondition", "true")]
1616
[SetupLinkerArgument ("--feature", "PropertyCondition", "false")]
1717
[SetupLinkerArgument ("--feature", "EventCondition", "true")]
18+
[SetupLinkerArgument ("--ignore-featuredefault", "IgnoredDefaultCondition")]
1819
public class FeatureDescriptors
1920
{
2021
public static void Main ()
@@ -25,6 +26,9 @@ public static void Main ()
2526
static bool DefaultConditionTrue;
2627
static bool DefaultConditionFalse;
2728

29+
static bool IgnoredDefaultConditionTrue;
30+
static bool IgnoredDefaultConditionFalse;
31+
2832
[Kept]
2933
static bool GlobalConditionTrue;
3034
static bool GlobalConditionFalse;

src/tools/illink/test/Mono.Linker.Tests.Cases/FeatureSettings/FeatureDescriptors.xml

+12
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,16 @@
4747
<field name="DefaultConditionFalse" />
4848
</type>
4949
</assembly>
50+
<!-- Check that a default feature condition can be ignored -->
51+
<assembly fullname="test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null" feature="IgnoredDefaultCondition" featurevalue="true" featuredefault="true">
52+
<type fullname="Mono.Linker.Tests.Cases.FeatureSettings.FeatureDescriptors">
53+
<field name="IgnoredDefaultConditionTrue" />
54+
</type>
55+
</assembly>
56+
<!-- Else case for the ignored default condition -->
57+
<assembly fullname="test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null" feature="IgnoredDefaultCondition" featurevalue="false">
58+
<type fullname="Mono.Linker.Tests.Cases.FeatureSettings.FeatureDescriptors">
59+
<field name="IgnoredDefaultConditionFalse" />
60+
</type>
61+
</assembly>
5062
</linker>

0 commit comments

Comments
 (0)