google / bundletool

Bundletool is a command-line tool to manipulate Android App Bundles
https://g.co/androidappbundle
Apache License 2.0
3.54k stars 386 forks source link

Split custom assets by device ABI? #190

Open jonathanpeppers opened 3 years ago

jonathanpeppers commented 3 years ago

Related to: https://github.com/google/bundletool/issues/116

I was reviewing the code and I don't see a way to have custom files split up per ABI:

https://github.com/google/bundletool/blob/ae0fc0162fd80d92ef8f4ef4527c066f0106942f/src/main/java/com/android/tools/build/bundletool/model/targeting/TargetedDirectorySegment.java#L52-L55

But you can do it for language or other "dimensions".

I work on .NET (for Android), and we have .NET assembly files such as:

assemblies/MultipleArch.dll
assemblies/armeabi-v7a/SingleArch.dll
assemblies/arm64-v8a/SingleArch.dll

I was looking for a way to split up these custom files per architecture. Is there a way to do this? Thanks!

ymakhno commented 3 years ago

Unfortunately splitting assets by device ABI is not supported now and we don't have short term plans to support this.

jonathanpeppers commented 3 years ago

Thanks @ymakhno,

If I were to implement this feature, adding support for a path similar to assemblies/#abi_armeabi-v7a/SingleArch.dll.

Assuming I sent a PR and it made it in, would there need to be changes to Google Play's backend as well? Or would it work even if we had our own fork of bundletool?

plecesne commented 3 years ago

Any reason you can't put the .dll files under lib/?

jonathanpeppers commented 3 years ago

@plecesne thanks, I'll give the lib folder a try and see if it works.

jonathanpeppers commented 3 years ago

The lib folder seems like it has some expectations for .so files:

[BT : 1.2.0] error : Native library files need to have paths in form 'lib/<single-directory>/<file>.so' but found 'lib/HelloWorld.dll'.

In this case, we would want HelloWorld.dll in the base .apk. There would be only some assemblies that are armeabi-v7a or x86-specific.

ymakhno commented 3 years ago

Could you please provide a bit more information about these assemblies to be able to identify a better solution for the problem? Why are some assemblies architecture specific and some not? Do architecture specific assemblies contain native code inside, are they effectively native libraries?

jonathanpeppers commented 3 years ago

These are .NET assemblies that contain IL that drives languages like C# or F#. It isn't native code. Our Android support was originally a product called Xamarin that we are working on moving to be a general feature of .NET.

A developer's C# code in their app would generally work on any architecture, but some libraries are highly optimized per architecture. An example would be parts of the Base Class Libraries such as System.Private.CoreLib.dll.

ymakhno commented 3 years ago

Thank you for the explanation! Two more questions:

jonathanpeppers commented 3 years ago
ymakhno commented 3 years ago

Thanks! Probably instead of me spamming you with questions it would be easier for me to just play with the technology to understand which assemblies are architecture-specific and which are not and how changes in code affect size of both. Could you please share a link to a good manual I can use?

jonathanpeppers commented 3 years ago

We are still developing this, but we have working samples with preview builds here:

https://github.com/xamarin/net6-samples

To build an app bundle, you can build the Android project:

dotnet build HelloAndroid -p:Configuration=Release -p:AndroidPackageFormat=aab

And you should be able to find the build output in bin\Release\.

If you want to play with Xamarin, in general, you might be better off trying the guides for the stable product here. But we don't have these architecture-specific assemblies today.

ymakhno commented 3 years ago

I've played with Xamarin a bit and understand your usecase better now.

Currently you put CLI assemblies under root folder inside aab. This folder by design contains files that should go to the main split and that's why files there are not splittable. But we can support platform targeting inside assets (like we already have for languages as an example) so in your case you will be able to put assemblies like presented below:

/
|--assets
|   |--assemblies
|   |   |-- SQLLite-net.dll
|   |   |
|   |   |-- platform#abi_armeabi-v7a
|   |   |    |-- System.Core.dll
|   |   |
|   |   |-- platform#abi_arm64-v8a
|   |   |    |-- System.Core.dll

Does it work for you? Will you be able to move assemblies to assets instead of root?

jonathanpeppers commented 3 years ago

@ymakhno yes, we can move them to assets. It actually might make more sense than picking our own directory name in the root.

Do you think platform#abi_armeabi-v7a would work today, or would this need to be added? Thanks!

ymakhno commented 3 years ago

It won't work today, I'll try to land it into next bundletool release. Will update this ticket once done.

ymakhno commented 3 years ago

Unfortunately I found out that solution that I wrote above won't be as easy to implement as I thought initially. I'll keep the issue open to keep it on our radar, but a short term workaround I can propose at the moment is only one described in #116.

jonathanpeppers commented 3 years ago

Thanks. Are you suggesting to put the files under lib? https://github.com/google/bundletool/issues/116#issuecomment-525328049

Would we have to rename their extension to .so? I was hitting this error when I tried: https://github.com/google/bundletool/issues/190#issuecomment-728357280

ymakhno commented 3 years ago

I think if you rename to .so it will solve the problem, if you don't want Android Platform to treat this file as a library I think you can skip lib prefix and have something like assembly-core.dll.so.