Skip to content
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

Value Marshaling with Expressions #8

Closed
jonpryor opened this issue Apr 7, 2015 · 0 comments
Closed

Value Marshaling with Expressions #8

jonpryor opened this issue Apr 7, 2015 · 0 comments

Comments

@jonpryor
Copy link
Member

jonpryor commented Apr 7, 2015

Fix marshaling

  • I don't like JniMarshalInfo; it's too convoluted, makes the simple cases hard.

  • Do in conjunction w/ Java.Interop.Dynamic

  • Need to permit use of custom attributes on return types, parameter types, "inline" into marshal methods.

  • Need to use System.Linq.Expressions/etc. to "merge"/do the work of monodroid/tools/generator, so that Java.Interop.Export can support value types, etc.

  • Use case: Android.Graphics.Color, which is marshaled from JNI as an int but to managed as an Android.Graphics.Color struct, and vice-versa.

  • Should probably split JniMarshalInfo into separate "to managed" and "from managed" types?

    • No; needless added complexity, and when it comes to System.Linq.Expressions many of the type information will be shared between them.
  • "New" marshaling support should try to leverage Expression<TDelegate> to make it easier to write marshalers:

    public class JnIValueMarshaler<TJni, TManaged> : JniValueMarshaler {
        public sealed override Expression<Func<JniValueMarshalerContext, TJni, TManaged>> JniTypeToManagedType (JniValueMarshalerContext context,  Expression jniSourceValue,     Expression manageDestinationdValue);
        public abstract Expression<Func<JniValueMarshaler, TJni, TManaged> JniTypeToManagedType ();
    }
    class Int32Marshaler : JniValueMarshaler<int, int> {
        public override Expression<Func<JniValueMarshalerContext, TJni, TManaged>> JniTypeToManagedType (JniValueMarshalerContext context,  Expression jniSourceValue,     Expression manageDestinationdValue)
        {
            return (c, jni) => jni;
        }
    }
    
  • With such a system in place, we'll need to be able to "rebind" the Expression<Func<...>> parameters with the generated parameters

    http://stackoverflow.com/questions/8610506/binding-parameter-in-expression-trees

    class MyVisitor : ExpressionVisitor {
        ParameterExpression[] old, cur;
        public MyVisitor(ParameterExpression[] old, ParameterExpression[] cur)
        {
            this.old = old;
            this.cur = cur;
        }
        protected override Expression VisitParameter(ParameterExpression node)
        {
            for (int i = 0; i < old.Length; ++i) {
                if (old [i].Name == node.Name && old [i].Type == node.Type)
                    return cur [i];
                }
            return node;
        }
    }
    

    With MyVisitor, we can then convert the result of Int32Marshaler.JniTypeToManagedType():

    var p = Expression.Parameter (typeof (int), "p");
    var c = Expression.Parameter (typeof (JniValueMarshalerContext), "c");
    var e = new Int32Marshaler ().JniValueMarshalerContext ();
    var v = new MyVisitor (e.Parameters, new[]{c, p});
    var e = Expression.Lambda<Func<JniValueMarshalerContext, int, int>>(v.Visit (e.Body), new[]{c, p});
    

Probably related: JniMarshalInfoAttribute, a custom attribute to control marshaling behavior?

We'll also need similar custom attributes to control parameter and return type marshaling, via the above Expression architecture.

jonpryor added a commit that referenced this issue Nov 27, 2015
Context: #8

Rename JniRuntime.JniValueMarshaler to JniRuntime.JniValueManager.

The reason for this is that the likely fix for issue 8
("Value Marshaling with Expressions") will involve adding a type named
JniValueMarshaler ("JniMarshalInfo" should die!), and having two
different JniValueMarshaler types running around would be confusing.

Added benefit: JniValueManager is more consistent with JniTypeManager.

:-)
jonpryor added a commit that referenced this issue Dec 4, 2015
Context: #2
Context: #8

From Issue #8:

> I don't like JniMarshalInfo; it's too convoluted, makes the
> simple cases hard.

What do we mean by "hard"?  We mean that it's use is error prone,
because what you need to do depends on the values of the
JniMarshalInfo members, which is best characterized by what
JniArgumentMarshalInfo had to do to create a JNI Local refererence:

	JniObjectReference lref;

	var marshaler = JniRuntime.CurrentRuntime.ValueManager.GetJniMarshalInfoForType (type);
	if (info.CreateMarshalCollection != null) {
		var obj = info.CreateMarshalCollection (value);
		lref    = obj.PeerReference;
	} else if (info.CreateLocalRef != null) {
		lref    = info.CreateLocalRef (value);
	} else
		throw new NotSupportedException ("Don't know how to get a JNI Local Reference!");

	// can now use `lref`...

Need to pass as a method argument? Similar-yet-different.  Then
there's the cleanup code!

The eventual intention is for tools/jnimarshalmethod-gen to
post-process assemblies and generate Java > Managed marshal methods
for all resolvable methods, and do this "dynamically" based on the
actual types involved.  This will allow "fixing" binding assemblies
when involved types change, because binding assemblies won't be as
"static" as they are in Xamarin.Android.  (Which is why Issue #8
mentions using Expressions for the marshaling.)

However, before we can get there we first need a rational marshaling
abstrasction, something that is "pluggable" and readily extensible, so
taht we can e.g. have a custom attribute to control which marshaler to
use on types, parameters, and method return types.  JniMarshalInfo
wasn't that abstraction, and couldn't *be* that abstraction.

To replace JniMarshalInfo, introduce JniValueMarshaler and
JniValueMarshler<T>:

	public abstract partial class JniValueMarshaler {
		public  abstract    object                  CreateValue (ref JniObjectReference reference, JniObjectReferenceOptions options, Type targetType = null);
		public  virtual     JniValueMarshalerState  CreateArgumentState (object value, ParameterAttributes synchronize = 0);
		public  abstract    JniValueMarshalerState  CreateObjectReferenceArgumentState (object value, ParameterAttributes synchronize = 0);
		public  abstract    void                    DestroyArgumentState (object value, ref JniValueMarshalerState state, ParameterAttributes synchronize = 0);
	}

	public abstract partial class JniValueMarshaler<T> : JniValueMarshaler {
		public  abstract    T                       CreateGenericValue (ref JniObjectReference reference, JniObjectReferenceOptions options, Type targetType = null);
		public  virtual     JniValueMarshalerState  CreateGenericArgumentState (T value, ParameterAttributes synchronize = 0);
		public  abstract    JniValueMarshalerState  CreateGenericObjectReferenceArgumentState (T value, ParameterAttributes synchronize = 0);
		public  abstract    void                    DestroyGenericArgumentState (T value, ref JniValueMarshalerState state, ParameterAttributes synchronize = 0);

		public override object                  CreateValue (ref JniObjectReference reference, JniObjectReferenceOptions options, Type targetType = null);
		public override JniValueMarshalerState  CreateArgumentState (object value, ParameterAttributes synchronize = 0);
		public override JniValueMarshalerState  CreateObjectReferenceArgumentState (object value, ParameterAttributes synchronize = 0);
		public override void                    DestroyArgumentState (object value, ref JniValueMarshalerState state, ParameterAttributes synchronize = 0);
	}

The intention is that a custom marshaler can be introduced by
inheriting from JniValueMarshaler<T> and overriding three methods.
This also provides a reasonable abstraction, e.g. to create a
JNI Local Reference:

	var state = marshaler.CreateGenericObjectReferenceArgumentState (value);
	// state.ReferenceValue contains a JNI Object Reference
	// use, then cleanup:
	marshaler.DestroyGenericArgumentState (value, ref state);

The methods are as follows:

  * CreateValue, CreateGenericValue:
    Java > Managed marshaler.
    Given a JniObjectReference, marshal the value to a type compatible
    with specified targetType, which should be either null or a class
    assignment compatible to T.

The other methods use a JniValueMarshalerState type:

	public partial struct JniValueMarshalerState {
		public JniArgumentValue         JniArgumentValue {get;}
		public JniObjectReference       ReferenceValue   {get;}
		public IJavaPeerable            PeerableValue    {get;}
	}

The remaining methods of import are:

  * CreateArgumentState(), CreateGenericArgumentState():
    Managed > Java marshaler.
    Used when the intention is to use
    JniValueMarshalerState.JniArgumentValue, which in turn is for use
    with JniEnvironment.*Methods.Call*Method().

  * CreateObjectReferenceArgumentState(),
    CreateGenericObjectReferenceArgumentState():
    Managed > Java marshaler.
    Used when the intention is to use
    JniValueMarshalerState.ReferenceValue.

  * DestroyArgumentState(), DestroyGenericArgumentState(): Generic
    resource cleanup mechanism for use with Create*ArgumentState().

The primary difference between Create*ArgumentState() and
Create*ObjectReferenceArgumentState() is with builtin value types,
e.g. `int`. Create*ArgumentState() will *only* provide a
JniArgumentValue, while JniValueMarshalerState.ReferenceValue will be
null. Create*ObjectReferenceArgumentState(), meanwhile, will "box" the
value type, providing a valid JniValueMarshalerState.ReferenceValue.
For all other types, these methods are identical.

JniValueMarshaler and JniValueMarshalerState together combine to
replace JniMarshalInfo and JniArgumentMarshalInfo, the latter of which
(1) wasn't public, and (2) was "duplicated" between the generic
marshalers and Java.Interop.Dynamic.  JniValueMarshaler thus allows
cleaning up this duplication.

Along with the new JniValueMarshaler abstraction, we provide
implementations for all builtin types, Nullable<T> for builtin types
(which always box), arrays of the builtin types, JavaObjectArray<T>,
IJavaPeerable, and `object`.

The `object` marshaler supersedes the previous
JniMarshal.GetValue<T>() semantics, using JavaProxyObject as needed.

One thing to note is the ParameterAttributes parameters.  This value
is intended to correspond with
System.Reflection.ParameterInfo.Attributes.  jnimarshalmethod-gen can
thus use the actual MethodInfo + ParameterInfo to encode parameter
marshaling direction.  For most types this won't be useful; this is
largely intended for *arrays*, e.g. we could have an `[In] int[]`
parameter which thus avoids the "copy out" behavior Xamarin.Android
currently performs, thus avoiding an extra JNI transition.  Or
vice-versa, have an `[Out] int[]` parameter, which avoids a JNI
transition to copy the managed `int[]` to the Java `int[]`, replacing
it with the copy-out transition.

Partially addressing Issue #2, this also introduces
JniRuntime.JniValueManager.GetValue() and GetValue<T>() methods.
GetObject() is not yet replaced, but will be in a future commit.
Actual implementation will be done alongside introduction of
CreateValue<T>() and cleaning up JniValueMarshaler.Create*Value()
methods to always create values when able, simplifying the logic if
JniValueMarshaler implementations.
jonpryor added a commit that referenced this issue Dec 22, 2015
Mentioned in ff4053c was a feature to complete Issue #8:

> Need to permit use of custom attributes on return types, parameter
> types, "inline" into marshal methods.

Let's do that. :-)

The new Java.Interop.JniValueMarshalerAttribute custom attribute can
be applied to:

  * Types: classes, enums, interfaces, structs

This allows:

	[JniValueMarshaler (typeof (MyCustomMarshaler))]
	public class MySpecialClass /* NOT JavaObject! */ {
	}

	public partial class MyCustomMarshaler : JniValueMarshaler<MySpecialClass> {
		// ...
	}

JniRuntime.JniValueManager.GetValueMarshaler(Type) has been updated to
check for the JniValueMarshalerAttribute and, when present, will
return a new instance of the specified JniValueMarshaler instance:

	var marshaler = JniRuntime.CurrentRuntime.ValueManager.GetValueMarshaler (typeof (MySpecialClass));
	// marshaler ISA MyCustomMarshaler

JniValueMarshalerAttribute can also be applied to:

  * Method parameters
  * Method return types

Java.Interop.Export has been updated to check for the
JniValueMarshalerAttribute custom attribute to marshal parameters and
return types, allowing:

	// e.g. code from an existing library
	public class ExistingType {
	}

	public partial class ExistingTypeValueMarshaler : JniValueMarshaler<ExistingType> {
		// ...
	}

	[JavaCallable]
	public static
		[return: JniValueMarshaler (typeof (ExistingTypeValueMarshaler))] ExistingType
		Foo ([JniValueMarshaler (typeof (ExistingTypeValueMarshaler))] ExistingType value)
	{
		return value;
	}

This allows one-off specification or overriding of value marshalers
for method parameter and return types, particularly useful if you want
to marshal a type that you don't control, and thus can't alter to
contain a [JniValueMarshaler] declaration.
jonpryor added a commit to jonpryor/java.interop that referenced this issue Aug 17, 2016
When `JniRuntime.CreationOptions.DestroyRuntimeOnDispose` is true,
`JavaVM::DestroyJavaVM()` will be invoked when the `JniRuntime`
instance is disposed *or* finalized.

`JreRuntime.CreateJreVM()` would *always* set
`DestroyRuntimeOnDispose` to true, because it called
`JNI_CreateJavaVM()`, so *of course* you'd want to destroy the
Java VM, right?

Which brings us to unit tests. I don't know of any "before all test
fixtures run" and "after all test fixtures run" extension points,
which means:

1. The JVM needs to be created implicitly, "on demand."
2. There's no good way to destroy the JVM created in (1) after all
    tests have finished executing.

Which *really* means that the `JreRuntime` instance is *finalized*,
which sets us up for the unholy trifecta of AppDomain unloads,
finalizers, and JVM shutdown:

For unknown reasons, ~randomly, when running the unit tests (e.g.
`make run-tests`), the test runner will *hang*, indefinitely.

Attaching `lldb` and triggering a backtrace shows the unholy trifecta:

Finalization:

	thread dotnet#4: tid = 0x403831, 0x00007fff9656bdb6 libsystem_kernel.dylib`__psynch_cvwait + 10, name = 'tid_1403'
	  ...
	  frame dotnet#10: 0x00000001001ccb4a mono64`mono_gc_run_finalize(obj=<unavailable>, data=<unavailable>) + 938 at gc.c:256 [opt]
	  frame dotnet#11: 0x00000001001cdd4a mono64`finalizer_thread [inlined] finalize_domain_objects + 51 at gc.c:681 [opt]
	  frame dotnet#12: 0x00000001001cdd17 mono64`finalizer_thread(unused=<unavailable>) + 295 at gc.c:730 [opt]

JVM destruction:

	thread dotnet#4: tid = 0x403831, 0x00007fff9656bdb6 libsystem_kernel.dylib`__psynch_cvwait + 10, name = 'tid_1403'
	  frame #0: 0x00007fff9656bdb6 libsystem_kernel.dylib`__psynch_cvwait + 10
	  frame dotnet#1: 0x00007fffa04d4728 libsystem_pthread.dylib`_pthread_cond_wait + 767
	  frame dotnet#2: 0x000000010ba5bc76 libjvm.dylib`os::PlatformEvent::park() + 192
	  frame dotnet#3: 0x000000010ba38e32 libjvm.dylib`ParkCommon(ParkEvent*, long) + 42
	  frame dotnet#4: 0x000000010ba39708 libjvm.dylib`Monitor::IWait(Thread*, long) + 168
	  frame dotnet#5: 0x000000010ba398f0 libjvm.dylib`Monitor::wait(bool, long, bool) + 246
	  frame dotnet#6: 0x000000010bb3dca2 libjvm.dylib`Threads::destroy_vm() + 80
	  frame dotnet#7: 0x000000010b8fd665 libjvm.dylib`jni_DestroyJavaVM + 254

AppDomain unload:

	thread dotnet#37: tid = 0x4038fb, 0x00007fff9656bdb6 libsystem_kernel.dylib`__psynch_cvwait + 10
	  frame #0: 0x00007fff9656bdb6 libsystem_kernel.dylib`__psynch_cvwait + 10
	  frame dotnet#1: 0x00007fffa04d4728 libsystem_pthread.dylib`_pthread_cond_wait + 767
	  frame dotnet#2: 0x0000000100234a7f mono64`mono_os_cond_timedwait [inlined] mono_os_cond_wait(cond=0x0000000102016e50, mutex=0x0000000102016e10) + 11 at mono-os-mutex.h:105 [opt]
	  frame dotnet#3: 0x0000000100234a74 mono64`mono_os_cond_timedwait(cond=0x0000000102016e50, mutex=0x0000000102016e10, timeout_ms=<unavailable>) + 164 at mono-os-mutex.h:120 [opt]
	  frame dotnet#4: 0x0000000100234828 mono64`_wapi_handle_timedwait_signal_handle(handle=0x0000000000000440, timeout=4294967295, alertable=1, poll=<unavailable>, alerted=0x0000700000a286f4) + 536 at handles.c:1554 [opt]
	  frame dotnet#5: 0x0000000100246370 mono64`wapi_WaitForSingleObjectEx(handle=<unavailable>, timeout=<unavailable>, alertable=<unavailable>) + 592 at wait.c:189 [opt]
	  frame dotnet#6: 0x00000001001c832e mono64`mono_domain_try_unload [inlined] guarded_wait(timeout=4294967295, alertable=1) + 30 at appdomain.c:2390 [opt]
	  frame dotnet#7: 0x00000001001c8310 mono64`mono_domain_try_unload(domain=0x000000010127ccb0, exc=0x0000700000a287a0) + 416 at appdomain.c:2482 [opt]
	  frame dotnet#8: 0x00000001001c7db2 mono64`ves_icall_System_AppDomain_InternalUnload [inlined] mono_domain_unload(domain=<unavailable>) + 20 at appdomain.c:2379 [opt]
	  frame dotnet#9: 0x00000001001c7d9e mono64`ves_icall_System_AppDomain_InternalUnload(domain_id=<unavailable>) + 46 at appdomain.c:2039 [opt]

This randomly results in deadlock, and hung Jenkins bots.

Fix this behavior by altering `JreRuntime.CreateJreVM()` to *not*
override the value of
`JniRuntime.CreationOptions.DestroyRuntimeOnDispose`. This allows the
constructor of the `JreRuntime` instance to decide whether or not the
JVM is destroyed.

In the case of TestJVM, we *don't* want to destroy the JVM.

This prevents the JVM from being destroyed, which in turn prevents the
hang during process shutdown.
jonpryor added a commit that referenced this issue Aug 17, 2016
When `JniRuntime.CreationOptions.DestroyRuntimeOnDispose` is true,
`JavaVM::DestroyJavaVM()` will be invoked when the `JniRuntime`
instance is disposed *or* finalized.

`JreRuntime.CreateJreVM()` would *always* set
`DestroyRuntimeOnDispose` to true, because it called
`JNI_CreateJavaVM()`, so *of course* you'd want to destroy the
Java VM, right?

Which brings us to unit tests. I don't know of any "before all test
fixtures run" and "after all test fixtures run" extension points,
which means:

1. The JVM needs to be created implicitly, "on demand."
2. There's no good way to destroy the JVM created in (1) after all
    tests have finished executing.

Which *really* means that the `JreRuntime` instance is *finalized*,
which sets us up for the unholy trifecta of AppDomain unloads,
finalizers, and JVM shutdown:

For unknown reasons, ~randomly, when running the unit tests (e.g.
`make run-tests`), the test runner will *hang*, indefinitely.

Attaching `lldb` and triggering a backtrace shows the unholy trifecta:

Finalization:

	thread #4: tid = 0x403831, 0x00007fff9656bdb6 libsystem_kernel.dylib`__psynch_cvwait + 10, name = 'tid_1403'
	  ...
	  frame #10: 0x00000001001ccb4a mono64`mono_gc_run_finalize(obj=<unavailable>, data=<unavailable>) + 938 at gc.c:256 [opt]
	  frame #11: 0x00000001001cdd4a mono64`finalizer_thread [inlined] finalize_domain_objects + 51 at gc.c:681 [opt]
	  frame #12: 0x00000001001cdd17 mono64`finalizer_thread(unused=<unavailable>) + 295 at gc.c:730 [opt]

JVM destruction:

	thread #4: tid = 0x403831, 0x00007fff9656bdb6 libsystem_kernel.dylib`__psynch_cvwait + 10, name = 'tid_1403'
	  frame #0: 0x00007fff9656bdb6 libsystem_kernel.dylib`__psynch_cvwait + 10
	  frame #1: 0x00007fffa04d4728 libsystem_pthread.dylib`_pthread_cond_wait + 767
	  frame #2: 0x000000010ba5bc76 libjvm.dylib`os::PlatformEvent::park() + 192
	  frame #3: 0x000000010ba38e32 libjvm.dylib`ParkCommon(ParkEvent*, long) + 42
	  frame #4: 0x000000010ba39708 libjvm.dylib`Monitor::IWait(Thread*, long) + 168
	  frame #5: 0x000000010ba398f0 libjvm.dylib`Monitor::wait(bool, long, bool) + 246
	  frame #6: 0x000000010bb3dca2 libjvm.dylib`Threads::destroy_vm() + 80
	  frame #7: 0x000000010b8fd665 libjvm.dylib`jni_DestroyJavaVM + 254

AppDomain unload:

	thread #37: tid = 0x4038fb, 0x00007fff9656bdb6 libsystem_kernel.dylib`__psynch_cvwait + 10
	  frame #0: 0x00007fff9656bdb6 libsystem_kernel.dylib`__psynch_cvwait + 10
	  frame #1: 0x00007fffa04d4728 libsystem_pthread.dylib`_pthread_cond_wait + 767
	  frame #2: 0x0000000100234a7f mono64`mono_os_cond_timedwait [inlined] mono_os_cond_wait(cond=0x0000000102016e50, mutex=0x0000000102016e10) + 11 at mono-os-mutex.h:105 [opt]
	  frame #3: 0x0000000100234a74 mono64`mono_os_cond_timedwait(cond=0x0000000102016e50, mutex=0x0000000102016e10, timeout_ms=<unavailable>) + 164 at mono-os-mutex.h:120 [opt]
	  frame #4: 0x0000000100234828 mono64`_wapi_handle_timedwait_signal_handle(handle=0x0000000000000440, timeout=4294967295, alertable=1, poll=<unavailable>, alerted=0x0000700000a286f4) + 536 at handles.c:1554 [opt]
	  frame #5: 0x0000000100246370 mono64`wapi_WaitForSingleObjectEx(handle=<unavailable>, timeout=<unavailable>, alertable=<unavailable>) + 592 at wait.c:189 [opt]
	  frame #6: 0x00000001001c832e mono64`mono_domain_try_unload [inlined] guarded_wait(timeout=4294967295, alertable=1) + 30 at appdomain.c:2390 [opt]
	  frame #7: 0x00000001001c8310 mono64`mono_domain_try_unload(domain=0x000000010127ccb0, exc=0x0000700000a287a0) + 416 at appdomain.c:2482 [opt]
	  frame #8: 0x00000001001c7db2 mono64`ves_icall_System_AppDomain_InternalUnload [inlined] mono_domain_unload(domain=<unavailable>) + 20 at appdomain.c:2379 [opt]
	  frame #9: 0x00000001001c7d9e mono64`ves_icall_System_AppDomain_InternalUnload(domain_id=<unavailable>) + 46 at appdomain.c:2039 [opt]

This randomly results in deadlock, and hung Jenkins bots.

Fix this behavior by altering `JreRuntime.CreateJreVM()` to *not*
override the value of
`JniRuntime.CreationOptions.DestroyRuntimeOnDispose`. This allows the
constructor of the `JreRuntime` instance to decide whether or not the
JVM is destroyed.

In the case of TestJVM, we *don't* want to destroy the JVM.

This prevents the JVM from being destroyed, which in turn prevents the
hang during process shutdown.
jonpryor added a commit to jonpryor/java.interop that referenced this issue Oct 19, 2020
Context: https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1230070

Changes: mono/LineEditor@5a7e3e2...3fa0c2e

  * mono/LineEditor@3fa0c2e: Fix NuGet publishing errors (dotnet#9)
  * mono/LineEditor@06a4ddf: Bump `$(PackageVersion)` to 5.4.1.
  * mono/LineEditor@bce1b7f: Enable .pdb files for Release config & add AzDO build script (dotnet#8)
  * mono/LineEditor@4831e1a: Merge pull request dotnet#6 from terrajobst/code-of-conduct
  * mono/LineEditor@5b4a4aa: Link Code of Conduct
  * mono/LineEditor@410ca3d: Merge pull request dotnet#2 from VEIT-Electronics/master
  * mono/LineEditor@3d802e7: Merge pull request dotnet#1 from VEIT-Electronics/bugfix/ENG-232-line-editor-completions
  * mono/LineEditor@0d43552: fix: text overriding was only platform specific (check platform)

The most important piece is mono/LineEditor@bce1b7f, which will allow
us to redistribute `LineEditor.pdb` in the Xamarin.Android installers.
jonpryor added a commit to jonpryor/java.interop that referenced this issue Oct 19, 2020
Context: https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1230070

Changes: mono/LineEditor@5a7e3e2...3fa0c2e

  * mono/LineEditor@3fa0c2e: Fix NuGet publishing errors (dotnet#9)
  * mono/LineEditor@06a4ddf: Bump `$(PackageVersion)` to 5.4.1.
  * mono/LineEditor@bce1b7f: Enable .pdb files for Release config & add AzDO build script (dotnet#8)
  * mono/LineEditor@4831e1a: Merge pull request dotnet#6 from terrajobst/code-of-conduct
  * mono/LineEditor@5b4a4aa: Link Code of Conduct
  * mono/LineEditor@410ca3d: Merge pull request dotnet#2 from VEIT-Electronics/master
  * mono/LineEditor@3d802e7: Merge pull request dotnet#1 from VEIT-Electronics/bugfix/ENG-232-line-editor-completions
  * mono/LineEditor@0d43552: fix: text overriding was only platform specific (check platform)

The most important piece is mono/LineEditor@bce1b7f, which will allow
us to redistribute `LineEditor.pdb` in the Xamarin.Android installers.
jonpryor added a commit to jonpryor/java.interop that referenced this issue Oct 20, 2020
Context: https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1230070

Changes: mono/LineEditor@5a7e3e2...3fa0c2e

  * mono/LineEditor@3fa0c2e: Fix NuGet publishing errors (dotnet#9)
  * mono/LineEditor@06a4ddf: Bump `$(PackageVersion)` to 5.4.1.
  * mono/LineEditor@bce1b7f: Enable .pdb files for Release config & add AzDO build script (dotnet#8)
  * mono/LineEditor@4831e1a: Merge pull request dotnet#6 from terrajobst/code-of-conduct
  * mono/LineEditor@5b4a4aa: Link Code of Conduct
  * mono/LineEditor@410ca3d: Merge pull request dotnet#2 from VEIT-Electronics/master
  * mono/LineEditor@3d802e7: Merge pull request dotnet#1 from VEIT-Electronics/bugfix/ENG-232-line-editor-completions
  * mono/LineEditor@0d43552: fix: text overriding was only platform specific (check platform)

The most important piece is mono/LineEditor@bce1b7f, which will allow
us to redistribute `LineEditor.pdb` in the Xamarin.Android installers.

Use `LineEditor.pdb` by adding a post-`Build` target to
`logcat-parse/Directory.Build.targets` which copies `LineEditor.pdb`
into `$(OutputPath)`.  This will allow the Xamarin.Android installer
to include `LineEditor.pdb` into the installer packages.
jonpryor added a commit to jonpryor/java.interop that referenced this issue Oct 20, 2020
Context: https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1230070

Changes: mono/LineEditor@5a7e3e2...3fa0c2e

  * mono/LineEditor@3fa0c2e: Fix NuGet publishing errors (dotnet#9)
  * mono/LineEditor@06a4ddf: Bump `$(PackageVersion)` to 5.4.1.
  * mono/LineEditor@bce1b7f: Enable .pdb files for Release config & add AzDO build script (dotnet#8)
  * mono/LineEditor@4831e1a: Merge pull request dotnet#6 from terrajobst/code-of-conduct
  * mono/LineEditor@5b4a4aa: Link Code of Conduct
  * mono/LineEditor@410ca3d: Merge pull request dotnet#2 from VEIT-Electronics/master
  * mono/LineEditor@3d802e7: Merge pull request dotnet#1 from VEIT-Electronics/bugfix/ENG-232-line-editor-completions
  * mono/LineEditor@0d43552: fix: text overriding was only platform specific (check platform)

The most important piece is mono/LineEditor@bce1b7f, which will allow
us to redistribute `LineEditor.pdb` in the Xamarin.Android installers.

Add a post-`Build` target to `logcat-parse/Directory.Build.targets`
which copies `LineEditor.pdb` into `$(OutputPath)`.  This will allow
the Xamarin.Android installer to include `LineEditor.pdb` into the
installer packages.
jonpryor added a commit that referenced this issue Oct 20, 2020
Context: https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1230070

Changes: mono/LineEditor@5a7e3e2...3fa0c2e

  * mono/LineEditor@3fa0c2e: Fix NuGet publishing errors (#9)
  * mono/LineEditor@06a4ddf: Bump `$(PackageVersion)` to 5.4.1.
  * mono/LineEditor@bce1b7f: Enable .pdb files for Release config & add AzDO build script (#8)
  * mono/LineEditor@4831e1a: Merge pull request #6 from terrajobst/code-of-conduct
  * mono/LineEditor@5b4a4aa: Link Code of Conduct
  * mono/LineEditor@410ca3d: Merge pull request #2 from VEIT-Electronics/master
  * mono/LineEditor@3d802e7: Merge pull request #1 from VEIT-Electronics/bugfix/ENG-232-line-editor-completions
  * mono/LineEditor@0d43552: fix: text overriding was only platform specific (check platform)

The most important piece is mono/LineEditor@bce1b7f, which will allow
us to redistribute `LineEditor.pdb` in the Xamarin.Android installers.

Add a post-`Build` target to `logcat-parse/Directory.Build.targets`
which copies `LineEditor.pdb` into `$(OutputPath)`.  This will allow
the Xamarin.Android installer to include `LineEditor.pdb` into the
installer packages.
pjcollins pushed a commit to pjcollins/java.interop that referenced this issue Dec 17, 2020
Context: https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1230070

Changes: mono/LineEditor@5a7e3e2...3fa0c2e

  * mono/LineEditor@3fa0c2e: Fix NuGet publishing errors (dotnet#9)
  * mono/LineEditor@06a4ddf: Bump `$(PackageVersion)` to 5.4.1.
  * mono/LineEditor@bce1b7f: Enable .pdb files for Release config & add AzDO build script (dotnet#8)
  * mono/LineEditor@4831e1a: Merge pull request dotnet#6 from terrajobst/code-of-conduct
  * mono/LineEditor@5b4a4aa: Link Code of Conduct
  * mono/LineEditor@410ca3d: Merge pull request dotnet#2 from VEIT-Electronics/master
  * mono/LineEditor@3d802e7: Merge pull request dotnet#1 from VEIT-Electronics/bugfix/ENG-232-line-editor-completions
  * mono/LineEditor@0d43552: fix: text overriding was only platform specific (check platform)

The most important piece is mono/LineEditor@bce1b7f, which will allow
us to redistribute `LineEditor.pdb` in the Xamarin.Android installers.

Add a post-`Build` target to `logcat-parse/Directory.Build.targets`
which copies `LineEditor.pdb` into `$(OutputPath)`.  This will allow
the Xamarin.Android installer to include `LineEditor.pdb` into the
installer packages.
@github-actions github-actions bot locked and limited conversation to collaborators Apr 15, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant