зеркало из https://github.com/mono/ikvm-fork.git
Use "ikvm.exports" map for "wildcard exports" (i.e. assemblies that are referenced and whose types are available thru the assembly class loader).
This commit is contained in:
Родитель
a7e9899995
Коммит
9803e4805b
|
@ -422,15 +422,20 @@ namespace IKVM.Internal
|
||||||
((DynamicClassLoader)this.GetTypeWrapperFactory()).FinishAll();
|
((DynamicClassLoader)this.GetTypeWrapperFactory()).FinishAll();
|
||||||
|
|
||||||
ModuleBuilder mb = GetTypeWrapperFactory().ModuleBuilder;
|
ModuleBuilder mb = GetTypeWrapperFactory().ModuleBuilder;
|
||||||
// HACK force all referenced assemblies to end up as references in the assembly
|
if(targetIsModule)
|
||||||
// (even if they are otherwise unused), to make sure that the assembly class loader
|
|
||||||
// delegates to them at runtime.
|
|
||||||
for(int i = 0;i < referencedAssemblies.Length; i++)
|
|
||||||
{
|
{
|
||||||
Type[] types = referencedAssemblies[i].MainAssembly.GetExportedTypes();
|
// HACK force all referenced assemblies to end up as references in the assembly
|
||||||
if(types.Length > 0)
|
// (even if they are otherwise unused), to make sure that the assembly class loader
|
||||||
|
// delegates to them at runtime.
|
||||||
|
// NOTE now we only do this for modules, when we're an assembly we store the exported
|
||||||
|
// assemblies in the ikvm.exports resource.
|
||||||
|
for(int i = 0;i < referencedAssemblies.Length; i++)
|
||||||
{
|
{
|
||||||
mb.GetTypeToken(types[0]);
|
Type[] types = referencedAssemblies[i].MainAssembly.GetExportedTypes();
|
||||||
|
if(types.Length > 0)
|
||||||
|
{
|
||||||
|
mb.GetTypeToken(types[0]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mb.CreateGlobalFunctions();
|
mb.CreateGlobalFunctions();
|
||||||
|
@ -454,18 +459,19 @@ namespace IKVM.Internal
|
||||||
mb.SetCustomAttribute(cab);
|
mb.SetCustomAttribute(cab);
|
||||||
}
|
}
|
||||||
|
|
||||||
// add a package list
|
// add a package list and export map
|
||||||
if(options.sharedclassloader == null || options.sharedclassloader[0] == this)
|
if(options.sharedclassloader == null || options.sharedclassloader[0] == this)
|
||||||
{
|
{
|
||||||
string[] list = new string[packages.Count];
|
string[] list = new string[packages.Count];
|
||||||
packages.Keys.CopyTo(list, 0);
|
packages.Keys.CopyTo(list, 0);
|
||||||
mb.SetCustomAttribute(new CustomAttributeBuilder(JVM.LoadType(typeof(PackageListAttribute)).GetConstructor(new Type[] { typeof(string[]) }), new object[] { list }));
|
mb.SetCustomAttribute(new CustomAttributeBuilder(JVM.LoadType(typeof(PackageListAttribute)).GetConstructor(new Type[] { typeof(string[]) }), new object[] { list }));
|
||||||
}
|
// We can't add the resource when we're a module, because a multi-module assembly has a single resource namespace
|
||||||
|
// and since you cannot combine -target:module with -sharedclassloader we don't need an export map
|
||||||
// if we're the main assembly in a shared class loader group, add a resource that lists all the types available in the other assemblies
|
// (the wildcard exports have already been added above, by making sure that we statically reference the assemblies).
|
||||||
if(options.sharedclassloader != null && options.sharedclassloader.Count > 1 && options.sharedclassloader[0] == this)
|
if(!targetIsModule)
|
||||||
{
|
{
|
||||||
WriteExportMap();
|
WriteExportMap();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(targetIsModule)
|
if(targetIsModule)
|
||||||
|
@ -482,40 +488,51 @@ namespace IKVM.Internal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void AddExportMapEntry(Dictionary<CompilerClassLoader, List<string>> map, CompilerClassLoader ccl, string name)
|
private static void AddExportMapEntry(Dictionary<AssemblyName, List<string>> map, CompilerClassLoader ccl, string name)
|
||||||
{
|
{
|
||||||
|
AssemblyName asm = ccl.assemblyBuilder.GetName();
|
||||||
List<string> list;
|
List<string> list;
|
||||||
if (!map.TryGetValue(ccl, out list))
|
if (!map.TryGetValue(asm, out list))
|
||||||
{
|
{
|
||||||
list = new List<string>();
|
list = new List<string>();
|
||||||
map.Add(ccl, list);
|
map.Add(asm, list);
|
||||||
|
}
|
||||||
|
if (list != null) // if list is null, we already have a wildcard export for this assembly
|
||||||
|
{
|
||||||
|
list.Add(name);
|
||||||
}
|
}
|
||||||
list.Add(name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void WriteExportMap()
|
private void WriteExportMap()
|
||||||
{
|
{
|
||||||
Dictionary<CompilerClassLoader, List<string>> exportedNamesPerAssembly = new Dictionary<CompilerClassLoader, List<string>>();
|
Dictionary<AssemblyName, List<string>> exportedNamesPerAssembly = new Dictionary<AssemblyName, List<string>>();
|
||||||
|
foreach (AssemblyClassLoader acl in referencedAssemblies)
|
||||||
|
{
|
||||||
|
exportedNamesPerAssembly.Add(acl.MainAssembly.GetName(), null);
|
||||||
|
}
|
||||||
foreach (TypeWrapper tw in dynamicallyImportedTypes)
|
foreach (TypeWrapper tw in dynamicallyImportedTypes)
|
||||||
{
|
{
|
||||||
AddExportMapEntry(exportedNamesPerAssembly, (CompilerClassLoader)tw.GetClassLoader(), tw.Name);
|
AddExportMapEntry(exportedNamesPerAssembly, (CompilerClassLoader)tw.GetClassLoader(), tw.Name);
|
||||||
}
|
}
|
||||||
foreach (CompilerClassLoader ccl in options.sharedclassloader)
|
if (options.sharedclassloader != null)
|
||||||
{
|
{
|
||||||
if (ccl != this)
|
foreach (CompilerClassLoader ccl in options.sharedclassloader)
|
||||||
{
|
{
|
||||||
if (ccl.options.resources != null)
|
if (ccl != this)
|
||||||
{
|
{
|
||||||
foreach (string name in ccl.options.resources.Keys)
|
if (ccl.options.resources != null)
|
||||||
{
|
{
|
||||||
AddExportMapEntry(exportedNamesPerAssembly, ccl, name);
|
foreach (string name in ccl.options.resources.Keys)
|
||||||
|
{
|
||||||
|
AddExportMapEntry(exportedNamesPerAssembly, ccl, name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
if (ccl.options.externalResources != null)
|
||||||
if (ccl.options.externalResources != null)
|
|
||||||
{
|
|
||||||
foreach (string name in ccl.options.externalResources.Keys)
|
|
||||||
{
|
{
|
||||||
AddExportMapEntry(exportedNamesPerAssembly, ccl, name);
|
foreach (string name in ccl.options.externalResources.Keys)
|
||||||
|
{
|
||||||
|
AddExportMapEntry(exportedNamesPerAssembly, ccl, name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -523,13 +540,22 @@ namespace IKVM.Internal
|
||||||
MemoryStream ms = new MemoryStream();
|
MemoryStream ms = new MemoryStream();
|
||||||
BinaryWriter bw = new BinaryWriter(ms);
|
BinaryWriter bw = new BinaryWriter(ms);
|
||||||
bw.Write(exportedNamesPerAssembly.Count);
|
bw.Write(exportedNamesPerAssembly.Count);
|
||||||
foreach (KeyValuePair<CompilerClassLoader, List<string>> kv in exportedNamesPerAssembly)
|
foreach (KeyValuePair<AssemblyName, List<string>> kv in exportedNamesPerAssembly)
|
||||||
{
|
{
|
||||||
bw.Write(kv.Key.assemblyBuilder.GetName().FullName);
|
bw.Write(kv.Key.FullName);
|
||||||
bw.Write(kv.Value.Count);
|
if (kv.Value == null)
|
||||||
foreach (string name in kv.Value)
|
|
||||||
{
|
{
|
||||||
bw.Write(JVM.PersistableHash(name));
|
// wildcard export
|
||||||
|
bw.Write(0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.Assert(kv.Value.Count != 0);
|
||||||
|
bw.Write(kv.Value.Count);
|
||||||
|
foreach (string name in kv.Value)
|
||||||
|
{
|
||||||
|
bw.Write(JVM.PersistableHash(name));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ms.Position = 0;
|
ms.Position = 0;
|
||||||
|
@ -2332,10 +2358,6 @@ namespace IKVM.Internal
|
||||||
{
|
{
|
||||||
compiler.EmitRemappedTypes2ndPass();
|
compiler.EmitRemappedTypes2ndPass();
|
||||||
}
|
}
|
||||||
if (!compilingCoreAssembly)
|
|
||||||
{
|
|
||||||
ClassLoaderWrapper.SetBootstrapClassLoader(ClassLoaderWrapper.GetAssemblyClassLoader(JVM.CoreAssembly));
|
|
||||||
}
|
|
||||||
Dictionary<CompilerClassLoader, CustomAttributeBuilder> mainAssemblyCabs = new Dictionary<CompilerClassLoader, CustomAttributeBuilder>();
|
Dictionary<CompilerClassLoader, CustomAttributeBuilder> mainAssemblyCabs = new Dictionary<CompilerClassLoader, CustomAttributeBuilder>();
|
||||||
foreach (CompilerClassLoader compiler in compilers)
|
foreach (CompilerClassLoader compiler in compilers)
|
||||||
{
|
{
|
||||||
|
|
|
@ -71,6 +71,7 @@ namespace IKVM.Internal
|
||||||
|
|
||||||
#if STATIC_COMPILER
|
#if STATIC_COMPILER
|
||||||
// HACK this is used by the ahead-of-time compiler to overrule the bootstrap classloader
|
// HACK this is used by the ahead-of-time compiler to overrule the bootstrap classloader
|
||||||
|
// when we're compiling the core class libraries
|
||||||
internal static void SetBootstrapClassLoader(ClassLoaderWrapper bootstrapClassLoader)
|
internal static void SetBootstrapClassLoader(ClassLoaderWrapper bootstrapClassLoader)
|
||||||
{
|
{
|
||||||
Debug.Assert(ClassLoaderWrapper.bootstrapClassLoader == null);
|
Debug.Assert(ClassLoaderWrapper.bootstrapClassLoader == null);
|
||||||
|
@ -1057,11 +1058,15 @@ namespace IKVM.Internal
|
||||||
return loader;
|
return loader;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if !STATIC_COMPILER && !FIRST_PASS
|
|
||||||
if(assembly == JVM.CoreAssembly)
|
if(assembly == JVM.CoreAssembly)
|
||||||
{
|
{
|
||||||
return GetBootstrapClassLoader();
|
// This cast is necessary for ikvmc and a no-op for the runtime.
|
||||||
|
// Note that the cast cannot fail, because ikvmc will only return a non AssemblyClassLoader
|
||||||
|
// from GetBootstrapClassLoader() when compiling the core assembly and in that case JVM.CoreAssembly
|
||||||
|
// will be null.
|
||||||
|
return (AssemblyClassLoader)GetBootstrapClassLoader();
|
||||||
}
|
}
|
||||||
|
#if !STATIC_COMPILER && !FIRST_PASS
|
||||||
if(!assembly.ReflectionOnly)
|
if(!assembly.ReflectionOnly)
|
||||||
{
|
{
|
||||||
Type customClassLoaderClass = null;
|
Type customClassLoaderClass = null;
|
||||||
|
@ -1678,20 +1683,20 @@ namespace IKVM.Internal
|
||||||
}
|
}
|
||||||
|
|
||||||
internal AssemblyClassLoader(Assembly assembly, object javaClassLoader, bool hasCustomClassLoader)
|
internal AssemblyClassLoader(Assembly assembly, object javaClassLoader, bool hasCustomClassLoader)
|
||||||
: this(assembly, assembly.GetReferencedAssemblies(), javaClassLoader, hasCustomClassLoader)
|
: this(assembly, null, javaClassLoader, hasCustomClassLoader)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
internal AssemblyClassLoader(Assembly assembly, AssemblyName[] references, object javaClassLoader, bool hasCustomClassLoader)
|
internal AssemblyClassLoader(Assembly assembly, AssemblyName[] fixedReferences, object javaClassLoader, bool hasCustomClassLoader)
|
||||||
: base(CodeGenOptions.None, javaClassLoader)
|
: base(CodeGenOptions.None, javaClassLoader)
|
||||||
{
|
{
|
||||||
this.assemblyLoader = new AssemblyLoader(assembly);
|
this.assemblyLoader = new AssemblyLoader(assembly);
|
||||||
this.references = references;
|
this.references = fixedReferences;
|
||||||
this.isReflectionOnly = assembly.ReflectionOnly;
|
this.isReflectionOnly = assembly.ReflectionOnly;
|
||||||
this.hasCustomClassLoader = hasCustomClassLoader;
|
this.hasCustomClassLoader = hasCustomClassLoader;
|
||||||
delegates = new AssemblyClassLoader[references.Length];
|
if(assembly.GetManifestResourceInfo("ikvm.exports") != null)
|
||||||
if(assembly.GetType("__<MainAssembly>") != null)
|
|
||||||
{
|
{
|
||||||
|
List<AssemblyName> wildcardExports = new List<AssemblyName>();
|
||||||
using(Stream stream = assembly.GetManifestResourceStream("ikvm.exports"))
|
using(Stream stream = assembly.GetManifestResourceStream("ikvm.exports"))
|
||||||
{
|
{
|
||||||
BinaryReader rdr = new BinaryReader(stream);
|
BinaryReader rdr = new BinaryReader(stream);
|
||||||
|
@ -1704,6 +1709,10 @@ namespace IKVM.Internal
|
||||||
{
|
{
|
||||||
exportedAssemblyNames[i] = new AssemblyName(rdr.ReadString());
|
exportedAssemblyNames[i] = new AssemblyName(rdr.ReadString());
|
||||||
int typeCount = rdr.ReadInt32();
|
int typeCount = rdr.ReadInt32();
|
||||||
|
if(typeCount == 0 && references == null)
|
||||||
|
{
|
||||||
|
wildcardExports.Add(exportedAssemblyNames[i]);
|
||||||
|
}
|
||||||
for(int j = 0; j < typeCount; j++)
|
for(int j = 0; j < typeCount; j++)
|
||||||
{
|
{
|
||||||
int hash = rdr.ReadInt32();
|
int hash = rdr.ReadInt32();
|
||||||
|
@ -1717,7 +1726,16 @@ namespace IKVM.Internal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(references == null)
|
||||||
|
{
|
||||||
|
references = wildcardExports.ToArray();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
references = assembly.GetReferencedAssemblies();
|
||||||
|
}
|
||||||
|
delegates = new AssemblyClassLoader[references.Length];
|
||||||
}
|
}
|
||||||
|
|
||||||
internal Assembly MainAssembly
|
internal Assembly MainAssembly
|
||||||
|
|
Загрузка…
Ссылка в новой задаче