-
Notifications
You must be signed in to change notification settings - Fork 53
Understanding the Binding Pipeline
In order to troubleshoot issues with binding a specific library, it can be helpful to understand the bindings pipeline, and how to verify results at each step in order to narrow down the cause of an issue.
There are 4 main stages in the bindings pipeline:
-
Extracting the Java API from a
.jar
/.aar
("class-parse"
) - Resolving the Java types in the API (
"ApiXmlAdjuster"
) - Applying metadata (
"Fixups"
) - Generating C# code (
"generator"
)
This step decompiles compiled Java, extracts the Java API, and writes it to an XML file. Additionally, if the Java library is actually a Kotlin library, it will read the additional annotations that Kotlin places in the API, and updates the Java API to be closer to the Kotlin API. (Kotlin supports more features than Java (like internal
classes), which are encoding in the Kotlin annotations.)
If the input binary is an .aar
, this file is unzipped and the classes.jar
file inside is used as the input.
The output of this step is an XML file in the /obj/$(Configuration)/$(TargetFramework)
directory called api.xml.class-parse
. There is a lot of noise in this file needed by future steps, but if you ignore the noise you can see it is a description of the Java API:
<api
api-source="class-parse">
<package
name="com.example">
<interface
deprecated="not deprecated"
name="MyInterface"
visibility="public">
<method
abstract="true"
deprecated="not deprecated"
final="false"
name="doStuff"
return="void"
static="false"
visibility="public">
<parameter
name="p0"
type="java.lang.String" />
</method>
</interface>
</package>
</api>
There isn't much interesting output in a diagnostic MSBuild log from this step. However if you are binding a Kotlin library you will see messages describing the changes made due to the Kotlin annotations:
Kotlin: Hiding internal class Com.Example.MyInternalClass
Kotlin: Renaming parameter Com.Example.MyClass - GetByName - p0 -> name
The next step takes the api.xml.class-parse
created in the previous step, attempts to resolve all Java types mentioned in the API, removes types that rely on other types it cannot resolve, and outputs the result as another XML file called api.xml
.
For example, imagine the following method was found in the previous step:
<method
abstract="true"
deprecated="not deprecated"
final="false"
name="getActivityByName"
return="android.app.Activity"
static="false"
visibility="public">
<parameter
name="p0"
type="java.lang.String" />
</method>
We need to ensure that we can find the definition for all Java types this method requires:
- Parameter with type
java.lang.String
- Return type
android.app.Activity