Fixes #86651.
This was implemented in .NET Native so we just need to resurface it from the compiler.
Note that this is not full support for satellite assemblies (in the assembly binder, etc.) that never existed and nobody ever asked for and I don't even know what it entails.
DependsOnTargets="$(IlcDynamicBuildPropertyDependencies)">
<ItemGroup>
<IlcReference Include="@(_ManagedResolvedAssembliesToPublish)" />
+ <IlcSatelliteAssembly Include="@(_SatelliteAssembliesToPublish)" />
+ <IlcSatelliteAssembly Include="@(IntermediateSatelliteAssembliesWithTargetPath)" />
</ItemGroup>
</Target>
FrameworkAssemblies="@(FrameworkAssemblies)">
<Output TaskParameter="ManagedAssemblies" ItemName="_ManagedResolvedAssembliesToPublish" />
+ <Output TaskParameter="SatelliteAssemblies" ItemName="_SatelliteAssembliesToPublish" />
<Output TaskParameter="AssembliesToSkipPublish" ItemName="_AssembliesToSkipPublish" />
</ComputeManagedAssembliesToCompileToNative>
<IlcArg Include="@(IlcCompileInput)" />
<IlcArg Include="-o:$(NativeIntermediateOutputPath)%(ManagedBinary.Filename)$(IlcOutputFileExt)" />
<IlcArg Include="@(IlcReference->'-r:%(Identity)')" />
+ <IlcArg Include="@(IlcSatelliteAssembly->'--satellite:%(Identity)')" />
<IlcArg Include="@(MibcFile->'--mibc:%(Identity)')" />
<IlcArg Condition="$(IlcGenerateMetadataLog) == 'true'" Include="--metadatalog:$(NativeIntermediateOutputPath)%(ManagedBinary.Filename).metadata.csv" />
<IlcArg Condition="$(_targetOS) != ''" Include="--targetos:$(_targetOS)" />
</Target>
<Target Name="IlcCompile"
- Inputs="@(IlcCompileInput);@(IlcReference);@(RdXmlFile);%(ManagedBinary.IlcRspFile)"
+ Inputs="@(IlcCompileInput);@(IlcReference);@(IlcSatelliteAssembly);@(RdXmlFile);%(ManagedBinary.IlcRspFile)"
Outputs="%(ManagedBinary.IlcOutputFile)"
DependsOnTargets="WriteIlcRspFileForCompilation;$(IlcCompileDependsOn)">
<Message Text="Generating native code" Importance="high" />
}
[Output]
+ public ITaskItem[] SatelliteAssemblies
+ {
+ get;
+ set;
+ }
+
+ [Output]
public ITaskItem[] AssembliesToSkipPublish
{
get;
{
var list = new List<ITaskItem>();
var assembliesToSkipPublish = new List<ITaskItem>();
+ var satelliteAssemblies = new List<ITaskItem>();
var nativeAotFrameworkAssembliesToUse = new HashSet<string>();
foreach (ITaskItem taskItem in SdkAssemblies)
string culture = moduleMetadataReader.GetString(moduleMetadataReader.GetAssemblyDefinition().Culture);
assembliesToSkipPublish.Add(taskItem);
+
+ // Split satellite assemblies from normal assemblies
if (culture == "" || culture.Equals("neutral", StringComparison.OrdinalIgnoreCase))
{
- // NativeAOT doesn't consume resource assemblies yet so skip them
list.Add(taskItem);
}
+ else
+ {
+ satelliteAssemblies.Add(taskItem);
+ }
}
}
}
ManagedAssemblies = list.ToArray();
AssembliesToSkipPublish = assembliesToSkipPublish.ToArray();
+ SatelliteAssemblies = satelliteAssemblies.ToArray();
return true;
}
new FullyBlockedMetadataBlockingPolicy(), new FullyBlockedManifestResourceBlockingPolicy(),
null, new NoStackTraceEmissionPolicy(), new NoDynamicInvokeThunkGenerationPolicy(),
new ILLink.Shared.TrimAnalysis.FlowAnnotations(Logger.Null, ilProvider, compilerGeneratedState), UsageBasedMetadataGenerationOptions.None,
- default, Logger.Null, Array.Empty<KeyValuePair<string, bool>>(), Array.Empty<string>(), Array.Empty<string>(), Array.Empty<string>());
+ default, Logger.Null, Array.Empty<KeyValuePair<string, bool>>(), Array.Empty<string>(), Array.Empty<string>(), Array.Empty<string>(), Array.Empty<string>());
CompilationBuilder builder = new RyuJitCompilationBuilder(context, compilationGroup)
.UseILProvider(ilProvider);
dependencies.Add(factory.ReflectedMethod(entrypoint), "Reflectable entrypoint");
}
- CustomAttributeBasedDependencyAlgorithm.AddDependenciesDueToCustomAttributes(ref dependencies, factory, (EcmaAssembly)_module);
+ EcmaAssembly ecmaAssembly = (EcmaAssembly)_module;
+
+ CustomAttributeBasedDependencyAlgorithm.AddDependenciesDueToCustomAttributes(ref dependencies, factory, ecmaAssembly);
+
+ foreach (EcmaModule satelliteModule in ((UsageBasedMetadataManager)factory.MetadataManager).GetSatelliteAssemblies(ecmaAssembly))
+ {
+ dependencies.Add(factory.ModuleMetadata(satelliteModule), "Satellite assembly");
+ }
return dependencies;
}
private readonly HashSet<string> _rootEntireAssembliesModules;
private readonly HashSet<string> _trimmedAssemblies;
+ private readonly List<string> _satelliteAssemblyFiles;
internal FlowAnnotations FlowAnnotations { get; }
IEnumerable<KeyValuePair<string, bool>> featureSwitchValues,
IEnumerable<string> rootEntireAssembliesModules,
IEnumerable<string> additionalRootedAssemblies,
- IEnumerable<string> trimmedAssemblies)
+ IEnumerable<string> trimmedAssemblies,
+ IEnumerable<string> satelliteAssemblyFilePaths)
: base(typeSystemContext, blockingPolicy, resourceBlockingPolicy, logFile, stackTracePolicy, invokeThunkGenerationPolicy, options)
{
_compilationModuleGroup = group;
_rootEntireAssembliesModules = new HashSet<string>(rootEntireAssembliesModules);
_rootEntireAssembliesModules.UnionWith(additionalRootedAssemblies);
_trimmedAssemblies = new HashSet<string>(trimmedAssemblies);
+ _satelliteAssemblyFiles = new List<string>(satelliteAssemblyFilePaths);
+ }
+
+ public IEnumerable<EcmaModule> GetSatelliteAssemblies(EcmaAssembly module)
+ {
+ string expectedSimpleName = module.GetName().Name + ".resources";
+ foreach (string filePath in _satelliteAssemblyFiles)
+ {
+ string simpleName = Path.GetFileNameWithoutExtension(filePath);
+ if (simpleName == expectedSimpleName)
+ {
+ yield return _typeSystemContext.GetMetadataOnlyModuleFromPath(filePath);
+ }
+ }
}
protected override void Graph_NewMarkedNode(DependencyNodeCore<NodeFactory> obj)
<ServerGarbageCollection>true</ServerGarbageCollection>
<TieredCompilation>false</TieredCompilation>
<EventSourceSupport>true</EventSourceSupport>
- <InvariantGlobalization>true</InvariantGlobalization>
<OptimizationPreference>Speed</OptimizationPreference>
</PropertyGroup>
new(new[] { "--optimize-time", "--Ot" }, "Enable optimizations, favor code speed");
public Option<string[]> MibcFilePaths { get; } =
new(new[] { "--mibc", "-m" }, Array.Empty<string>, "Mibc file(s) for profile guided optimization");
+ public Option<string[]> SatelliteFilePaths { get; } =
+ new(new[] { "--satellite" }, Array.Empty<string>, "Satellite assemblies associated with inputs/references");
public Option<bool> EnableDebugInfo { get; } =
new(new[] { "--debug", "-g" }, "Emit debugging information");
public Option<bool> UseDwarf5 { get; } =
AddOption(OptimizeSpace);
AddOption(OptimizeTime);
AddOption(MibcFilePaths);
+ AddOption(SatelliteFilePaths);
AddOption(EnableDebugInfo);
AddOption(UseDwarf5);
AddOption(NativeLib);
featureSwitches,
Get(_command.ConditionallyRootedAssemblies),
rootedAssemblies,
- Get(_command.TrimmedAssemblies));
+ Get(_command.TrimmedAssemblies),
+ Get(_command.SatelliteFilePaths));
InteropStateManager interopStateManager = new InteropStateManager(typeSystemContext.GeneratedAssembly);
InteropStubManager interopStubManager = new UsageBasedInteropStubManager(interopStateManager, pinvokePolicy, logger);
Array.Empty<KeyValuePair<string, bool>> (),
Array.Empty<string> (),
options.AdditionalRootAssemblies.ToArray (),
- options.TrimAssemblies.ToArray ());
+ options.TrimAssemblies.ToArray (),
+ Array.Empty<string> ());
PInvokeILEmitterConfiguration pinvokePolicy = new ILCompilerTestPInvokePolicy ();
InteropStateManager interopStateManager = new InteropStateManager (typeSystemContext.GeneratedAssembly);
<Configurations>Debug;Release;Checked</Configurations>
<ServerGarbageCollection>true</ServerGarbageCollection>
<EventSourceSupport>true</EventSourceSupport>
- <InvariantGlobalization>true</InvariantGlobalization>
<OptimizationPreference>Speed</OptimizationPreference>
<RunAnalyzers>false</RunAnalyzers>
</PropertyGroup>
[Theory]
[MemberData(nameof(CultureResourceData))]
- [ActiveIssue("https://github.com/dotnet/runtimelab/issues/155", typeof(PlatformDetection), nameof(PlatformDetection.IsNativeAot))] // satellite assemblies
public static void GetString_CultureFallback(string key, string cultureName, string expectedValue)
{
Type resourceType = typeof(Resources.TestResx);
}
[Fact]
- [ActiveIssue("https://github.com/dotnet/runtimelab/issues/155", typeof(PlatformDetection), nameof(PlatformDetection.IsNativeAot))] //satellite assemblies
public static void GetString_FromTestClassWithoutNeutralResources()
{
// This test is designed to complement the GetString_FromCulutureAndResourceType "fr" & "fr-CA" cases