[PATCH v2 0/3] MR10354: wineandroid: update Android build to work with modern toolchains
Update the Android project and build logic to work with recent Gradle and Android SDK versions, adjust types for consistency, separate APK generation from the default build, and add the required staging steps to prepare assets and libraries before building the APK. These changes allow Wine to be built with NDK r29 and modern Android build tools. The resulting build runs on Android 7 and later (only devices using the legacy gralloc interface). The build process still remains somewhat non-standard, so a build script and screenshot are provided for reference. <details> <summary>Screenshot</summary> {width=792 height=600} </details> [wineandroid-builder.tar.gz](/uploads/0b47ae812cfcd2d64f71aa9dee7042f6/wineandroid-builder.tar.gz) -- v2: wineandroid: remove APK from default build and add staging checks wineandroid: use BOOL for is_desktop flag wineandroid: update Android project for modern Gradle plugin https://gitlab.winehq.org/wine/wine/-/merge_requests/10354
From: Twaik Yont <9674930+twaik@users.noreply.github.com> The wineandroid Gradle project no longer builds with recent Android build tools. Replace jcenter() with google() and mavenCentral(), update the Android Gradle plugin, and add the required namespace and android:exported attributes. The archivesBaseName property is no longer supported and is replaced with the current mechanism for setting the APK output name. Update task wiring to use configureEach so icon generation and asset checksums continue to run correctly with the modern task graph. This allows wineandroid to build with recent Gradle and Android SDK versions. Signed-off-by: Twaik Yont <9674930+twaik@users.noreply.github.com> --- dlls/wineandroid.drv/AndroidManifest.xml | 1 + dlls/wineandroid.drv/build.gradle.in | 81 +++++++++++++++++------- 2 files changed, 58 insertions(+), 24 deletions(-) diff --git a/dlls/wineandroid.drv/AndroidManifest.xml b/dlls/wineandroid.drv/AndroidManifest.xml index 574b98e3820..7f0a5e6ce64 100644 --- a/dlls/wineandroid.drv/AndroidManifest.xml +++ b/dlls/wineandroid.drv/AndroidManifest.xml @@ -9,6 +9,7 @@ android:icon="@drawable/wine" android:label="Wine" > <activity + android:exported="true" android:label="Wine" android:name=".WineActivity" android:launchMode="singleInstance" diff --git a/dlls/wineandroid.drv/build.gradle.in b/dlls/wineandroid.drv/build.gradle.in index 662e8b7ea22..8d0e138c9a2 100644 --- a/dlls/wineandroid.drv/build.gradle.in +++ b/dlls/wineandroid.drv/build.gradle.in @@ -18,20 +18,31 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ +if (GradleVersion.current() < GradleVersion.version("9.4.0")) { + throw new GradleException("Gradle 9.4.0+ required") +} + apply plugin: 'com.android.application' buildscript { repositories { - jcenter() + google() + mavenCentral() } dependencies { - classpath "com.android.tools.build:gradle:2.2.1" + classpath "com.android.tools.build:gradle:9.1.0" } } +repositories +{ + google() + mavenCentral() +} + def get_srcdir() { if (srcdir.equals(".")) { return "."; } @@ -52,32 +63,39 @@ def add_icon_task( dir, scale ) } } -def checksum_task() +def checksum_task = tasks.create( "checksumAssets", Exec ) { - return tasks.create( "checksumAssets", Exec ) { - commandLine "sh", "-c", - "(test -d assets && " + - "rm -f assets/files.sum assets/sums.sum && " + - "sha256sum \$(find assets -type f -print) | sed 's/ assets\\// /' >files.sum && " + - "sha256sum files.sum >sums.sum && " + - "mv files.sum sums.sum assets) || rm -rf assets"; - } + commandLine "sh", "-c", + "(test -d assets && " + + "rm -f assets/files.sum assets/sums.sum && " + + "sha256sum \$(find assets -type f -print) | sed 's/ assets\\// /' >files.sum && " + + "sha256sum files.sum >sums.sum && " + + "mv files.sum sums.sum assets) || rm -rf assets"; } -tasks.whenTaskAdded +def icon_tasks = [ + add_icon_task( "ldpi", 0.75 ), + add_icon_task( "mdpi", 1 ), + add_icon_task( "hdpi", 1.5 ), + add_icon_task( "xhdpi", 2 ), + add_icon_task( "xxhdpi", 3 ), + add_icon_task( "xxxhdpi", 4 ) +] + +tasks.configureEach { - if (name.equals( "generateDebugResources" )) + if (name.equals( "preBuild" ) || + name.equals( "processDebugResources" ) || + name.equals( "processDebugNavigationResources" ) || + name.equals( "mergeDebugResources" )) { - dependsOn add_icon_task( "ldpi", 0.75 ) - dependsOn add_icon_task( "mdpi", 1 ) - dependsOn add_icon_task( "hdpi", 1.5 ) - dependsOn add_icon_task( "xhdpi", 2 ) - dependsOn add_icon_task( "xxhdpi", 3 ) - dependsOn add_icon_task( "xxxhdpi", 4 ) + dependsOn icon_tasks } - if (name.equals( "generateDebugAssets" )) + if (name.equals( "preBuild" ) || + name.equals( "generateDebugAssets" ) || + name.equals( "mergeDebugAssets" )) { - dependsOn checksum_task() + dependsOn checksum_task } } @@ -88,8 +106,8 @@ tasks.withType(JavaCompile) android { - compileSdkVersion 25 - buildToolsVersion "25.0.3" + namespace "org.winehq.wine" + compileSdkVersion 36 defaultConfig { @@ -97,7 +115,6 @@ android minSdkVersion 17 versionCode 1 versionName "@PACKAGE_VERSION@" - setProperty( "archivesBaseName", "wine" ) } sourceSets @@ -110,3 +127,19 @@ android main.manifest.srcFile get_srcdir() + "/AndroidManifest.xml" } } + +configurations.configureEach +{ + exclude group: "org.jetbrains.kotlin", module: "kotlin-stdlib" +} + +androidComponents +{ + onVariants(selector().all()) + { variant -> + variant.outputs.forEach + { output -> + output.outputFileName.set("wine-${variant.name}.apk") + } + } +} -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10354
From: Twaik Yont <9674930+twaik@users.noreply.github.com> Replace the bool type with BOOL for the is_desktop field to match the rest of device.c and avoid mixing C99 bool with Win32 types. Signed-off-by: Twaik Yont <9674930+twaik@users.noreply.github.com> --- dlls/wineandroid.drv/device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dlls/wineandroid.drv/device.c b/dlls/wineandroid.drv/device.c index b976968f092..8ae0172a57f 100644 --- a/dlls/wineandroid.drv/device.c +++ b/dlls/wineandroid.drv/device.c @@ -132,7 +132,7 @@ struct ioctl_android_create_window struct ioctl_header hdr; int parent; float scale; - bool is_desktop; + BOOL is_desktop; }; struct ioctl_android_destroy_window -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10354
From: Twaik Yont <9674930+twaik@users.noreply.github.com> Remove APK generation from default targets, as Android packaging requires external staging (prefix and dependencies). Add checks for required staged files (libfreetype, wineserver, ntdll) and fail early with a diagnostic message pointing to the reference packaging script. Factor out Android ABI selection to avoid duplication. Signed-off-by: Twaik Yont <9674930+twaik@users.noreply.github.com> --- configure | 27 +++++++++++++++++++-------- configure.ac | 27 +++++++++++++++++++-------- dlls/wineandroid.drv/Makefile.in | 2 -- 3 files changed, 38 insertions(+), 18 deletions(-) diff --git a/configure b/configure index ac58d7c1874..ea8417f3884 100755 --- a/configure +++ b/configure @@ -13060,14 +13060,16 @@ printf "%s\n" "#define SONAME_LIBGLESV2 \"$ac_cv_lib_soname_GLESv2\"" >>confdefs esac fi + + case $HOST_ARCH in + i386) android_abi='x86' ;; + x86_64) android_abi='x86_64' ;; + arm) android_abi='armeabi-v7a' ;; + aarch64) android_abi='arm64-v8a' ;; + esac if test "x$exec_prefix" = xNONE then - case $HOST_ARCH in - i386) exec_prefix='${prefix}/x86' ;; - x86_64) exec_prefix='${prefix}/x86_64' ;; - arm) exec_prefix='${prefix}/armeabi-v7a' ;; - aarch64) exec_prefix='${prefix}/arm64-v8a' ;; - esac + exec_prefix='${prefix}/'${android_abi} fi ;; @@ -24684,9 +24686,18 @@ dlls/ntdll/unix/version.c: dummy @version=\`(GIT_DIR=${wine_srcdir}.git git describe HEAD 2>/dev/null || echo \"wine-\$(PACKAGE_VERSION)\") | sed -n -e '\$\$s/\(.*\)/const char wine_build[] = \"\\1\";/p'\` && (echo \$\$version | cmp -s - \$@) || echo \$\$version >\$@ || (rm -f \$@ && exit 1) programs/winetest/build.rc: dummy @build=\"STRINGTABLE { 1 \\\"\`GIT_DIR=${wine_srcdir}.git git rev-parse HEAD 2>/dev/null\`\\\" }\" && (echo \$\$build | cmp -s - \$@) || echo \$\$build >\$@ || (rm -f \$@ && exit 1) -dlls/wineandroid.drv/wine-debug.apk: dlls/wineandroid.drv/build.gradle ${wine_srcdir}dlls/wineandroid.drv/AndroidManifest.xml ${wine_srcdir}dlls/wineandroid.drv/WineActivity.java ${wine_srcdir}dlls/wineandroid.drv/wine.svg + +wineandroid_drv_required_files = \ + dlls/wineandroid.drv/lib/${android_abi}/libfreetype.so \ + dlls/wineandroid.drv/assets/${android_abi}/bin/wineserver \ + dlls/wineandroid.drv/assets/${android_abi}/lib/wine/${HOST_ARCH}-unix/ntdll.so +\$(wineandroid_drv_required_files): + @echo \"Misbuild detected: missing \$@. See https://gitlab.winehq.org/winehq/tools/-/blob/master/packaging/android/build... for the reference build script.\" + @false + +dlls/wineandroid.drv/wine-debug.apk: all dlls/wineandroid.drv/build.gradle ${wine_srcdir}dlls/wineandroid.drv/AndroidManifest.xml ${wine_srcdir}dlls/wineandroid.drv/WineActivity.java ${wine_srcdir}dlls/wineandroid.drv/wine.svg \$(wineandroid_drv_required_files) cd dlls/wineandroid.drv && gradle -q -Psrcdir=$srcdir assembleDebug - mv dlls/wineandroid.drv/build/outputs/apk/wine-debug.apk \$@" + mv dlls/wineandroid.drv/build/outputs/apk/debug/wine-debug.apk \$@" EXTERNAL_SUBDIRS="libs/capstone libs/c++ libs/c++abi libs/faudio libs/fluidsynth libs/gsm libs/icucommon libs/icui18n libs/jpeg libs/jxr libs/lcms2 libs/ldap libs/mpg123 libs/musl libs/png libs/tiff libs/tomcrypt libs/unwind libs/vkd3d libs/xml2 libs/xslt libs/zlib libs/compiler-rt" diff --git a/configure.ac b/configure.ac index 89243b45be0..6a3be50f2b1 100644 --- a/configure.ac +++ b/configure.ac @@ -1056,14 +1056,16 @@ case $host_os in WINE_CHECK_SONAME(GLESv2,glFlush) + + case $HOST_ARCH in + i386) android_abi='x86' ;; + x86_64) android_abi='x86_64' ;; + arm) android_abi='armeabi-v7a' ;; + aarch64) android_abi='arm64-v8a' ;; + esac if test "x$exec_prefix" = xNONE then - case $HOST_ARCH in - i386) exec_prefix='${prefix}/x86' ;; - x86_64) exec_prefix='${prefix}/x86_64' ;; - arm) exec_prefix='${prefix}/armeabi-v7a' ;; - aarch64) exec_prefix='${prefix}/arm64-v8a' ;; - esac + exec_prefix='${prefix}/'${android_abi} fi ;; @@ -3836,9 +3838,18 @@ WINE_APPEND_RULE( @version=\`(GIT_DIR=${wine_srcdir}.git git describe HEAD 2>/dev/null || echo \"wine-\$(PACKAGE_VERSION)\") | sed -n -e '\$\$s/\(.*\)/const char wine_build[[]] = \"\\1\";/p'\` && (echo \$\$version | cmp -s - \$[@]) || echo \$\$version >\$[@] || (rm -f \$[@] && exit 1) programs/winetest/build.rc: dummy @build=\"STRINGTABLE { 1 \\\"\`GIT_DIR=${wine_srcdir}.git git rev-parse HEAD 2>/dev/null\`\\\" }\" && (echo \$\$build | cmp -s - \$[@]) || echo \$\$build >\$[@] || (rm -f \$[@] && exit 1) -dlls/wineandroid.drv/wine-debug.apk: dlls/wineandroid.drv/build.gradle ${wine_srcdir}dlls/wineandroid.drv/AndroidManifest.xml ${wine_srcdir}dlls/wineandroid.drv/WineActivity.java ${wine_srcdir}dlls/wineandroid.drv/wine.svg + +wineandroid_drv_required_files = \ + dlls/wineandroid.drv/lib/${android_abi}/libfreetype.so \ + dlls/wineandroid.drv/assets/${android_abi}/bin/wineserver \ + dlls/wineandroid.drv/assets/${android_abi}/lib/wine/${HOST_ARCH}-unix/ntdll.so +\$(wineandroid_drv_required_files): + @echo \"Misbuild detected: missing \$@. See https://gitlab.winehq.org/winehq/tools/-/blob/master/packaging/android/build... for the reference build script.\" + @false + +dlls/wineandroid.drv/wine-debug.apk: all dlls/wineandroid.drv/build.gradle ${wine_srcdir}dlls/wineandroid.drv/AndroidManifest.xml ${wine_srcdir}dlls/wineandroid.drv/WineActivity.java ${wine_srcdir}dlls/wineandroid.drv/wine.svg \$(wineandroid_drv_required_files) cd dlls/wineandroid.drv && gradle -q -Psrcdir=$srcdir assembleDebug - mv dlls/wineandroid.drv/build/outputs/apk/wine-debug.apk \$[@]]) + mv dlls/wineandroid.drv/build/outputs/apk/debug/wine-debug.apk \$[@]]) dnl Misc rules diff --git a/dlls/wineandroid.drv/Makefile.in b/dlls/wineandroid.drv/Makefile.in index 9a8be0ef90a..45152b16123 100644 --- a/dlls/wineandroid.drv/Makefile.in +++ b/dlls/wineandroid.drv/Makefile.in @@ -12,5 +12,3 @@ SOURCES = \ opengl.c \ window.c \ wine.svg - -EXTRA_TARGETS = wine-debug.apk -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10354
Well, I updated my changes. Seems like modern Android plugin requires Gradle 9.3.1+ (and most likely will require even higher version in the future) so requiring gradle 9.4.0 seems to be fine on our side. Also I made it explicitly check for required files and reference official build script URL in the case of they are missing (to show the expected workflow). I am planning to open merge request for the official buildscript as well. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10354#note_133196
Also I made it explicitly check for required files and reference official build script URL in the case of they are missing (to show the expected workflow).
I don't think that sort of thing belongs in configure, it should all be handled by the build script. The makefile should build a simple APK to make sure that the code compiles. This is not meant to be the final APK, and it's not meant to contain the assets. The final APK is built by the packaging script. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10354#note_133197
Here lies the problem. You can not build simple apk without explicitly fetching and injecting up-to-date Gradle to `$PATH`, otherwise importing of `com.android.application` will fail anyways. I am almost sure that no sane person will inject up-to-date gradle to their own environment instead of using bundled gradle wrapper which we do not have. So asking user/builder to do `make all`, prepare prefix and then run `make ...wine-debug.apk` with clear and coincise errors should make the situation clear. I think referencing official build script is necessary because people are not aware of it. During my own searches I found only 3rd party ruby script and hangover's Makefile for building the wine backend, and exactly 0 references to official one. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10354#note_133198
Well, if we can't build an APK we need to find some other way to test the build. If you make a change to the Java code, you should be able to test that it compiles without having to run an external packaging script. Note that there's no such thing as an "official" build script. That script in tools is the script I was using back when I was building packages for WineHQ, but someone else may well want to use a different script. We have multiple variants of Debian packages for instance. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10354#note_133199
If the goal is only to keep a minimal build check in configure rather than support a proper Android build, it may make more sense to remove the Android backend build logic from configure and instead point users to the official packaging script. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10354#note_133200
Well, the script is in official winehq git and was written by official wine maintainer, and also was used for building official apk, so I consider it official script. I did not say it must be used for any possible apk. I only said we can direct users there to show expected flow. In the case if you want to keep checking if java code builds we could make it download, unpack and use gradle from the official website. I am not saying that any of my proposotions is correct or not, I am just asking what do you prefer. Btw my AHardwareBuffer code is almost ready, but I could not test it because termux overrides some system libraries so `libandroid.so` can not be linked properly, so I must have correct buildscripts to finish my code. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10354#note_133201
So, do you think downloading recent gradle from official website and using it to perform the check will be fine? -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10354#note_133202
I don't think the build process should be downloading anything. But yeah, I understand that gradle is a huge PITA to work with... -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10354#note_133219
participants (3)
-
Alexandre Julliard (@julliard) -
Twaik Yont -
Twaik Yont (@twaik)