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
depends: Add Android NDK support #16110
Conversation
Very cool, concept ACK |
Concept ACK |
@greenaddress You might be interested in taking a look at this? |
Would be awesome if someone who is building bitcoin core for Android would review and test this. This change is pretty minimal. I'd love to have a |
Google now mandates that all ndk based application ship all 4 binaries armv7a/aarch64/x86/amd64 - should be tested on all (and ideally added to the CI to prevent breakage). Specifically you may have some issue on 32 bit without some extra flags. See https://GitHub.com/GreenAddress/bitcoin_ndk for what's currently required to build core with NDK Haven't reviewed the PR patches yet, will have a look later |
I had a quick test of this. Installed the Mac ndk from https://developer.android.com/ndk/downloads/. Couldn't get Boost 1.70.0 to build correctly, but reverting to 1.64.0 seemed to work. NO_QT=1 NO_WALLET=1 ANDROID_API_LEVEL=29 ANDROID_TOOLCHAIN_BIN=/Users/michael/Library/Android/macOS-ndk-bundle/toolchains/llvm/prebuilt/darwin-x86_64/bin make HOST=aarch64-linux-android |
4d27cd2
to
11e2173
Compare
Thanks @fanquake, after adding the @greenaddress I believe Google only mandates 64-bit in addition to 32-bit. Pure 64-bit native packages are fine. Going forward I don't personally see much demand for 32-bit since Android is moving to 64-bit so those devices are going to be increasingly rare and most likely underpowered. |
This seems to configure a build that has QT disabled, am I correct ? Also doesnt this :- #13696 resolve the QT issue? |
@BlockMechanic, this is built without Qt. You probably don't want it anyway as the Qt Widgets approach Bitcoin-Qt uses is not really optimised for Android. Qt Quick OTOH would be grand as an official mobile UI but that's a topic for another PR. |
@icota thanks for the response. I'll still try to build it with QT as is though if a project to make it mobile friendly is started, i'd be happy to help |
Finally got down to it last night , only to see that the example also stipulates NO_WALLET=1 ... why is this ? |
@BlockMechanic, there is no particular reason. It's just an example. I haven't tested it myself, but I guess you can build with wallet if you wish so. |
11e2173
to
f2d33de
Compare
Rebased on top of master and added config options and a patch file enabling Android build of Qt. Thanks @BlockMechanic! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried to build f2d33de on macOS 10.14:
$ make HOST=aarch64-linux-android ANDROID_API_LEVEL=28 ANDROID_TOOLCHAIN_BIN=/Users/sjors/dev/android-ndk-r20/toolchains/llvm/prebuilt/darwin-x86_64/bin
...
Building zlib...
/Users/sjors/dev/android-ndk-r20/toolchains/llvm/prebuilt/darwin-x86_64/bin/aarch64-linux-android-ar -o libz.a adler32.o crc32.o deflate.o infback.o inffast.o inflate.o inftrees.o trees.o zutil.o compress.o uncompr.o gzclose.o gzlib.o gzread.o gzwrite.o
/Users/sjors/dev/android-ndk-r20/toolchains/llvm/prebuilt/darwin-x86_64/bin/aarch64-linux-android-ar: no operation specified
make[1]: *** [libz.a] Error 1
make: *** [/Users/sjors/dev/bitcoin/depends/work/build/aarch64-linux-android/zlib/1.2.11-d7483e8fc2d/./.stamp_built] Error 2
Building depends with NO_QT=1 does work.
Building the project fails:
./configure --prefix=/Users/sjors/dev/bitcoin/depends/aarch64-linux-android
make
...
AR leveldb/libleveldb.a
/Users/sjors/dev/bitcoin/depends/aarch64-linux-android/share/../lib/libevent.a(evutil_rand.o): In function `evutil_secure_rng_add_bytes':
/Users/sjors/dev/bitcoin/depends/work/build/aarch64-linux-android/libevent/2.1.8-stable-254609abc4b/evutil_rand.c:198: undefined reference to `arc4random_addrandom'
clang++: error: linker command failed with exit code 1 (use -v to see invocation)
Cross-compiling from macOS is generally a pain, so I don't mind if it doesn't work (as long as that's documented).
I also tried cross-compiling on Ubuntu 18.04. This also failed for me:
make HOST=aarch64-linux-android ANDROID_API_LEVEL=28 ANDROID_TOOLCHAIN_BIN=/home/dev/android-ndk-r20/toolchains/llvm/prebuilt/linux-x86_64/bin
...
Info: creating cache file /home/dev/bitcoin/depends/work/build/aarch64-linux-android/qt/5.9.8-feb0561b74d/qtbase/.qmake.cache
ERROR: No value supplied to command line option 'android-sdk'.
funcs.mk:251: recipe for target '/home/dev/bitcoin/depends/work/build/aarch64-linux-android/qt/5.9.8-feb0561b74d/qtbase/.stamp_configured' failed
make: *** [/home/dev/bitcoin/depends/work/build/aarch64-linux-android/qt/5.9.8-feb0561b74d/qtbase/.stamp_configured] Error 3
Similarly it's happy with NO_QT=1
. I run into the same arc4random_addrandom
error when trying to build bitcoind
though.
Can you add or link to instructions on how to produce an APK? I'll try an IBD on my Xiaomi Mi A1 (which works with ABCore). Is it possible to create an APK for test/test_bitcoin
as well?
In a followup we can figure out how to run the functional test suite on the device; that's probably a lot more involved.
Thanks for testing @Sjors. The line I'm using to build (with Qt) is:
I'd be thankful if you could retry the build on both Ubuntu and Mac (mine is out of commision right now). I will make sure to update the docs with this command and your suggestions. |
I downloaded the sdk-tools from https://developer.android.com/studio#downloads, extract it to
I used I then added the
I still get the same error with zlib. Maybe I'm pointing to the wrong places? |
To get an actual APK there are additional files required such as AndroidManifest.xml and gradle files. Also the final APK in my case was built using androiddeployqt. I'll work a clean PR that highlights this and has appropriate code and notes |
I've updated the docs to make it clear where to get the SDK/NDK/Platform packages and what |
I was missing some pieces: It also looks like it installed the SDK at I ended up with this incantation:
Which results in the same zlib error. Not sure what I'm doing wrong here. I guess I don't need an APK to test, but could use the Android debugger directly? No idea how that works though. |
I upgraded to macOS Catalina in the mean time. I can build depends:
And then build QT:
@BlockMechanic I'll try with older SDK versions after I get the most recent version to work on a device. |
Unless the qt gui as currently in repo can be used on android i think this PR should limit itself to NDK support in the depends builds system without qt support. Even if the QT current GUI worked on android i would argue it wouldn't be very useful. I am aware of a QML PR but I imagine this PR needs to go first anyway and I'd like to think of this PR in the context of master. Qt build support IMHO should come when there's something usable on android as a separate PR. Also I think support for Android needs to be for all 4 currently supported targets (i686-linux-android, x86_64-linux-android, aarch64-linux-android and arm-linux-androideabi). As a note a lot of emulators images are i686. Android support should also be better than just android 29. I suggest android 19 as minimum for 32 bit and 21 as minimum for 64 bit (64 bit afaik was introduced at 21) or both android 21 should also be reasonable at this point (although declining, lose 6.9% of android market) Note that the libevent patch from bitcoin_ndk but it's actually to patch libevent code with code from a newer version of libevent - once core updates libevent it won't be necessary. |
The Qt Widgets GUI as is in master does indeed work. It's a weird look on mobile but it does work and I'd argue it might even be useful for some people: I'm working on a PR that I hope will make packaging as easy as Supporting all the architectures and old API levels I'm a bit more ambivalent about. I just checked on geizhals.eu and out of 3186 Android phones out there only 2 run x86, that's 0.06% marketshare. 32-bit ARM is probably not going to run Core all that well. Android API 19 was released 6 years ago. In my mind running Bitcoin Core is a flagship device game so that's what I focus on. But like I said patches for supporting other arch or lower API levels are welcome. I'll even concede that x86_64 is useful because of the emulators. |
@icota Supporting all abis in this PR can be done by cherry picking from the one i built atop yours. I have been using API level 24 specifically because starting from Android API level 24 (Android 7.0 Nougat) ifaddrs.h is supported officially, so the need to use custom implementations as was done for earlier versions is removed. In as far as i can tell API level 24 is the earliest version that can compile core as is without modifications to core's code. While indeed android devices vary, flagship devices from 3-4 years ago, hardware which by today's standards is considered mid-range are perfectly capable of running it. Today's flagship devices would not be bothered. A mobile device user's only issues are storage (if they do not prune) and data use, which is easily resolved by setting the app's use to wifi only. I fully support the inclusion of QT in the android depends builds. And on top of the previous points in favour of keeping the changes, i'd like to again point out that android is now by far the most dominant OS, and I strongly believe that our efforts to enable FULL support of it are on the right track. |
@icota if the gui is not pretty but otherwise 'usable' then linking qt makes sense - AFAIK 32bit requires some extra flags I think so I think makes sense to covered by this PR (and in CI and gitian ideally) @BlockMechanic as far as i know you don't need to provide ifaddrs even on lower android versions - see master of https://github.com/greenaddress/bitcoin_ndk and supports android 19 as min version for 32bit and 21 for 64 bit https://github.com/greenaddress/bitcoin_ndk/blob/3023f04ea21f7f4cd0cee456f4ccf6795cc83f15/fetchbuild.sh#L41 and doesn't provide ifaddrs (using latest ndk, r20) |
@greenaddress during my attempts to produce and test an apk, at first it would not compile properly, then the apk would not start , then it would crash immediately after sync. A lot of the time (using gdb) I kept getting traces to various aspects of threads and networking. Eventually after a lot of google searches and reading comments across github and stackoverflow, i used api 24 and I got a stable build without need to mod core. It is possible we could go lower, but i haven't tried. Another part of why i am fine with 24 is that according to the distro map on https://developer.android.com/about/dashboards , it covers ~60% of known active android devices and IMO devices running lower versions of android are also likely to be underpowered and will have difficulty running core. |
Add support for armv7a, i686 and x86_64 archs to android.mk Add -fPIC to depends file as anddroid requires it see https://stackoverflow.com/questions/30498776/position-independent-executables-and-android
3320641
to
f9af3ce
Compare
With the latest changes (thanks @BlockMechanic) you can build a prefix for any of the supported Android ABIs ( To test the CLI binaries push to a device and run. |
@dongcarl @theuni do you want to weigh in in the build changes here and maybe concept ACK? The changes required are surprisingly small and sensible, and currently let you build for android from both linux and macos, and we should be able to add a travis target too #16110 (comment) |
AWESOME |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK f9af3ce. I'm OK with merging and then improving later.
I built depends for one of the four triplets (64 bit ARM) on macOS 10.15.1 using SDK version 24 which is the minimum for now, as discussed above. We can try to support older versions in a followup PR, though generally we don't (actively) support end-of-life distros.
Tested bitcoind on a Xiaomi Mi A1 (64 bit, Android 9). First I turned on developer mode, and enabled USB debugging. I then used ABD:
adb devices
add push src/bitcoind /data/local/tmp
add push src/bitcoin-cli /data/local/tmp
add push src/test/test_bitcoin /data/local/tmp
adb shell
cd /data/local/tmp
mkdir .bitcoin
./bitcoind -datadir=.bitcoin
Initially I got a CANNOT LINK EXECUTABLE "./bitcoin-cli": library "libc++_shared.so" not found
error. I tried SDK version 29 instead, but that didn't help. Using make LDFLAGS="-static-libstdc++"
did the trick. IDB in progress... :-)
I also ran ./test_bitcoin
.
Nit: in b68f2a6 you add _config_opts_aarch64_android
which you then remove in e4c319e. You can use git interactive rebase to edit
that first commit and drop
the second.
Fun fact: if you have ABCore installed, it will try to mess with bitcoind via RPC :-) And if you unplug USB even a daemon will stop.
@@ -30,8 +30,17 @@ Common `host-platform-triplets` for cross compilation are: | |||
- `aarch64-linux-gnu` for Linux ARM 64 bit | |||
- `riscv32-linux-gnu` for Linux RISC-V 32 bit | |||
- `riscv64-linux-gnu` for Linux RISC-V 64 bit | |||
- `aarch64-linux-android` for Android ARM 64 bit |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't forget to add the new configurations you added: armv7a-linux-android, x86_64-linux-android, i686-linux-android or aarch64-linux-android
Please also mention the minimum supported version. I believe you tested down to 24?
Agree with @Sjors. Thanks for testing. |
f9af3ce Android: add all arch support (Block Mechanic) d419ca7 depends: export dynamic JNI symbols from static qtforandroid.a (Igor Cota) ed30684 Qt: patch androidjnimain.cpp to make sure JNI is initialised when statically compiled (Igor Cota) e4c319e builds: remove superfluous config_opts_aarch64_android (Igor Cota) 24ffef0 Patch libevent when building for Android (fix arc4random_addrandom) (Igor Cota) f1e40b3 Update bitcoin_qt.m4 (BlockMechanic) b4057d8 Define TARGET_OS when host is android (Igor Cota) 80b475f Fix Android zlib cross compilation issue (https://stackoverflow.com/questions/21396988/zlib-build-not-configuring-properly-with-cross-compiler-ignores-ar) (Igor Cota) 45f8219 Add full Android build example command and instructions on getting SDK/NDK (Igor Cota) b68f2a6 Add config opts and patch for aarch64_android build of Qt (Igor Cota) 9c4cb01 Add ranlib to android.mk hosts file (fix OSX Android NDK build) (Igor Cota) c2a749c Add example Android host-platform-triplet and options (Igor Cota) 0b0cff3 Add support for building Android dependencies (Igor Cota) Pull request description: This allows one to build the dependencies with the Android SDK and goes towards fixing #11844. It has been tested to work with: `make HOST=aarch64-linux-android ANDROID_API_LEVEL=28 ANDROID_TOOLCHAIN_BIN=/home/user/Android/Sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64/bin NO_QT=1 NO_WALLET=1` ACKs for top commit: Sjors: ACK f9af3ce. I'm OK with merging and then improving later. Tree-SHA512: cb805115ebe5c9e33db2bf3eab8628808fe3f50052053d8877d8b8e4406d6fea1ed9e5c4dff85d777fb99c81be6ffb9d95a0e6d32344e728e5e0da6c653e2ce7
…argets and API levels 3fe1aba depends: move README.md Android instructions to a separate section (Igor Cota) aa9b84a depends: update README.md with working Android targets and API levels (Igor Cota) Pull request description: Per @Sjors comments in bitcoin#16110 (review) ACKs for top commit: Sjors: ACK 3fe1aba Tree-SHA512: 7a2e676070d51c7a4291b0d4b638f52321c08cc6ebe2bd2c02ba62f6cc3dd8a73227df4693c6ce9201863eb0bf26e0133805347b9016cb0f9a389a49cc9492aa
f9af3ce Android: add all arch support (Block Mechanic) d419ca7 depends: export dynamic JNI symbols from static qtforandroid.a (Igor Cota) ed30684 Qt: patch androidjnimain.cpp to make sure JNI is initialised when statically compiled (Igor Cota) e4c319e builds: remove superfluous config_opts_aarch64_android (Igor Cota) 24ffef0 Patch libevent when building for Android (fix arc4random_addrandom) (Igor Cota) f1e40b3 Update bitcoin_qt.m4 (BlockMechanic) b4057d8 Define TARGET_OS when host is android (Igor Cota) 80b475f Fix Android zlib cross compilation issue (https://stackoverflow.com/questions/21396988/zlib-build-not-configuring-properly-with-cross-compiler-ignores-ar) (Igor Cota) 45f8219 Add full Android build example command and instructions on getting SDK/NDK (Igor Cota) b68f2a6 Add config opts and patch for aarch64_android build of Qt (Igor Cota) 9c4cb01 Add ranlib to android.mk hosts file (fix OSX Android NDK build) (Igor Cota) c2a749c Add example Android host-platform-triplet and options (Igor Cota) 0b0cff3 Add support for building Android dependencies (Igor Cota) Pull request description: This allows one to build the dependencies with the Android SDK and goes towards fixing bitcoin#11844. It has been tested to work with: `make HOST=aarch64-linux-android ANDROID_API_LEVEL=28 ANDROID_TOOLCHAIN_BIN=/home/user/Android/Sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64/bin NO_QT=1 NO_WALLET=1` ACKs for top commit: Sjors: ACK f9af3ce. I'm OK with merging and then improving later. Tree-SHA512: cb805115ebe5c9e33db2bf3eab8628808fe3f50052053d8877d8b8e4406d6fea1ed9e5c4dff85d777fb99c81be6ffb9d95a0e6d32344e728e5e0da6c653e2ce7
This allows one to build the dependencies with the Android SDK and goes towards fixing #11844. It has been tested to work with:
make HOST=aarch64-linux-android ANDROID_API_LEVEL=28 ANDROID_TOOLCHAIN_BIN=/home/user/Android/Sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64/bin NO_QT=1 NO_WALLET=1