-
Notifications
You must be signed in to change notification settings - Fork 541
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[XABT] Move marshal method generation to a "linker step". #10027
base: main
Are you sure you want to change the base?
Conversation
…>` tasks to use an actual pipeline.
5a287b2
to
d8bcd19
Compare
There seems to be an issue with this as we move from an "all at once" model to an incremental "per-assembly" model. Previously we would scan all assemblies with the marshal method classifier to determine which methods needed to be changed. Then we would perform the needed modifications on all the assemblies. In the new process, we would like to be able to convert single assemblies independently. For example, in an incremental build where only a user's custom binding project changed, we do not want to rerun the marshal method generation process on every assembly in the project. However, this leads to a problem, as scanning an assembly requires being able to find the relevant "connector" method which may be in a dependent assembly. If this dependent assembly has already gone through the marshal method process then the connector method has already been removed then the marshal method process fails to convert the new method. A concrete example:
// Xamarin.AndroidX.Core - 1.12.0.2
[Register("androidx/core/app/ComponentActivity", DoNotGenerateAcw = true)]
public class AndroidX.Core.App.ComponentActivity.ComponentActivity : Activity, KeyEventDispatcher.IComponent, IJavaObject, IDisposable, IJavaPeerable, ILifecycleOwner
{
public unsafe virtual Lifecycle Lifecycle
{
[Register("getLifecycle", "()Landroidx/lifecycle/Lifecycle;", "GetGetLifecycleHandler")]
get {
JniObjectReference val = _members.get_InstanceMethods().InvokeVirtualObjectMethod("getLifecycle.()Landroidx/lifecycle/Lifecycle;", (IJavaPeerable)(object)this, (JniArgumentValue*)null);
return Object.GetObject<Lifecycle>(((JniObjectReference)(ref val)).get_Handle(), (JniHandleOwnership)1);
}
}
private static IntPtr n_GetLifecycle(IntPtr jnienv, IntPtr native__this)
{
return JNIEnv.ToLocalJniHandle((IJavaObject)(object)Object.GetObject<ComponentActivity>(jnienv, native__this, (JniHandleOwnership)0).Lifecycle);
}
private static Delegate GetGetLifecycleHandler()
{
if ((object)cb_getLifecycle == null) {
cb_getLifecycle = JNINativeWrapper.CreateDelegate((Delegate)new _JniMarshal_PP_L(n_GetLifecycle));
}
return cb_getLifecycle;
}
}
// Xamarin.AndroidX.Lifecycle.Common - 2.6.2.2
[Register("androidx/lifecycle/LifecycleOwner", "", "AndroidX.Lifecycle.ILifecycleOwnerInvoker")]
public interface AndroidX.Lifecycle.ILifecycleOwner : IJavaObject, IDisposable, IJavaPeerable
{
Lifecycle Lifecycle
{
[Register("getLifecycle", "()Landroidx/lifecycle/Lifecycle;", "GetGetLifecycleHandler:AndroidX.Lifecycle.ILifecycleOwnerInvoker, Xamarin.AndroidX.Lifecycle.Common")]
get;
}
}
[Register("androidx/lifecycle/LifecycleOwner", DoNotGenerateAcw = true)]
internal class AndroidX.Lifecycle.ILifecycleOwnerInvoker : Object, ILifecycleOwner, IJavaObject, IDisposable, IJavaPeerable
{
public Lifecycle Lifecycle
{
get
{
if (id_getLifecycle == IntPtr.Zero)
{
id_getLifecycle = JNIEnv.GetMethodID(class_ref, "getLifecycle", "()Landroidx/lifecycle/Lifecycle;");
}
return Object.GetObject<Lifecycle>(JNIEnv.CallObjectMethod(((Object)this).get_Handle(), id_getLifecycle), (JniHandleOwnership)1);
}
}
private static IntPtr n_GetLifecycle(IntPtr jnienv, IntPtr native__this)
{
return JNIEnv.ToLocalJniHandle((IJavaObject)(object)Object.GetObject<ILifecycleOwner>(jnienv, native__this, (JniHandleOwnership)0).Lifecycle);
}
private static Delegate GetGetLifecycleHandler()
{
if ((object)cb_getLifecycle == null)
{
cb_getLifecycle = JNINativeWrapper.CreateDelegate((Delegate)new _JniMarshal_PP_L(n_GetLifecycle));
}
return cb_getLifecycle;
}
} Now imagine that the marshal method rewriter runs on the It removes // Xamarin.AndroidX.Lifecycle.Common - 2.6.2.2
[Register("androidx/lifecycle/LifecycleOwner", DoNotGenerateAcw = true)]
internal class AndroidX.Lifecycle.ILifecycleOwnerInvoker : Object, ILifecycleOwner, IJavaObject, IDisposable, IJavaPeerable
{
[UnmanagedCallersOnly]
private static IntPtr n_GetLifecycle_mm_wrapper(IntPtr jnienv, IntPtr native__this)
{
AndroidRuntimeInternal.WaitForBridgeProcessing();
try
{
return n_GetLifecycle(jnienv, native__this);
}
catch (System.Exception e)
{
Android.Runtime.AndroidEnvironmentInternal.UnhandledException(e);
return (IntPtr)0;
}
}
} Then we run the marshal method rewriter on
|
d8bcd19
to
d26e3a2
Compare
An easier example would be "app assembly" and We will need to retain the |
This commit moves the process of rewriting marshal methods found in Java binding libraries to a new
RewriteMarshalMethodsStep
"linker step".The marshal method generation step involves scanning through all assemblies that may contain Java bindings with Cecil, making changes, and writing the assemblies back out to disk. By combining this with our "linker steps" pipeline, we only need to open, modify, and write the assemblies to disk once instead of twice.