xamarin-macios/tools/common/Symbols.cs

199 строки
4.3 KiB
C#
Исходник Обычный вид История

[mtouch] Improve how we make sure native symbols aren't stripped away. Fixes #51710 and #54417. (#2162) * [mtouch] Improve how we make sure native symbols aren't stripped away. Fixes #51710 and #54417. * Refactor required symbol collection to store more information about each symbol (field, function, Objective-C class), and in general make the code more straight forward. * Implement support for generating source code that references these symbols, and do this whenever we can't ask the native linker to keep these symbols (when using bitcode). Additionally make it possible to do this manually, so that the source code can be generated for non-bitcode platforms too (which is useful if the number of symbols is enormous, in which case we might surpass the maximum command-line length). * Also make it possible to completely ignore native symbols, or ignore them on a per-symbol basis. This provides a fallback for users if we get something right and we try to preserve something that shouldn't be preserved (for instance if it doesn't exist), and the user ends up with unfixable linker errors. * Don't collect Objective-C classes unless they're in an assembly with LinkWith attributes. We don't need to preserve Objective-C classes in any other circumstances. * Implement everything for both Xamarin.iOS and Xamarin.Mac, and share the code between them. * Remove previous workaround for bug #51710, since it's no longer needed. * Add tests. https://bugzilla.xamarin.com/show_bug.cgi?id=54417 https://bugzilla.xamarin.com/show_bug.cgi?id=51710 * [mtouch] Make sure to only keep symbols from the current app when code sharing. This fixes a build problem with the interdependent-binding-projects test when testing in Today Extension mode.
2017-06-02 19:29:19 +03:00
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using Mono.Cecil;
namespace Xamarin.Bundler
{
public enum SymbolType
{
Function,
ObjectiveCClass,
Field,
}
public enum SymbolMode
{
Default,
Linker, // pass "-u symbol" to the native linker
Code, // generate code
Ignore, // do nothing and hope for the best
}
public class Symbol
{
public SymbolType Type;
public bool Ignore;
static string ObjectiveCPrefix {
get {
return "OBJC_CLASS_$_";
}
}
[mtouch] Improve how we make sure native symbols aren't stripped away. Fixes #51710 and #54417. (#2162) * [mtouch] Improve how we make sure native symbols aren't stripped away. Fixes #51710 and #54417. * Refactor required symbol collection to store more information about each symbol (field, function, Objective-C class), and in general make the code more straight forward. * Implement support for generating source code that references these symbols, and do this whenever we can't ask the native linker to keep these symbols (when using bitcode). Additionally make it possible to do this manually, so that the source code can be generated for non-bitcode platforms too (which is useful if the number of symbols is enormous, in which case we might surpass the maximum command-line length). * Also make it possible to completely ignore native symbols, or ignore them on a per-symbol basis. This provides a fallback for users if we get something right and we try to preserve something that shouldn't be preserved (for instance if it doesn't exist), and the user ends up with unfixable linker errors. * Don't collect Objective-C classes unless they're in an assembly with LinkWith attributes. We don't need to preserve Objective-C classes in any other circumstances. * Implement everything for both Xamarin.iOS and Xamarin.Mac, and share the code between them. * Remove previous workaround for bug #51710, since it's no longer needed. * Add tests. https://bugzilla.xamarin.com/show_bug.cgi?id=54417 https://bugzilla.xamarin.com/show_bug.cgi?id=51710 * [mtouch] Make sure to only keep symbols from the current app when code sharing. This fixes a build problem with the interdependent-binding-projects test when testing in Today Extension mode.
2017-06-02 19:29:19 +03:00
string name;
public string Name {
get {
if (name != null)
return name;
if (ObjectiveCName != null)
return ObjectiveCPrefix + ObjectiveCName;
2020-01-31 23:02:52 +03:00
throw ErrorHelper.CreateError (99, Errors.MX0099, $"symbol without a name (type: {Type})");
[mtouch] Improve how we make sure native symbols aren't stripped away. Fixes #51710 and #54417. (#2162) * [mtouch] Improve how we make sure native symbols aren't stripped away. Fixes #51710 and #54417. * Refactor required symbol collection to store more information about each symbol (field, function, Objective-C class), and in general make the code more straight forward. * Implement support for generating source code that references these symbols, and do this whenever we can't ask the native linker to keep these symbols (when using bitcode). Additionally make it possible to do this manually, so that the source code can be generated for non-bitcode platforms too (which is useful if the number of symbols is enormous, in which case we might surpass the maximum command-line length). * Also make it possible to completely ignore native symbols, or ignore them on a per-symbol basis. This provides a fallback for users if we get something right and we try to preserve something that shouldn't be preserved (for instance if it doesn't exist), and the user ends up with unfixable linker errors. * Don't collect Objective-C classes unless they're in an assembly with LinkWith attributes. We don't need to preserve Objective-C classes in any other circumstances. * Implement everything for both Xamarin.iOS and Xamarin.Mac, and share the code between them. * Remove previous workaround for bug #51710, since it's no longer needed. * Add tests. https://bugzilla.xamarin.com/show_bug.cgi?id=54417 https://bugzilla.xamarin.com/show_bug.cgi?id=51710 * [mtouch] Make sure to only keep symbols from the current app when code sharing. This fixes a build problem with the interdependent-binding-projects test when testing in Today Extension mode.
2017-06-02 19:29:19 +03:00
}
set {
name = value;
if (name.StartsWith (ObjectiveCPrefix, StringComparison.Ordinal)) {
ObjectiveCName = name.Substring (ObjectiveCPrefix.Length);
name = null;
}
[mtouch] Improve how we make sure native symbols aren't stripped away. Fixes #51710 and #54417. (#2162) * [mtouch] Improve how we make sure native symbols aren't stripped away. Fixes #51710 and #54417. * Refactor required symbol collection to store more information about each symbol (field, function, Objective-C class), and in general make the code more straight forward. * Implement support for generating source code that references these symbols, and do this whenever we can't ask the native linker to keep these symbols (when using bitcode). Additionally make it possible to do this manually, so that the source code can be generated for non-bitcode platforms too (which is useful if the number of symbols is enormous, in which case we might surpass the maximum command-line length). * Also make it possible to completely ignore native symbols, or ignore them on a per-symbol basis. This provides a fallback for users if we get something right and we try to preserve something that shouldn't be preserved (for instance if it doesn't exist), and the user ends up with unfixable linker errors. * Don't collect Objective-C classes unless they're in an assembly with LinkWith attributes. We don't need to preserve Objective-C classes in any other circumstances. * Implement everything for both Xamarin.iOS and Xamarin.Mac, and share the code between them. * Remove previous workaround for bug #51710, since it's no longer needed. * Add tests. https://bugzilla.xamarin.com/show_bug.cgi?id=54417 https://bugzilla.xamarin.com/show_bug.cgi?id=51710 * [mtouch] Make sure to only keep symbols from the current app when code sharing. This fixes a build problem with the interdependent-binding-projects test when testing in Today Extension mode.
2017-06-02 19:29:19 +03:00
}
}
public string ObjectiveCName;
public string Prefix {
get {
return "_";
}
}
[mtouch] Improve how we make sure native symbols aren't stripped away. Fixes #51710 and #54417. (#2162) * [mtouch] Improve how we make sure native symbols aren't stripped away. Fixes #51710 and #54417. * Refactor required symbol collection to store more information about each symbol (field, function, Objective-C class), and in general make the code more straight forward. * Implement support for generating source code that references these symbols, and do this whenever we can't ask the native linker to keep these symbols (when using bitcode). Additionally make it possible to do this manually, so that the source code can be generated for non-bitcode platforms too (which is useful if the number of symbols is enormous, in which case we might surpass the maximum command-line length). * Also make it possible to completely ignore native symbols, or ignore them on a per-symbol basis. This provides a fallback for users if we get something right and we try to preserve something that shouldn't be preserved (for instance if it doesn't exist), and the user ends up with unfixable linker errors. * Don't collect Objective-C classes unless they're in an assembly with LinkWith attributes. We don't need to preserve Objective-C classes in any other circumstances. * Implement everything for both Xamarin.iOS and Xamarin.Mac, and share the code between them. * Remove previous workaround for bug #51710, since it's no longer needed. * Add tests. https://bugzilla.xamarin.com/show_bug.cgi?id=54417 https://bugzilla.xamarin.com/show_bug.cgi?id=51710 * [mtouch] Make sure to only keep symbols from the current app when code sharing. This fixes a build problem with the interdependent-binding-projects test when testing in Today Extension mode.
2017-06-02 19:29:19 +03:00
List<MemberReference> members = new List<MemberReference> ();
public IEnumerable<MemberReference> Members { get { return members; } }
public HashSet<AssemblyDefinition> Assemblies { get; private set; } = new HashSet<AssemblyDefinition> ();
public void AddMember (MemberReference member)
{
members.Add (member);
Assemblies.Add (member.Module.Assembly);
}
public void AddAssembly (AssemblyDefinition assembly)
{
Assemblies.Add (assembly);
}
}
public class Symbols : IEnumerable<Symbol>
{
Dictionary<string, Symbol> store = new Dictionary<string, Symbol> (StringComparer.Ordinal);
public int Count {
get {
return store.Count;
}
}
public void Add (Symbol symbol)
{
store.Add (symbol.Name, symbol);
}
public Symbol AddObjectiveCClass (string class_name)
{
var symbol = new Symbol {
Type = SymbolType.ObjectiveCClass,
ObjectiveCName = class_name,
};
var existing = Find (symbol.Name);
if (existing != null)
return existing;
Add (symbol);
return symbol;
}
public Symbol AddField (string name)
{
Symbol rv = Find (name);
if (rv == null) {
rv = new Symbol { Name = name, Type = SymbolType.Field };
Add (rv);
}
return rv;
}
public Symbol AddFunction (string name)
{
Symbol rv = Find (name);
if (rv == null) {
rv = new Symbol { Name = name, Type = SymbolType.Function };
Add (rv);
}
return rv;
}
public void Remove (Func<Symbol, bool> condition)
{
foreach (var symbol in this) {
if (condition (symbol))
store.Remove (symbol.Name);
}
}
public IEnumerator<Symbol> GetEnumerator ()
{
return store.Values.GetEnumerator ();
}
IEnumerator IEnumerable.GetEnumerator ()
{
return store.Values.GetEnumerator ();
}
public Symbol Find (string name)
{
Symbol rv;
store.TryGetValue (name, out rv);
return rv;
}
public bool Contains (string name)
{
return store.ContainsKey (name);
}
public Symbol this [string name] {
get {
return store [name];
}
}
public void Load (string filename, Target target)
{
using (var reader = new StreamReader (filename)) {
string line;
Symbol current = null;
while ((line = reader.ReadLine ()) != null) {
if (line.Length == 0)
continue;
if (line [0] == '\t') {
var asm = line.Substring (1);
Assembly assembly;
if (!target.Assemblies.TryGetValue (Assembly.GetIdentity (asm), out assembly))
2020-01-31 23:02:52 +03:00
throw ErrorHelper.CreateError (99, Errors.MX0099, $"serialized assembly {asm} for symbol {current.Name}, but no such assembly loaded");
[mtouch] Improve how we make sure native symbols aren't stripped away. Fixes #51710 and #54417. (#2162) * [mtouch] Improve how we make sure native symbols aren't stripped away. Fixes #51710 and #54417. * Refactor required symbol collection to store more information about each symbol (field, function, Objective-C class), and in general make the code more straight forward. * Implement support for generating source code that references these symbols, and do this whenever we can't ask the native linker to keep these symbols (when using bitcode). Additionally make it possible to do this manually, so that the source code can be generated for non-bitcode platforms too (which is useful if the number of symbols is enormous, in which case we might surpass the maximum command-line length). * Also make it possible to completely ignore native symbols, or ignore them on a per-symbol basis. This provides a fallback for users if we get something right and we try to preserve something that shouldn't be preserved (for instance if it doesn't exist), and the user ends up with unfixable linker errors. * Don't collect Objective-C classes unless they're in an assembly with LinkWith attributes. We don't need to preserve Objective-C classes in any other circumstances. * Implement everything for both Xamarin.iOS and Xamarin.Mac, and share the code between them. * Remove previous workaround for bug #51710, since it's no longer needed. * Add tests. https://bugzilla.xamarin.com/show_bug.cgi?id=54417 https://bugzilla.xamarin.com/show_bug.cgi?id=51710 * [mtouch] Make sure to only keep symbols from the current app when code sharing. This fixes a build problem with the interdependent-binding-projects test when testing in Today Extension mode.
2017-06-02 19:29:19 +03:00
current.AddAssembly (assembly.AssemblyDefinition);
} else {
var eq = line.IndexOf ('=');
var typestr = line.Substring (0, eq);
var name = line.Substring (eq + 1);
current = new Symbol { Name = name, Type = (SymbolType) Enum.Parse (typeof (SymbolType), typestr) };
Add (current);
}
}
}
}
public void Save (string filename)
{
using (var writer = new StreamWriter (filename)) {
foreach (var symbol in store.Values) {
writer.WriteLine ("{0}={1}", symbol.Type, symbol.Name);
foreach (var asm in symbol.Assemblies)
writer.WriteLine ($"\t{asm.MainModule.FileName}");
}
}
}
}
}