File: Linker.Steps\ProcessReferencesStep.cs
Web Access
Project: src\src\tools\illink\src\linker\Mono.Linker.csproj (illink)
// 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);
		}
	}
}