protected override string GenerateCommandLineCommands() { ProcessArguments arguments = null; if (!InvokeLinkerUsingMono) { arguments = ProcessArguments.Create("--verbose"); } else { var toolsPath = GetPathToMonoLinker(); Log.LogMessage(MessageImportance.High, $"Running monolinker from {toolsPath}."); arguments = ProcessArguments.Create(toolsPath); arguments = arguments.Add("--verbose"); } // add exclude features arguments = arguments.AddRange("--exclude-feature", "remoting", "--exclude-feature", "com", "--exclude-feature", "etw"); string coremode, usermode; switch ((WasmLinkMode)Enum.Parse(typeof(WasmLinkMode), LinkMode)) { case WasmLinkMode.SdkOnly: coremode = "link"; usermode = "copy"; break; case WasmLinkMode.Full: coremode = "link"; usermode = "link"; break; default: coremode = "copyused"; usermode = "copy"; break; } arguments = arguments.AddRange("-c", coremode, "-u", usermode); //the linker doesn't consider these core by default arguments = arguments.AddRange("-p", coremode, "WebAssembly.Bindings"); arguments = arguments.AddRange("-p", coremode, "WebAssembly.Net.Http"); arguments = arguments.AddRange("-p", coremode, "WebAssembly.Net.WebSockets"); if (!string.IsNullOrEmpty(LinkSkip)) { var skips = LinkSkip.Split(new[] { ';', ',', ' ', '\t', '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); foreach (var s in skips) { arguments = arguments.AddRange("-p", "copy", s); } } arguments = arguments.AddRange("-out", OutputDir); arguments = arguments.AddRange("-d", FrameworkDir); arguments = arguments.AddRange("-d", Path.Combine(FrameworkDir, "Facades")); arguments = arguments.AddRange("-b", Debug.ToString()); arguments = arguments.AddRange("-v", Debug.ToString()); arguments = arguments.AddRange("-a", RootAssembly[0].GetMetadata("FullPath")); //we'll normally have to check most of the because the SDK references most framework asm by default //so let's enumerate upfront var frameworkAssemblies = new HashSet <string> (StringComparer.OrdinalIgnoreCase); foreach (var f in Directory.EnumerateFiles(FrameworkDir)) { frameworkAssemblies.Add(Path.GetFileNameWithoutExtension(f)); } foreach (var f in Directory.EnumerateFiles(Path.Combine(FrameworkDir, "Facades"))) { frameworkAssemblies.Add(Path.GetFileNameWithoutExtension(f)); } //add references for non-framework assemblies if (Assemblies != null) { foreach (var asm in Assemblies) { var p = asm.GetMetadata("FullPath"); if (frameworkAssemblies.Contains(Path.GetFileNameWithoutExtension(p))) { continue; } arguments = arguments.AddRange("-r", p); } } if (string.IsNullOrEmpty(I18n)) { arguments = arguments.AddRange("-l", "none"); } else { var vals = I18n.Split(new[] { ',', ';', ' ', '\r', '\n', '\t' }); arguments = arguments.AddRange("-l", string.Join(",", vals)); } return(arguments.ToString()); }
bool Execute(DirectoryAssemblyResolver res) { // Put every assembly we'll need in the resolver foreach (var assembly in ResolvedAssemblies) { res.Load(Path.GetFullPath(assembly.ItemSpec)); } var resolver = new AssemblyResolver(res.ToResolverCache()); // Set up for linking var options = new LinkerOptions(); options.MainAssembly = res.GetAssembly(MainAssembly); options.OutputDirectory = Path.GetFullPath(OutputDirectory); options.LinkSdkOnly = string.Compare(LinkMode, "SdkOnly", true) == 0; options.LinkNone = false; options.Resolver = resolver; options.LinkDescriptions = LinkDescriptions.Select(item => Path.GetFullPath(item.ItemSpec)).ToArray(); options.I18nAssemblies = Linker.ParseI18nAssemblies(I18nAssemblies); if (!options.LinkSdkOnly) { options.RetainAssemblies = GetRetainAssemblies(res); } options.DumpDependencies = DumpDependencies; options.HttpClientHandlerType = HttpClientHandlerType; options.TlsProvider = TlsProvider; options.AddKeepAlives = AddKeepAlives; options.PreserveJniMarshalMethods = PreserveJniMarshalMethods; options.DeterministicOutput = Deterministic; options.LinkResources = LinkResources; var skiplist = new List <string> (); // Add LinkSkip options if (!string.IsNullOrWhiteSpace(LinkSkip)) { skiplist.AddRange(LinkSkip.Split(',', ';')); } options.SkippedAssemblies = skiplist; if (EnableProguard) { options.ProguardConfiguration = ProguardConfiguration; } // Link! try { LinkContext link_context; Linker.Process(options, this, out link_context); foreach (var assembly in ResolvedAssemblies) { var copysrc = assembly.ItemSpec; var filename = Path.GetFileName(assembly.ItemSpec); var assemblyDestination = Path.Combine(OutputDirectory, filename); if (!MonoAndroidHelper.IsForceRetainedAssembly(filename)) { continue; } MonoAndroidHelper.CopyAssemblyAndSymbols(copysrc, assemblyDestination); } } catch (ResolutionException ex) { Diagnostic.Error(2006, ex, Properties.Resources.XA2006, ex.Member, ex.Member.Module.Assembly, ex.Scope); } return(true); }
bool Execute(DirectoryAssemblyResolver res) { // Put every assembly we'll need in the resolver foreach (var assembly in ResolvedAssemblies) { res.Load(Path.GetFullPath(assembly.ItemSpec)); } var resolver = new AssemblyResolver(res.ToResolverCache()); // Set up for linking var options = new LinkerOptions(); options.MainAssembly = res.GetAssembly(MainAssembly); options.OutputDirectory = Path.GetFullPath(OutputDirectory); options.LinkSdkOnly = string.Compare(LinkMode, "SdkOnly", true) == 0; options.LinkNone = string.Compare(LinkMode, "None", true) == 0; options.Resolver = resolver; options.LinkDescriptions = LinkDescriptions.Select(item => Path.GetFullPath(item.ItemSpec)).ToArray(); options.I18nAssemblies = Linker.ParseI18nAssemblies(I18nAssemblies); if (!options.LinkSdkOnly) { options.RetainAssemblies = GetRetainAssemblies(res); } options.DumpDependencies = DumpDependencies; options.HttpClientHandlerType = HttpClientHandlerType; options.TlsProvider = TlsProvider; options.PreserveJniMarshalMethods = PreserveJniMarshalMethods; var skiplist = new List <string> (); if (string.Compare(UseSharedRuntime, "true", true) == 0) { skiplist.AddRange(Profile.SharedRuntimeAssemblies.Where(a => a.EndsWith(".dll")).Select(a => Path.GetFileNameWithoutExtension(a))); } if (!string.IsNullOrWhiteSpace(LinkOnlyNewerThan) && File.Exists(LinkOnlyNewerThan)) { var newerThan = File.GetLastWriteTime(LinkOnlyNewerThan); var skipOldOnes = ResolvedAssemblies.Where(a => File.GetLastWriteTime(a.ItemSpec) < newerThan); foreach (var old in skipOldOnes) { Log.LogMessage(MBF.MessageImportance.Low, " Skip linking unchanged file: " + old.ItemSpec); } skiplist = skipOldOnes.Select(a => Path.GetFileNameWithoutExtension(a.ItemSpec)).Concat(skiplist).ToList(); } // Add LinkSkip options if (!string.IsNullOrWhiteSpace(LinkSkip)) { foreach (var assembly in LinkSkip.Split(',', ';')) { skiplist.Add(assembly); } } options.SkippedAssemblies = skiplist; if (EnableProguard) { options.ProguardConfiguration = ProguardConfiguration; } // Link! try { LinkContext link_context; Linker.Process(options, this, out link_context); var copydst = OptionalDestinationDirectory ?? OutputDirectory; foreach (var assembly in ResolvedAssemblies) { var copysrc = assembly.ItemSpec; var filename = Path.GetFileName(assembly.ItemSpec); var assemblyDestination = Path.Combine(copydst, filename); if (options.LinkNone) { if (skiplist.Any(s => Path.GetFileNameWithoutExtension(filename) == s)) { // For skipped assemblies, skip if there is existing file in the destination. // We cannot just copy the linker output from *current* run output, because // it always renew the assemblies, in *different* binary values, whereas // the dll in the OptionalDestinationDirectory must retain old and unchanged. if (File.Exists(assemblyDestination)) { MonoAndroidHelper.SetLastAccessAndWriteTimeUtc(assemblyDestination, DateTime.UtcNow, Log); continue; } } else { // Prefer fixup assemblies if exists, otherwise just copy the original. copysrc = Path.Combine(OutputDirectory, filename); copysrc = File.Exists(copysrc) ? copysrc : assembly.ItemSpec; } } else if (!MonoAndroidHelper.IsForceRetainedAssembly(filename)) { continue; } if (MonoAndroidHelper.CopyIfChanged(copysrc, assemblyDestination)) { MonoAndroidHelper.SetLastAccessAndWriteTimeUtc(assemblyDestination, DateTime.UtcNow, Log); } try { var mdbDestination = assemblyDestination + ".mdb"; if (MonoAndroidHelper.CopyIfChanged(assembly.ItemSpec + ".mdb", mdbDestination)) { MonoAndroidHelper.SetLastAccessAndWriteTimeUtc(mdbDestination, DateTime.UtcNow, Log); } } catch (Exception) { // skip it, mdb sometimes fails to read and it's optional } var pdb = Path.ChangeExtension(copysrc, "pdb"); if (File.Exists(pdb) && Files.IsPortablePdb(pdb)) { var pdbDestination = Path.ChangeExtension(Path.Combine(copydst, filename), "pdb"); if (MonoAndroidHelper.CopyIfChanged(pdb, pdbDestination)) { MonoAndroidHelper.SetLastAccessAndWriteTimeUtc(pdbDestination, DateTime.UtcNow, Log); } } } } catch (ResolutionException ex) { Diagnostic.Error(2006, ex, "Could not resolve reference to '{0}' (defined in assembly '{1}') with scope '{2}'. When the scope is different from the defining assembly, it usually means that the type is forwarded.", ex.Member, ex.Member.Module.Assembly, ex.Scope); } return(true); }
protected override string GenerateCommandLineCommands() { var sb = new StringBuilder(); sb.Append(" --verbose"); string coremode, usermode; switch ((WasmLinkMode)Enum.Parse(typeof(WasmLinkMode), LinkMode)) { case WasmLinkMode.SdkOnly: coremode = "link"; usermode = "copy"; break; case WasmLinkMode.Full: coremode = "link"; usermode = "link"; break; default: coremode = "copyused"; usermode = "copy"; break; } sb.AppendFormat(" -c {0} -u {1}", coremode, usermode); //the linker doesn't consider these core by default sb.AppendFormat(" -p {0} netstandard -p {1} WebAssembly.Bindings -p {1} WebAssembly.Net.Http", coremode, usermode); if (!string.IsNullOrEmpty(LinkSkip)) { var skips = LinkSkip.Split(new[] { ';', ',', ' ', '\t', '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); foreach (var s in skips) { sb.AppendFormat(" -p \"{0}\" copy", s); } } sb.AppendFormat(" -out \"{0}\"", OutputDir); sb.AppendFormat(" -d \"{0}\"", FrameworkDir); sb.AppendFormat(" -b {0} -v {0}", Debug); sb.AppendFormat(" -a \"{0}\"", RootAssembly[0].GetMetadata("FullPath")); //we'll normally have to check most of the because the SDK references most framework asm by default //so let's enumerate upfront var frameworkAssemblies = new HashSet <string> (StringComparer.OrdinalIgnoreCase); foreach (var f in Directory.EnumerateFiles(FrameworkDir)) { frameworkAssemblies.Add(Path.GetFileNameWithoutExtension(f)); } foreach (var f in Directory.EnumerateFiles(Path.Combine(FrameworkDir, "Facades"))) { frameworkAssemblies.Add(Path.GetFileNameWithoutExtension(f)); } //add references for non-framework assemblies if (Assemblies != null) { foreach (var asm in Assemblies) { var p = asm.GetMetadata("FullPath"); if (frameworkAssemblies.Contains(Path.GetFileNameWithoutExtension(p))) { continue; } sb.AppendFormat(" -r \"{0}\"", p); } } if (string.IsNullOrEmpty(I18n)) { sb.Append(" -l none"); } else { var vals = I18n.Split(new[] { ',', ';', ' ', '\r', '\n', '\t' }); sb.AppendFormat(" -l {0}", string.Join(",", vals)); } return(sb.ToString()); }
public override bool Execute() { Log.LogDebugMessage("LinkAssemblies Task"); Log.LogDebugMessage(" UseSharedRuntime: {0}", UseSharedRuntime); Log.LogDebugMessage(" MainAssembly: {0}", MainAssembly); Log.LogDebugMessage(" OutputDirectory: {0}", OutputDirectory); Log.LogDebugMessage(" OptionalDestinationDirectory: {0}", OptionalDestinationDirectory); Log.LogDebugMessage(" I18nAssemblies: {0}", I18nAssemblies); Log.LogDebugMessage(" LinkMode: {0}", LinkMode); Log.LogDebugMessage(" LinkSkip: {0}", LinkSkip); Log.LogDebugTaskItems(" LinkDescriptions:", LinkDescriptions); Log.LogDebugTaskItems(" ResolvedAssemblies:", ResolvedAssemblies); Log.LogDebugMessage(" EnableProguard: {0}", EnableProguard); Log.LogDebugMessage(" ProguardConfiguration: {0}", ProguardConfiguration); Log.LogDebugMessage(" DumpDependencies: {0}", DumpDependencies); Log.LogDebugMessage(" LinkOnlyNewerThan: {0}", LinkOnlyNewerThan); var res = new DirectoryAssemblyResolver(Log.LogWarning, loadDebugSymbols: false); // Put every assembly we'll need in the resolver foreach (var assembly in ResolvedAssemblies) { res.Load(Path.GetFullPath(assembly.ItemSpec)); } var resolver = new AssemblyResolver(res.ToResolverCache()); // Set up for linking var options = new LinkerOptions(); options.MainAssembly = res.GetAssembly(MainAssembly); options.OutputDirectory = Path.GetFullPath(OutputDirectory); options.LinkSdkOnly = string.Compare(LinkMode, "SdkOnly", true) == 0; options.LinkNone = string.Compare(LinkMode, "None", true) == 0; options.Resolver = resolver; options.LinkDescriptions = LinkDescriptions.Select(item => Path.GetFullPath(item.ItemSpec)).ToArray(); options.I18nAssemblies = Linker.ParseI18nAssemblies(I18nAssemblies); if (!options.LinkSdkOnly) { options.RetainAssemblies = GetRetainAssemblies(res); } options.DumpDependencies = DumpDependencies; var skiplist = new List <string> (); if (string.Compare(UseSharedRuntime, "true", true) == 0) { skiplist.AddRange(Profile.SharedRuntimeAssemblies.Where(a => a.EndsWith(".dll")).Select(a => Path.GetFileNameWithoutExtension(a))); } if (!string.IsNullOrWhiteSpace(LinkOnlyNewerThan) && File.Exists(LinkOnlyNewerThan)) { var newerThan = File.GetLastWriteTime(LinkOnlyNewerThan); var skipOldOnes = ResolvedAssemblies.Where(a => File.GetLastWriteTime(a.ItemSpec) < newerThan); foreach (var old in skipOldOnes) { Log.LogMessage(MessageImportance.Low, " Skip linking unchanged file: " + old.ItemSpec); } skiplist = skipOldOnes.Select(a => Path.GetFileNameWithoutExtension(a.ItemSpec)).Concat(skiplist).ToList(); } // Add LinkSkip options if (!string.IsNullOrWhiteSpace(LinkSkip)) { foreach (var assembly in LinkSkip.Split(',', ';')) { skiplist.Add(assembly); } } options.SkippedAssemblies = skiplist; if (EnableProguard) { options.ProguardConfiguration = ProguardConfiguration; } // Link! try { LinkContext link_context; Linker.Process(options, out link_context); var copydst = OptionalDestinationDirectory ?? OutputDirectory; foreach (var assembly in ResolvedAssemblies) { var copysrc = assembly.ItemSpec; var filename = Path.GetFileName(assembly.ItemSpec); if (options.LinkNone) { if (skiplist.Any(s => Path.GetFileNameWithoutExtension(filename) == s)) { // For skipped assemblies, skip if there is existing file in the destination. // We cannot just copy the linker output from *current* run output, because // it always renew the assemblies, in *different* binary values, whereas // the dll in the OptionalDestinationDirectory must retain old and unchanged. if (File.Exists(Path.Combine(copydst, filename))) { continue; } copysrc = assembly.ItemSpec; } else { // Prefer fixup assemblies if exists, otherwise just copy the original. copysrc = Path.Combine(OutputDirectory, filename); copysrc = File.Exists(copysrc) ? copysrc : assembly.ItemSpec; } } else if (!MonoAndroidHelper.IsForceRetainedAssembly(filename)) { continue; } MonoAndroidHelper.CopyIfChanged(copysrc, Path.Combine(copydst, filename)); try { MonoAndroidHelper.CopyIfChanged(assembly.ItemSpec + ".mdb", Path.Combine(copydst, filename + ".mdb")); } catch (Exception) { // skip it, mdb sometimes fails to read and it's optional } } } catch (ResolutionException ex) { Diagnostic.Error(2006, ex, "Reference to metadata item '{0}' (defined in '{1}') from '{1}' could not be resolved.", ex.Member, ex.Member.Module.Assembly, ex.Scope); } return(true); }
bool Execute(DirectoryAssemblyResolver res) { // Put every assembly we'll need in the resolver foreach (var assembly in ResolvedAssemblies) { res.Load(Path.GetFullPath(assembly.ItemSpec)); } var resolver = new AssemblyResolver(res.ToResolverCache()); // Set up for linking var options = new LinkerOptions(); options.MainAssembly = res.GetAssembly(MainAssembly); options.OutputDirectory = Path.GetFullPath(OutputDirectory); options.LinkSdkOnly = string.Compare(LinkMode, "SdkOnly", true) == 0; options.LinkNone = false; options.Resolver = resolver; options.LinkDescriptions = LinkDescriptions.Select(item => Path.GetFullPath(item.ItemSpec)).ToArray(); options.I18nAssemblies = Linker.ParseI18nAssemblies(I18nAssemblies); if (!options.LinkSdkOnly) { options.RetainAssemblies = GetRetainAssemblies(res); } options.DumpDependencies = DumpDependencies; options.HttpClientHandlerType = HttpClientHandlerType; options.TlsProvider = TlsProvider; options.PreserveJniMarshalMethods = PreserveJniMarshalMethods; options.DeterministicOutput = Deterministic; var skiplist = new List <string> (); if (string.Compare(UseSharedRuntime, "true", true) == 0) { skiplist.AddRange(Profile.SharedRuntimeAssemblies.Where(a => a.EndsWith(".dll")).Select(a => Path.GetFileNameWithoutExtension(a))); } // Add LinkSkip options if (!string.IsNullOrWhiteSpace(LinkSkip)) { skiplist.AddRange(LinkSkip.Split(',', ';')); } options.SkippedAssemblies = skiplist; if (EnableProguard) { options.ProguardConfiguration = ProguardConfiguration; } // Link! try { LinkContext link_context; Linker.Process(options, this, out link_context); foreach (var assembly in ResolvedAssemblies) { var copysrc = assembly.ItemSpec; var filename = Path.GetFileName(assembly.ItemSpec); var assemblyDestination = Path.Combine(OutputDirectory, filename); if (!MonoAndroidHelper.IsForceRetainedAssembly(filename)) { continue; } MonoAndroidHelper.CopyAssemblyAndSymbols(copysrc, assemblyDestination); } } catch (ResolutionException ex) { Diagnostic.Error(2006, ex, "Could not resolve reference to '{0}' (defined in assembly '{1}') with scope '{2}'. When the scope is different from the defining assembly, it usually means that the type is forwarded.", ex.Member, ex.Member.Module.Assembly, ex.Scope); } return(true); }
protected override string GenerateCommandLineCommands() { ProcessArguments arguments = null; if (!InvokeLinkerUsingMono) { arguments = ProcessArguments.Create("--verbose"); } else { var toolsPath = GetPathToMonoLinker(); Log.LogMessage(MessageImportance.High, $"Running monolinker from {toolsPath}."); arguments = ProcessArguments.Create(toolsPath); arguments = arguments.Add("--verbose"); } arguments = arguments.AddRange("--deterministic"); // add exclude features arguments = arguments.AddRange("--exclude-feature", "remoting", "--exclude-feature", "com", "--exclude-feature", "etw"); string coremode, usermode; switch ((WasmLinkMode)Enum.Parse(typeof(WasmLinkMode), LinkMode)) { case WasmLinkMode.SdkOnly: coremode = "link"; usermode = "copy"; break; case WasmLinkMode.Full: coremode = "link"; usermode = "link"; break; default: coremode = "copyused"; usermode = "copy"; break; } arguments = arguments.AddRange("-c", coremode, "-u", usermode); //the linker doesn't consider these core by default foreach (var bn in bindingNames) { arguments = arguments.AddRange("-p", coremode, bn); } if (!string.IsNullOrEmpty(LinkSkip)) { var skips = LinkSkip.Split(new[] { ';', ',', ' ', '\t', '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); foreach (var s in skips) { arguments = arguments.AddRange("-p", "copy", s); } } arguments = arguments.AddRange("-out", OutputDir); arguments = arguments.AddRange("-d", FrameworkDir); arguments = arguments.AddRange("-d", Path.Combine(FrameworkDir, "Facades")); arguments = arguments.AddRange("-b", Debug.ToString()); arguments = arguments.AddRange("-v", Debug.ToString()); // add custom link descriptions // to ensure the type, methods and/or fields are not eliminated from your application. if (LinkDescriptions != null) { foreach (var desc in LinkDescriptions) { var l = desc.GetMetadata("FullPath"); arguments = arguments.AddRange("-x", l); } } arguments = arguments.AddRange("-a", RootAssembly[0].GetMetadata("FullPath")); //we'll normally have to check most of the files because the SDK references most framework asm by default //so let's enumerate upfront var frameworkAssemblies = new HashSet <string> (StringComparer.OrdinalIgnoreCase); foreach (var f in Directory.EnumerateFiles(FrameworkDir)) { frameworkAssemblies.Add(Path.GetFileNameWithoutExtension(f)); } foreach (var f in Directory.EnumerateFiles(Path.Combine(FrameworkDir, "Facades"))) { frameworkAssemblies.Add(Path.GetFileNameWithoutExtension(f)); } // Load the runtime assemblies to be replaced in the references below var runtimeCopyLocal = new Dictionary <string, string> (StringComparer.OrdinalIgnoreCase); if (RuntimeCopyLocalAssemblies != null) { foreach (var copyAsm in RuntimeCopyLocalAssemblies) { var p = copyAsm.GetMetadata("FullPath"); if (frameworkAssemblies.Contains(Path.GetFileNameWithoutExtension(p))) { continue; } runtimeCopyLocal.Add(Path.GetFileNameWithoutExtension(p), p); } } //add references for non-framework assemblies if (Assemblies != null) { foreach (var asm in Assemblies) { var p = asm.GetMetadata("FullPath"); if (frameworkAssemblies.Contains(Path.GetFileNameWithoutExtension(p))) { continue; } if (runtimeCopyLocal.TryGetValue(Path.GetFileNameWithoutExtension(p), out var runtimePath)) { if (!string.IsNullOrEmpty(BindingsDir) && bindingNames.Contains(Path.GetFileNameWithoutExtension(p))) { runtimePath = Path.Combine(BindingsDir, Path.GetFileName(p)); } // Just in case if (File.Exists(runtimePath)) { p = runtimePath; } } arguments = arguments.AddRange("-r", p); } } if (string.IsNullOrEmpty(I18n)) { arguments = arguments.AddRange("-l", "none"); } else { var vals = I18n.Split(new[] { ',', ';', ' ', '\r', '\n', '\t' }); arguments = arguments.AddRange("-l", string.Join(",", vals)); } return(arguments.ToString()); }