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

Generate ELF shared libraries and allow multi-abi libs in APKs and App bundles #33696

Merged
merged 26 commits into from Jun 9, 2019

Conversation

blasten
Copy link

@blasten blasten commented Jun 1, 2019

Description

Include ELF shared library instead of AOT snapshots in APKs and make the flag target-platform multi-option for build apk and build appbundle.

After this change, an APK built for release or profile will have the following structure:

    2460  Defl:N      889  64% 1980-00-00 00:00 f40cf37a  AndroidManifest.xml
     765  Defl:N      595  22% 1980-00-00 00:00 dce0efa9  META-INF/CERT.RSA
    1522  Defl:N      722  53% 1980-00-00 00:00 39881335  META-INF/CERT.SF
    1479  Defl:N      695  53% 1980-00-00 00:00 ce61d107  META-INF/MANIFEST.MF
     109  Defl:N       53  51% 1980-00-00 00:00 e83e6b87  assets/flutter_assets/AssetManifest.json
     208  Defl:N      113  46% 1980-00-00 00:00 92d58e5f  assets/flutter_assets/FontManifest.json
  644419  Defl:N    58421  91% 1980-00-00 00:00 548a9a0b  assets/flutter_assets/LICENSE
  134640  Defl:N    63011  53% 1980-00-00 00:00 c7c94b78  assets/flutter_assets/fonts/MaterialIcons-Regular.ttf
   97680  Defl:N    54923  44% 1980-00-00 00:00 273d62de  assets/flutter_assets/packages/cupertino_icons/assets/CupertinoIcons.ttf
- 1821616  Defl:N   773152  58% 1980-00-00 00:00 10467cf1  assets/isolate_snapshot_data
- 3060736  Defl:N   832709  73% 1980-00-00 00:00 0406652a  assets/isolate_snapshot_instr
-   23592  Defl:N    11409  52% 1980-00-00 00:00 0fa678e0  assets/vm_snapshot_data
-   12704  Defl:N     2807  78% 1980-00-00 00:00 b5e3f0f0  assets/vm_snapshot_instr
  258100  Defl:N   107181  59% 1980-00-00 00:00 5bc8eac3  classes.dex
+ 5632000  Defl:N  1850034  67% 1980-00-00 00:00 6415dcf7  lib/armeabi-v7a/libapp.so
 6032316  Defl:N  3293989  45% 1980-00-00 00:00 c82f4361  lib/armeabi-v7a/libflutter.so
     344  Defl:N      186  46% 1980-00-00 00:00 55202761  res/drawable/launch_background.xml
     507  Stored      507   0% 1980-00-00 00:00 dab4e8f1  res/mipmap-hdpi-v4/ic_launcher.png
     405  Stored      405   0% 1980-00-00 00:00 ad6e0a73  res/mipmap-mdpi-v4/ic_launcher.png
     684  Stored      684   0% 1980-00-00 00:00 77d229a5  res/mipmap-xhdpi-v4/ic_launcher.png
     994  Stored      994   0% 1980-00-00 00:00 547189ae  res/mipmap-xxhdpi-v4/ic_launcher.png
    1406  Stored     1406   0% 1980-00-00 00:00 63bc7c87  res/mipmap-xxxhdpi-v4/ic_launcher.png

Fat APK

$ flutter build apk

# Effectively the same as
$ flutter build apk --target-platform android-arm,android-arm64

# Also possible in the near future
$ flutter build apk --target-platform android-arm,android-arm64,android_x64

The tool displays a message:

You are building a fat APK that includes binaries for android-arm, android-arm64.
If you are deploying the app to the Play Store, it's recommended to use app bundles or split the APK to reduce the APK size.
    To generate an app bundle, run:
        flutter build appbundle --target-platform android-arm,android-arm64
        Learn more on: https://developer.android.com/guide/app-bundle
    To split the APKs per ABI, run:
        flutter build apk --target-platform android-arm,android-arm64 --split-per-abi
        Learn more on:  https://developer.android.com/studio/build/configure-apk-splits#configure-abi-split

Resulting APK:

    2512  Defl:N      901  64% 00-00-1980 00:00 c7f247d8  AndroidManifest.xml
     765  Defl:N      597  22% 00-00-1980 00:00 b105c0a9  META-INF/CERT.RSA
    1678  Defl:N      777  54% 00-00-1980 00:00 45833d1e  META-INF/CERT.SF
    1635  Defl:N      747  54% 00-00-1980 00:00 a3af0ca9  META-INF/MANIFEST.MF
     109  Defl:N       53  51% 00-00-1980 00:00 e83e6b87  assets/flutter_assets/AssetManifest.json
     208  Defl:N      113  46% 00-00-1980 00:00 92d58e5f  assets/flutter_assets/FontManifest.json
  644419  Defl:N    58421  91% 00-00-1980 00:00 548a9a0b  assets/flutter_assets/LICENSE
  134640  Defl:N    63011  53% 00-00-1980 00:00 c7c94b78  assets/flutter_assets/fonts/MaterialIcons-Regular.ttf
   97680  Defl:N    54923  44% 00-00-1980 00:00 273d62de  assets/flutter_assets/packages/cupertino_icons/assets/CupertinoIcons.ttf
  257176  Defl:N   107353  58% 00-00-1980 00:00 8e495fa1  classes.dex
 6311936  Defl:N  1801944  72% 00-00-1980 00:00 ed1058f5  lib/arm64-v8a/libapp.so
 8473344  Defl:N  3657267  57% 00-00-1980 00:00 540aacd2  lib/arm64-v8a/libflutter.so
 5632000  Defl:N  1850033  67% 00-00-1980 00:00 8abc54a5  lib/armeabi-v7a/libapp.so
 6032316  Defl:N  3293989  45% 00-00-1980 00:00 c82f4361  lib/armeabi-v7a/libflutter.so
     344  Defl:N      186  46% 00-00-1980 00:00 55202761  res/drawable/launch_background.xml
     507  Stored      507   0% 00-00-1980 00:00 dab4e8f1  res/mipmap-hdpi-v4/ic_launcher.png
     405  Stored      405   0% 00-00-1980 00:00 ad6e0a73  res/mipmap-mdpi-v4/ic_launcher.png
     684  Stored      684   0% 00-00-1980 00:00 77d229a5  res/mipmap-xhdpi-v4/ic_launcher.png
     994  Stored      994   0% 00-00-1980 00:00 547189ae  res/mipmap-xxhdpi-v4/ic_launcher.png
    1406  Stored     1406   0% 00-00-1980 00:00 63bc7c87  res/mipmap-xxxhdpi-v4/ic_launcher.png
    1560  Stored     1560   0% 00-00-1980 00:00 71db73fd  resources.arsc

ABI split per APK

$ flutter build apk --split-per-abi

This will generate two APKs with the appropriate version for the the Play Store:

  • Built build/app/outputs/apk/release/app-armeabi-v7a-release.apk.
  • Built build/app/outputs/apk/release/app-arm64-v8a-release.apk.

Related Issues

#18494
#31922

Tests

  • Unit tests to the AOT snapshotter.
  • Unpack the APK and app bundle and assert that the expected libraries are contained.

Checklist

Before you create this PR confirm that it meets all requirements listed below by checking the relevant checkboxes ([x]). This will ensure a smooth and quick review process.

  • I read the Contributor Guide and followed the process outlined there for submitting PRs.
  • I signed the CLA.
  • I read and followed the Flutter Style Guide, including Features we expect every widget to implement.
  • I updated/added relevant documentation (doc comments with ///).
  • All existing and new tests are passing.
  • The analyzer (flutter analyze --flutter-repo) does not report any problems on my PR.
  • I am willing to follow-up on review comments in a timely manner.

Breaking Change

Does your PR require Flutter developers to manually update their apps to accommodate your change?

  • Yes, this is a breaking change (Please read Handling breaking changes). Replace this with a link to the e-mail where you asked for input on this proposed change.
  • No, this is not a breaking change.

@blasten blasten added platform-android Android applications specifically t: gradle "flutter build" and "flutter run" on Android labels Jun 1, 2019
@Piinks Piinks added the tool Affects the "flutter" command-line tool. See also t: labels. label Jun 3, 2019
@goderbauer
Copy link
Member

Wondering what this change does to APK size. From the diff in the description it looks like it adds ~220KiB compressed?

@jason-simmons
Copy link
Member

I tried building a default template app with flutter build apk --release and flutter build apk --release --build-shared-library

The regular APK was 5.23MB and the build-shared-library APK was 5.46MB.

The uncompressed app.so library was 5.96MB. Versus 4.97MB for the total of isolate_snapshot_data, isolate_snapshot_instr, vm_snapshot_data, and vm_snapshot_instr in the regular APK.

Note that we had to disable the debug symbol stripping that Android usually does to .so libraries packaged into an APK. See dart-lang/sdk#37146

@rmacnak-google

@goderbauer
Copy link
Member

Is the size increase likely due to the debug symbols?

@blasten
Copy link
Author

blasten commented Jun 4, 2019

FYI: the config to avoid stripping debug symbols does not work in Flutter modules. It seems that the root cause is that the Gradle plugin is inserted as an implementation dependency:

dependencies {
    implementation project(':flutter')
}

In which, any config set in the android { } block by the plugin is completely ignored. The app's .android/app/build.gradle needs to set doNotStrip.

We may need to land a fix for dart-lang/sdk#37146 before this one goes in.

cc @rmacnak-google @jason-simmons @tvolkert

@blasten
Copy link
Author

blasten commented Jun 4, 2019

The CI seems to be running into: https://github.com/dart-lang/sdk/blob/a6bbc58d09569ed84f437d6ff55c01166745b3d4/runtime/vm/dart_api_impl.cc#L6075. The target is still arm, but the command is run from Windows. Is that expected?

@blasten blasten force-pushed the elf branch 2 times, most recently from 6af89f8 to 0dcfa51 Compare June 5, 2019 00:15
@blasten
Copy link
Author

blasten commented Jun 5, 2019

Pending AIs:

  • The issue about Android stripping symbols was fixed in dart-lang/sdk@da0de06 (Confirmation pending, AI: remove doNotStrip "*/${abi}/libapp.so" from Gradle).
  • The failure on Windows will be fixed by https://github.com/flutter/engine/pull/9190/files
  • Add integration test that installs an APK in release mode from build apk for app and add to app.
  • Add integration test that installs an APK in release mode from build appbundle. Requires to update the image in devicelab to include bundletool for app and add to app.

@blasten blasten changed the title Generate ELF shared libraries instead of AOT snapshots Generate ELF shared libraries instead of AOT snapshots and allow multi-abi libs in APKs and App bundles Jun 5, 2019
@blasten blasten changed the title Generate ELF shared libraries instead of AOT snapshots and allow multi-abi libs in APKs and App bundles Generate ELF shared libraries and allow multi-abi libs in APKs and App bundles Jun 5, 2019
@tvolkert
Copy link
Contributor

tvolkert commented Jun 5, 2019

The CI seems to be running into: https://github.com/dart-lang/sdk/blob/a6bbc58d09569ed84f437d6ff55c01166745b3d4/runtime/vm/dart_api_impl.cc#L6075. The target is still arm, but the command is run from Windows. Is that expected?

@rmacnak-google

@blasten
Copy link
Author

blasten commented Jun 5, 2019

@tvolkert I think https://github.com/flutter/engine/pull/9190/files will fix it.

@jason-simmons
Copy link
Member

Copy link
Contributor

@tvolkert tvolkert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Other than a few nits, LGTM

@blasten
Copy link
Author

blasten commented Jun 7, 2019

@tvolkert

How do we know it's a profile or release build at this point?

There's a check before that. I have updated both error messages, so it's more clear.

Copy link
Member

@jonahwilliams jonahwilliams left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link
Contributor

@tvolkert tvolkert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@@ -111,21 +144,53 @@ class FlutterPlugin implements Plugin<Project> {
return result
}

/**
* Returns the platform that is used to extract the `libflutter.so` and the .class files.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this really used to used to extract libflutter.so? It looks like it's only used to extract the .class files.

If I'm mis-reading it (and it is used to extract libflutter.so), is it not a problem that it's returning PLATFORM_ARM64 if that's merely one of the target platforms?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It extracts libflutter.so as well, then it adds the libflutter.so for the rest of the ABIs.
Alternatively, we could extract the .class only before the afterEvaluate block (otherwise Gradle complains that we are referencing classes that aren't defined).

I filed an issue to track this in #33059 and #33064

The current engine artifacts for Android are:

android-arm/
android-arm-profile/
android-arm-release/
android-arm64/
android-arm64-profile/
android-arm64-release/
android-x64/
android-x86/

x64 and x86 are for debug only, and their corresponding libflutter.so is always added even for arm and arm64.

packages/flutter_tools/gradle/flutter.gradle Outdated Show resolved Hide resolved
@blasten blasten merged commit 966b15b into flutter:master Jun 9, 2019
@blasten blasten deleted the elf branch June 9, 2019 01:02
@jonahwilliams
Copy link
Member

This change has doubled the measured size in the basic_material_app_android__compile benchmark.

@blasten
Copy link
Author

blasten commented Jun 9, 2019

@jonahwilliams that's intended. Looks like the goal/baseline is defined in a db?

kiku-jw pushed a commit to kiku-jw/flutter that referenced this pull request Jun 14, 2019
…p bundles (flutter#33696)

* Gradle generates ELF shared libraries instead of AOT snapshots.
* `flutter build apk/appbundle` supports multiple `--target-platform` and defaults to `android-arm` and `android-arm64`.
*  `flutter build apk` now has a flag called `--split-per-abi`.
kiku-jw pushed a commit to kiku-jw/flutter that referenced this pull request Jun 14, 2019
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Aug 6, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
platform-android Android applications specifically t: gradle "flutter build" and "flutter run" on Android tool Affects the "flutter" command-line tool. See also t: labels.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants