|
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System.Collections.Generic;
using System.IO;
using ILLink.Shared;
namespace Mono.Linker.Steps
{
public class ProcessReferencesStep : BaseStep
{
protected override void Process()
{
// Walk over all -reference inputs and resolve any that may need to be rooted.
// For example:
// -reference dir/Unreferenced.dll --action copy --trim-mode copyused
// In this case we need to check whether Unreferenced has the
// IsTrimmable attribute, and root it if not.
// -reference dir/Unreferenced.dll --action copy --trim-mode copyused --action link Unreferenced
// The per-assembly action wins over the default --action or --trim-mode,
// so we don't need to load the assembly to check for IsTrimmable attribute.
// -reference dir/Unreferenced.dll --action link --trim-mode link
// In this case, we don't need to load the assembly up-front, because it will
// not get the copy/save action, regardless of the IsTrimmable attribute.
// Note that we don't do the same for assemblies which may be resolved from input directories - such
// assemblies will only be rooted if something loads them.
foreach (var assemblyPath in GetInputAssemblyPaths())
{
var assemblyName = Path.GetFileNameWithoutExtension(assemblyPath);
// If there's no way that this reference could have the copy/save action,
// we don't need to load it up-front.
if (!MaybeIsFullyPreservedAssembly(assemblyName))
continue;
// For the remaining references, we need to resolve them (which looks for IsTrimmable attribute)
// to determine the action.
var assembly = Context.TryResolve(assemblyName);
if (assembly == null)
{
Context.LogError(null, DiagnosticId.ReferenceAssemblyCouldNotBeLoaded, assemblyPath);
continue;
}
// If the assigned action (now taking into account the IsTrimmable attribute) requires us
// to root the assembly, do so.
if (IsFullyPreservedAction(Annotations.GetAction(assembly)))
Annotations.Mark(assembly.MainModule, new DependencyInfo(DependencyKind.AssemblyAction, assembly), new MessageOrigin(assembly));
}
}
IEnumerable<string> GetInputAssemblyPaths()
{
var assemblies = new HashSet<string>();
foreach (var referencePath in Context.Resolver.GetReferencePaths())
{
var assemblyName = Path.GetFileNameWithoutExtension(referencePath);
if (assemblies.Add(assemblyName))
yield return referencePath;
}
}
public static bool IsFullyPreservedAction(AssemblyAction action)
{
return action == AssemblyAction.Copy || action == AssemblyAction.Save;
}
bool MaybeIsFullyPreservedAssembly(string assemblyName)
{
if (Context.Actions.TryGetValue(assemblyName, out AssemblyAction action))
return IsFullyPreservedAction(action);
return IsFullyPreservedAction(Context.DefaultAction) || IsFullyPreservedAction(Context.TrimAction);
}
}
}
|