| Summary: | latest android sdk and sdl doesn't work (gradle is needed) | ||
|---|---|---|---|
| Product: | SDL | Reporter: | Martin Gerhardy <martin.gerhardy> |
| Component: | build | Assignee: | Sam Lantinga <slouken> |
| Status: | RESOLVED FIXED | QA Contact: | Sam Lantinga <slouken> |
| Severity: | normal | ||
| Priority: | P2 | CC: | deveee, icculus, sfalexrog, sylvain.becker, tower120 |
| Version: | HG 2.0 | ||
| Hardware: | All | ||
| OS: | Android (All) | ||
| Attachments: |
build.gradle template
build.gradle template patch Remove redundant lines from AndroidMatifest.xml |
||
|
Description
Martin Gerhardy
2015-12-03 17:43:44 UTC
Hello, Just writing that I am building with gradle (without eclipse, nor android studio) under linux. At first it seems a little bit painful to set-up, but afterwards, it seems faster and more reliable. Let me know if you want me to share some information. Yes, I think the right approach is to remove ant support and only support gradle. Sylvain, can you provide information on how to do that? Thanks! Created attachment 2567 [details] build.gradle template Here's some explanation: - Android NDK is still needed (preferably with env variable: $ANDROID_NDK_HOME) - attached file "build.gradle" is needed. - "gradle" from: http://services.gradle.org/distributions/ is needed Download the "bin" archive, version 2.14.1 You may need to regenerate it, doing: ~/Downloads/gradle/gradle-2.14.1/bin/gradle wrapper Copy the files into your application directory to have the following structure: AndroidManifest.xml ... gradle/ gradle/wrapper gradle/wrapper/gradle-wrapper.jar gradle/wrapper/gradle-wrapper.properties gradlew build.gradle (maybe also "gradlew.cmd" for windows). (and "proguard.pro" if needed ..) - Those files are not needed anymore: ant.properties build.xml build.properties? Usage: build with: ./gradlew assembleRelease build, sign, install on device with: ./gradlew appStart User needs to customize "build.gradle": - change its "applicationId" - set all the versions correctly to fit its android build system ("buildToolsVersion", "dependencies", SDK). - fill the signing configuration A couple of things to consider:
First, as of Android gradle plugin v.2.3.3, NDK builds are supported natively, so there's no need to execute ndk-build by hand. Instead, you would have something like this in your build.gradle file:
/*...*/
android {
externalNativeBuild {
ndk-build {
/*specify targets, cflags, abiFilters, etc*/
}
/* other stuff */
}
This also has an added benefit of integrating nicely with Android Studio, allowing to use its C/C++ editor and debugger.
Second, cmake seems to be the preferred way to add native code to an Android project right now. Official Google tutorials show how to use cmake, and creating a new project with C++ support will create a cmake-based project. Gradle seems to not run its ndk-build jobs in parallel, resulting in really long build times, while cmake projects are using all CPU cores during build.
Messed up my example... Should have been something like that:
/*...*/
android {
externalNativeBuild {
ndk-build {
/* Specify path to your Android.mk file */
path "path/to/android.mk"
}
defaultConfig {
externalNativeBuild {
ndk-build {
/* Arguments for ndk-build */
arguments "NDK_APPLICATION_MK:=Application.mk"
/* You can specify your cFlags, cppFlags, abiFilters and targets here as well */
}
}
/* Other defaultConfig paramters go here */
}
/* You can specify additional ndk-build parameters per build type */
buildTypes {
release {
externalNativeBuild {
ndk-build {
cFlags "-DRELEASE_BUILD"
}
}
}
}
/* other stuff */
}
Syntax for CMake doesn't differ at all, you just replace "ndk-build" with "cmake".
The options for cmake and ndk-build are described at:
https://google.github.io/android-gradle-dsl/current/com.android.build.gradle.internal.dsl.ExternalNativeCmakeOptions.html
https://google.github.io/android-gradle-dsl/current/com.android.build.gradle.internal.dsl.ExternalNativeNdkBuildOptions.html
(Note that top-level externalNativeBuild differs from per-configuration externalNativeBuild, and you can only put path there:
https://google.github.io/android-gradle-dsl/current/com.android.build.gradle.internal.dsl.NdkBuildOptions.html
https://google.github.io/android-gradle-dsl/current/com.android.build.gradle.internal.dsl.CmakeOptions.html
)
Created attachment 2893 [details]
build.gradle template
Thanks for the news, the android gradle plugin has improved in the meantimes!
I just tried it and here's my build.grade file updated.
Some remarks:
- it's not "ndk-build" but "ndkBuild"
- you can have parallel builds with: arguments "-j10"
- I was forced to set the abiFilters to what I wanted. It wouldn't use the one from Android.mk. (though, all other variables from Android.mk are used!)
I haven't tried CMake with Android. I don't really see the point of it. You still need a cross-compiler, so eventually the Android NDK.
(In reply to Sylvain from comment #6) > Created attachment 2893 [details] > build.gradle template > > Thanks for the news, the android gradle plugin has improved in the > meantimes! > I just tried it and here's my build.grade file updated. > > Some remarks: > - it's not "ndk-build" but "ndkBuild" > - you can have parallel builds with: arguments "-j10" > - I was forced to set the abiFilters to what I wanted. It wouldn't use the > one from Android.mk. (though, all other variables from Android.mk are used!) > > I haven't tried CMake with Android. I don't really see the point of it. You > still need a cross-compiler, so eventually the Android NDK. Thanks for mentioning those points! I should've double-checked the ndkBuild stuff. Yeah, you have to use abiFilters to specify your targets now, but I guess that makes adding platform-specific condidionals to build scripts simplier? If I understand correctly, now ndk-build or cmake will be running for each abi separately. Well, one of the reasons SDL might want to use CMake to build for Android is that SDL would no longer need Android-specific .mk files, so that's one less build system to worry about :-) Seriously, though, CMake is much more flexible than Android's custom makefiles. And in my opinion it's more transparent (and maybe even easier to understand) than those .mk files - at the very least, CMake is better-documented than the old Android build system, and there's always a CMakeCache that I can look through to get a sense of what's happening. Sure, you'll need NDK eventually, but CMake for Android does not create makefiles, it targets (and runs) ninja build system. So only the toolchain+sysroot part of the NDK gets used. As an added bonus, you can create apps that are easily buildable (without external scripts, with a single set of build scripts) for multiple platforms. Here's an example I've made: https://github.com/sfalexrog/Imgui_Android There are, unfortunately, some caveats when using CMake for Android. You want to use Google's version of CMake that can be downloaded with sdk tools, because it has some "gradle integration" that a usual CMake doesn't have. That might not sound so bad, but the binary they provide links to a particular version of OpenSSL that's not in Fedora repositories, so I had to build one myself. It also expects to find OpenSSL library in /usr/lib, so I couldn't just place the file near the executable, and had to put it among other system libraries. It's like Google means "for Ubuntu" when labeling their tools as "for Linux". Created attachment 2903 [details]
patch
This is a patch to build with gradle using the script androidbuild.sh
It drops "ant" build stuff.
you need to have env ANDROID_HOME set to you SDK location and gradle in path.
I have updated the sdk version to 16 because SDLActivity code needs it, but according to the documentation we should updated it to latest.
Though the minSdkVersion remains 10.
I've been asked about this a lot recently; Sam, should we cram this into 2.0.6, or is it too risky? --ryan. BTW, I haven't tested androidbuild.sh on window nor macosx. only on linux. It's too risky for 2.0.6, but I'm getting it in right after we release. Also a patch there : bug 3510 *** Bug 3510 has been marked as a duplicate of this bug. *** I've checked in a first pass of SDL gradle build system here: https://hg.libsdl.org/SDL/rev/5816b27073a4 Comments and patches welcome! (In reply to Sam Lantinga from comment #14) I believe you don't have to check in *.iml files - they are generated by the IDE and will be overwritten anyway. AndroidMatifest.xml might be simplified as well, if I'm not mistaken. The uses-sdk property is overriden by gradle anyway (and isn't minSdkVersion 14 or 16 nowadays?) I'm not sold on disabling automatic ndk-build in build.gradle - wasn't having a "single-click build" from Android Studio one of the points for this change? And I'm not sure if C/C++ syntax highlighting, autocompletion, and native debugging are going to work with this setup. Then again, I'm not sure what's the proper process of using SDL2 in an Android app is, so far I've been simply building it alongside the app (possibly rebuilding the whole library), so maybe I've been doing it wrong all along. Still, really happy to see that! Will try to send something more meaningful (i.e. patches :-) ) soon! Here you go! https://hg.libsdl.org/SDL/rev/fe6769530709 Updated Android build tools version, which bumped minimum deployment target to API 14 Also added native code to the Android gradle project, which allows using gradle or Android Studio to build the entire SDL application without a separate ndk-build step. This is really quite elegant. :) Thanks! sfalexrog, I don't really speak CMake, but the benefits of tracking Google's recommneded development path and parallel make seem worth it, so feel free to enter a separate bug to track adding Android CMake support. Thanks! Created attachment 3037 [details]
Remove redundant lines from AndroidMatifest.xml
These fields are redundant now that SDL uses Gradle for Android builds - they are set from build.gradle
I was about to write the same patch. Indeed, we don't need to write Sdk version in AndroidManifest.xml, it's overwritten into a temporary file: "build/intermediates/manifests/full/release/AndroidManifest.xml" (Maybe also APP_PLATFORM can be remove from Android.mk, since it's on the command line) NDK-r15 has bumped the min sdk version to 14, but SDL2 still works fine with min sdk 10. I personally still see downloads (~100 per day) for user with android 2.3 - 2.3.7. (less with android 3.x), and I will keep my minSdkVersion to 10. But I understand that for new user that just setup android studio, use latest ndk and SDL2. They can face this issue and be disappointed. I don't mean the patch below to be applied, but if you keep the minSdkVersion to API 14, please don't remove the java code that run belows API_14. Thanks Also, some reading, they suggest to use the max compileSdkVersion: minSdkVersion (lowest possible) <= targetSdkVersion == compileSdkVersion (latest SDK) https://medium.com/google-developers/picking-your-compilesdkversion-minsdkversion-targetsdkversion-a098a0341ebd https://stackoverflow.com/questions/26694108/what-is-the-difference-between-compilesdkversion-and-targetsdkversion diff -r 4130b92b6be4 android-project/app/build.gradle --- a/android-project/app/build.gradle Tue Oct 24 00:17:07 2017 -0700 +++ b/android-project/app/build.gradle Tue Oct 24 11:20:06 2017 +0200 @@ -1,11 +1,11 @@ apply plugin: 'com.android.application' android { - compileSdkVersion 16 + compileSdkVersion 26 buildToolsVersion "26.0.1" defaultConfig { applicationId "org.libsdl.app" - minSdkVersion 14 + minSdkVersion 10 targetSdkVersion 16 versionCode 1 versionName "1.0" diff -r 4130b92b6be4 android-project/app/jni/Application.mk --- a/android-project/app/jni/Application.mk Tue Oct 24 00:17:07 2017 -0700 +++ b/android-project/app/jni/Application.mk Tue Oct 24 11:20:06 2017 +0200 @@ -6,4 +6,4 @@ APP_ABI := all # Min SDK level -APP_PLATFORM=android-14 +APP_PLATFORM=android-10 (In reply to Sylvain from comment #19) > I don't mean the patch below to be applied, but if you keep the > minSdkVersion to API 14, please don't remove the java code that run belows > API_14. I thought the Java code required API 14 since 2.0.5 or 2.0.6? Though maybe your game doesn't take the "dangerous" code paths with the missing APIs. > Also, some reading, they suggest to use the max compileSdkVersion: > > minSdkVersion (lowest possible) <= targetSdkVersion == compileSdkVersion > (latest SDK) Be aware, though, that if you're using a high enough targetSdkVersion, you might run into stuff like missing runtime permissions (for filesystem access, for example). It's fine if you're shipping your assets with your game (you can simply extract those to an app-local folder, which is always accessible, though you'll make users with tiny internal storage and SD cards sad), but if you're accessing any outside locations, you'll have to request these permissions at runtime if the device is recent enough. And I'm not sure if that's still configurable, but you should probably compile your native code with a *lower* API version, since you might end up linking against libraries that don't exist in an older device (breaking changes in bionic, like missing rand(), come to mind) (In reply to Sam Lantinga from comment #17) Also, you should probably replace all references to stlport_static with c++_static: https://twitter.com/johnregehr/status/920691341738123264 (In reply to Sam Lantinga from comment #17) Done: bug 3918 - Java code still works fine with API 10. But some function are disabled: no clipboard notification (need API 11) no motion event (need API 12) only 1 mouse button (API 14) no joysticks (API 14/16), maybe other stuff. (some flags like KeyEvent.KEYCODE_ZOOM_INdoes not exist). - indeed, at targetSdkVersion 23, you need to request permissions at runtime. but SDL only needs *normal* permissions, that are granted at installation. https://developer.android.com/guide/topics/permissions/normal-permissions.html like INTERNET / VIBRATE / ACCESS_NETWORK_STATE WRITE_EXTERNAL_STORAGE seems not to be in the list, but it says "Starting in API level 19, this permission is not required to read/write files in your application-specific directories returned by getExternalFilesDir(String) and getExternalCacheDir()." RECORD_AUDIO, which is commented out, probably needs to be granted. - to avoid API breaking changes like rand(), atof(), and so on. Yes, there is a nasty issue there. one needs to make sure set minSdkVersion to the same as APP_PLATEFORM. |