[PATCH 0/9] MR9977: wineandroid: Fix build issues and early runtime regressions on modern Android toolchains
This merge request contains a set of incremental Android-specific fixes aimed at restoring buildability and removing several early runtime regressions when building Wine with modern Android NDK toolchains. The changes are intentionally minimal and focused on correctness and cleanup rather than adding new functionality. Build-related fixes: - Fix missing ffs() declaration by including <strings.h>. - Fix mismatched ANDROID_WindowPosChanged prototype. - Remove leftover drawable_mutex declarations after OpenGL refactoring. - Avoid unsupported pthread mutex attributes on Android. - Export Java-related globals to ensure they remain visible for dlsym with newer NDKs. - Force --rosegment for wine-preloader when supported to avoid excessive ELF size. Runtime-related fixes: - Fix WineAndroid device access by switching to a consistent \Device\WineAndroid path and aligning driver/device object creation. - Fix start_device_callback assignment type to match expected storage. Status: These changes improve build reliability and eliminate some immediate runtime failures, but they do not make wineandroid fully functional yet. This MR is part of an ongoing bring-up effort for modern Android versions and focuses on getting the simplest pieces building and initializing correctly before further functional work. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/9977
From: Twaik Yont <9674930+twaik@users.noreply.github.com> ffs() is used in unix_private.h without a visible prototype, which causes build failures with compilers enforcing ISO C99 or later rules. Include <strings.h> to ensure ffs() is properly declared. Signed-off-by: Twaik Yont <9674930+twaik@users.noreply.github.com> --- dlls/ntdll/unix/unix_private.h | 1 + 1 file changed, 1 insertion(+) diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h index 8d77d726a33..8b633dfdd68 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h @@ -23,6 +23,7 @@ #include <pthread.h> #include <signal.h> +#include <strings.h> #include "unixlib.h" #include "wine/unixlib.h" #include "wine/server.h" -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9977
From: Twaik Yont <9674930+twaik@users.noreply.github.com> The ANDROID_WindowPosChanged prototype in android.h was not updated along with its implementation in e28867deb16579e541397a8e0c90153c94c82b90. Fix the declaration to match the current function signature. Signed-off-by: Twaik Yont <9674930+twaik@users.noreply.github.com> --- dlls/wineandroid.drv/android.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dlls/wineandroid.drv/android.h b/dlls/wineandroid.drv/android.h index 07c0f9ea7b7..98e5136ec07 100644 --- a/dlls/wineandroid.drv/android.h +++ b/dlls/wineandroid.drv/android.h @@ -95,7 +95,7 @@ extern UINT ANDROID_ShowWindow( HWND hwnd, INT cmd, RECT *rect, UINT swp ); extern LRESULT ANDROID_WindowMessage( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp ); extern BOOL ANDROID_WindowPosChanging( HWND hwnd, UINT swp_flags, BOOL shaped, const struct window_rects *rects ); extern BOOL ANDROID_CreateWindowSurface( HWND hwnd, BOOL layered, const RECT *surface_rect, struct window_surface **surface ); -extern void ANDROID_WindowPosChanged( HWND hwnd, HWND insert_after, HWND owner_hint, UINT swp_flags, BOOL fullscreen, +extern void ANDROID_WindowPosChanged( HWND hwnd, HWND insert_after, HWND owner_hint, UINT swp_flags, const struct window_rects *new_rects, struct window_surface *surface ); extern ANativeWindow *get_client_window( HWND hwnd ); extern BOOL has_client_surface( HWND hwnd ); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9977
From: Twaik Yont <9674930+twaik@users.noreply.github.com> Commit 392d6163614065edab50d5d629ff9f145e0a1012 removed the drawable_mutex definition and all its users in the Android OpenGL driver, but left behind the public declaration and initialization. Remove the leftover extern declaration from android.h and the corresponding pthread_mutex_init() call from init.c. Signed-off-by: Twaik Yont <9674930+twaik@users.noreply.github.com> --- dlls/wineandroid.drv/android.h | 1 - dlls/wineandroid.drv/init.c | 1 - 2 files changed, 2 deletions(-) diff --git a/dlls/wineandroid.drv/android.h b/dlls/wineandroid.drv/android.h index 98e5136ec07..1ed83406cff 100644 --- a/dlls/wineandroid.drv/android.h +++ b/dlls/wineandroid.drv/android.h @@ -53,7 +53,6 @@ DECL_FUNCPTR( ANativeWindow_release ); * OpenGL driver */ -extern pthread_mutex_t drawable_mutex; extern UINT ANDROID_OpenGLInit( UINT version, const struct opengl_funcs *opengl_funcs, const struct opengl_driver_funcs **driver_funcs ); diff --git a/dlls/wineandroid.drv/init.c b/dlls/wineandroid.drv/init.c index 472de7b8317..9ceacacd51a 100644 --- a/dlls/wineandroid.drv/init.c +++ b/dlls/wineandroid.drv/init.c @@ -537,7 +537,6 @@ static HRESULT android_init( void *arg ) pthread_mutexattr_init( &attr ); pthread_mutexattr_settype( &attr, PTHREAD_MUTEX_RECURSIVE ); - pthread_mutex_init( &drawable_mutex, &attr ); pthread_mutex_init( &win_data_mutex, &attr ); pthread_mutexattr_destroy( &attr ); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9977
From: Twaik Yont <9674930+twaik@users.noreply.github.com> Newer compilers warn or error when assigning a function pointer to an integer-typed field without an explicit cast. Cast android_start_device when assigning it to start_device_callback to satisfy the expected UINT64 type. Signed-off-by: Twaik Yont <9674930+twaik@users.noreply.github.com> --- dlls/wineandroid.drv/dllmain.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dlls/wineandroid.drv/dllmain.c b/dlls/wineandroid.drv/dllmain.c index c8495d679f9..d8f3346954c 100644 --- a/dlls/wineandroid.drv/dllmain.c +++ b/dlls/wineandroid.drv/dllmain.c @@ -123,6 +123,6 @@ BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserved ) if (__wine_init_unix_call()) return FALSE; params.register_window_callback = register_window_callback; - params.start_device_callback = android_start_device; + params.start_device_callback = (UINT64) android_start_device; return !ANDROID_CALL( init, ¶ms ); } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9977
From: Twaik Yont <9674930+twaik@users.noreply.github.com> After commit 7557d83c074a958ea042c3b86e11cd3b5670ec66, the Android OpenGL driver fails to build because set_window_opengl_drawable() is no longer visible. Export set_window_opengl_drawable() on Android to restore the wineandroid.drv build, while keeping the existing internal linkage for non-Android platforms. Signed-off-by: Twaik Yont <9674930+twaik@users.noreply.github.com> --- dlls/win32u/opengl.c | 7 ++++++- dlls/wineandroid.drv/opengl.c | 3 +++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/dlls/win32u/opengl.c b/dlls/win32u/opengl.c index f5308314812..37294238285 100644 --- a/dlls/win32u/opengl.c +++ b/dlls/win32u/opengl.c @@ -1346,7 +1346,12 @@ static int win32u_wglGetPixelFormat( HDC hdc ) return format > 0 ? format : 0; } -static void set_window_opengl_drawable( HWND hwnd, struct opengl_drawable *new_drawable, BOOL current ) +#ifdef __ANDROID__ +DECLSPEC_EXPORT +#else +static +#endif +void set_window_opengl_drawable( HWND hwnd, struct opengl_drawable *new_drawable, BOOL current ) { struct opengl_drawable *old_drawable = NULL; WND *win; diff --git a/dlls/wineandroid.drv/opengl.c b/dlls/wineandroid.drv/opengl.c index 1efd312b940..366158d4955 100644 --- a/dlls/wineandroid.drv/opengl.c +++ b/dlls/wineandroid.drv/opengl.c @@ -44,6 +44,9 @@ #include "wine/opengl_driver.h" #include "wine/debug.h" +// defined in dlls/win32u/opengl.c +extern void set_window_opengl_drawable( HWND hwnd, struct opengl_drawable *new_drawable, BOOL current ); + WINE_DEFAULT_DEBUG_CHANNEL(android); static const struct egl_platform *egl; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9977
From: Twaik Yont <9674930+twaik@users.noreply.github.com> Android only provides pthread_mutexattr_setprotocol() starting with API 28 and does not support robust mutexes. Initialize pulse_mutex without special attributes on Android and keep the existing mutex setup on other platforms. Signed-off-by: Twaik Yont <9674930+twaik@users.noreply.github.com> --- dlls/winepulse.drv/pulse.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dlls/winepulse.drv/pulse.c b/dlls/winepulse.drv/pulse.c index 7c8d872c604..5e90879f80a 100644 --- a/dlls/winepulse.drv/pulse.c +++ b/dlls/winepulse.drv/pulse.c @@ -240,6 +240,7 @@ static int pulse_poll_func(struct pollfd *ufds, unsigned long nfds, int timeout, static NTSTATUS pulse_process_attach(void *args) { +#ifndef __ANDROID__ pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); @@ -248,6 +249,9 @@ static NTSTATUS pulse_process_attach(void *args) if (pthread_mutex_init(&pulse_mutex, &attr) != 0) pthread_mutex_init(&pulse_mutex, NULL); +#else + pthread_mutex_init(&pulse_mutex, NULL); +#endif #ifdef _WIN64 if (NtCurrentTeb()->WowTebOffset) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9977
From: Twaik Yont <9674930+twaik@users.noreply.github.com> The java_vm, java_object and java_gdt_sel globals are looked up via dlsym, but can end up with hidden visibility and therefore missing from the dynamic symbol table. Explicitly export these symbols to ensure they remain visible to dlsym. This appears to be required with newer Android NDK toolchains, likely related to changes in symbol visibility handling (for example Android NDK r22). Reference: https://github.com/android/ndk/wiki/Changelog-r22 Signed-off-by: Twaik Yont <9674930+twaik@users.noreply.github.com> --- dlls/ntdll/unix/loader.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c index c9696fef115..5b765d7a869 100644 --- a/dlls/ntdll/unix/loader.c +++ b/dlls/ntdll/unix/loader.c @@ -1809,9 +1809,9 @@ static void start_main_thread(void) #define WINE_JAVA_CLASS "org/winehq/wine/WineActivity" #endif -JavaVM *java_vm = NULL; -jobject java_object = 0; -unsigned short java_gdt_sel = 0; +DECLSPEC_EXPORT JavaVM *java_vm = NULL; +DECLSPEC_EXPORT jobject java_object = 0; +DECLSPEC_EXPORT unsigned short java_gdt_sel = 0; /* main Wine initialisation */ static jstring wine_init_jni( JNIEnv *env, jobject obj, jobjectArray cmdline, jobjectArray environment ) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9977
From: Twaik Yont <9674930+twaik@users.noreply.github.com> Following an earlier change, the \\.\WineAndroid path and the corresponding \??\WineAndroid symbolic link no longer resolved correctly. Open the WineAndroid device directly via \Device\WineAndroid, create the driver and device objects using explicit kernel object names, and update the ioctl path to match. Use RTL_CONSTANT_STRING for allocation-free UNICODE_STRING initialization. Signed-off-by: Twaik Yont <9674930+twaik@users.noreply.github.com> --- dlls/wineandroid.drv/device.c | 5 ++--- dlls/wineandroid.drv/dllmain.c | 17 +++-------------- 2 files changed, 5 insertions(+), 17 deletions(-) diff --git a/dlls/wineandroid.drv/device.c b/dlls/wineandroid.drv/device.c index 1c7985ca1a5..d936c95b15a 100644 --- a/dlls/wineandroid.drv/device.c +++ b/dlls/wineandroid.drv/device.c @@ -1188,7 +1188,7 @@ void start_android_device(void) static int android_ioctl( enum android_ioctl code, void *in, DWORD in_size, void *out, DWORD *out_size ) { - static const WCHAR deviceW[] = {'\\','\\','.','\\','W','i','n','e','A','n','d','r','o','i','d',0 }; + static const WCHAR deviceW[] = { '\\','D','e','v','i','c','e','\\','W','i','n','e','A','n','d','r','o','i','d', 0 }; static HANDLE device; IO_STATUS_BLOCK iosb; NTSTATUS status; @@ -1196,12 +1196,11 @@ static int android_ioctl( enum android_ioctl code, void *in, DWORD in_size, void if (!device) { OBJECT_ATTRIBUTES attr; - UNICODE_STRING name; + UNICODE_STRING name = RTL_CONSTANT_STRING( deviceW ); IO_STATUS_BLOCK io; NTSTATUS status; HANDLE file; - RtlInitUnicodeString( &name, deviceW ); InitializeObjectAttributes( &attr, &name, OBJ_CASE_INSENSITIVE, NULL, NULL ); status = NtCreateFile( &file, GENERIC_READ | SYNCHRONIZE, &attr, &io, NULL, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, diff --git a/dlls/wineandroid.drv/dllmain.c b/dlls/wineandroid.drv/dllmain.c index d8f3346954c..9c82565fd6f 100644 --- a/dlls/wineandroid.drv/dllmain.c +++ b/dlls/wineandroid.drv/dllmain.c @@ -46,28 +46,18 @@ static NTSTATUS WINAPI ioctl_callback( DEVICE_OBJECT *device, IRP *irp ) static NTSTATUS CALLBACK init_android_driver( DRIVER_OBJECT *driver, UNICODE_STRING *name ) { - static const WCHAR device_nameW[] = {'\\','D','e','v','i','c','e','\\','W','i','n','e','A','n','d','r','o','i','d',0 }; - static const WCHAR device_linkW[] = {'\\','?','?','\\','W','i','n','e','A','n','d','r','o','i','d',0 }; - - UNICODE_STRING nameW, linkW; + UNICODE_STRING nameW = RTL_CONSTANT_STRING( L"\\Device\\WineAndroid" ); DEVICE_OBJECT *device; - NTSTATUS status; driver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ioctl_callback; - RtlInitUnicodeString( &nameW, device_nameW ); - RtlInitUnicodeString( &linkW, device_linkW ); - - if ((status = IoCreateDevice( driver, 0, &nameW, 0, 0, FALSE, &device ))) return status; - return IoCreateSymbolicLink( &linkW, &nameW ); + return IoCreateDevice( driver, 0, &nameW, 0, 0, FALSE, &device ); } static DWORD CALLBACK device_thread( void *arg ) { - static const WCHAR driver_nameW[] = {'\\','D','r','i','v','e','r','\\','W','i','n','e','A','n','d','r','o','i','d',0 }; - HANDLE start_event = arg; - UNICODE_STRING nameW; + UNICODE_STRING nameW = RTL_CONSTANT_STRING( L"\\Driver\\WineAndroid" ); NTSTATUS status; DWORD ret; @@ -75,7 +65,6 @@ static DWORD CALLBACK device_thread( void *arg ) if (ANDROID_CALL( java_init, NULL )) return 0; /* not running under Java */ - RtlInitUnicodeString( &nameW, driver_nameW ); if ((status = IoCreateDriver( &nameW, init_android_driver ))) { FIXME( "failed to create driver error %lx\n", status ); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9977
From: Twaik Yont <9674930+twaik@users.noreply.github.com> Without rosegment the linker may produce an excessively large preloader ELF (around 2GB) due to the resulting segment layout. Enabling rosegment keeps the wine-preloader output size reasonable. Keep this flag limited to wine-preloader to avoid affecting other binaries. Reference: https://github.com/android/ndk/wiki/Changelog-r22 Signed-off-by: Twaik Yont <9674930+twaik@users.noreply.github.com> --- configure | 30 ++++++++++++++++++++++++++++++ configure.ac | 1 + 2 files changed, 31 insertions(+) diff --git a/configure b/configure index 29dbfa40ba1..4ead1e784d3 100755 --- a/configure +++ b/configure @@ -11935,6 +11935,36 @@ then : WINELOADER_LDFLAGS="-Wl,--export-dynamic" fi WINEPRELOADER_LDFLAGS="-static -nostartfiles -nodefaultlibs -Wl,-Ttext=0x7d400000" + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports -Wl,--rosegment" >&5 +printf %s "checking whether the compiler supports -Wl,--rosegment... " >&6; } +if test ${ac_cv_cflags__Wl___rosegment+y} +then : + printf %s "(cached) " >&6 +else case e in #( + e) ac_wine_try_cflags_saved=$CFLAGS +CFLAGS="$CFLAGS -Wl,--rosegment" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int main(int argc, char **argv) { return 0; } +_ACEOF +if ac_fn_c_try_link "$LINENO" +then : + ac_cv_cflags__Wl___rosegment=yes +else case e in #( + e) ac_cv_cflags__Wl___rosegment=no ;; +esac +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam \ + conftest$ac_exeext conftest.$ac_ext +CFLAGS=$ac_wine_try_cflags_saved ;; +esac +fi +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cflags__Wl___rosegment" >&5 +printf "%s\n" "$ac_cv_cflags__Wl___rosegment" >&6; } +if test "x$ac_cv_cflags__Wl___rosegment" = xyes +then : + WINEPRELOADER_LDFLAGS="$WINEPRELOADER_LDFLAGS -Wl,--rosegment" +fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for -lGLESv2" >&5 printf %s "checking for -lGLESv2... " >&6; } diff --git a/configure.ac b/configure.ac index da4a0af4a60..5213a94f0e7 100644 --- a/configure.ac +++ b/configure.ac @@ -1001,6 +1001,7 @@ case $host_os in WINE_TRY_CFLAGS([-Wl,-z,defs],[UNIXLDFLAGS="$UNIXLDFLAGS -Wl,-z,defs"]) WINE_TRY_CFLAGS([-fPIC -Wl,--export-dynamic],[WINELOADER_LDFLAGS="-Wl,--export-dynamic"]) WINEPRELOADER_LDFLAGS="-static -nostartfiles -nodefaultlibs -Wl,-Ttext=0x7d400000" + WINE_TRY_CFLAGS([-Wl,--rosegment], [WINEPRELOADER_LDFLAGS="$WINEPRELOADER_LDFLAGS -Wl,--rosegment"]) WINE_CHECK_SONAME(GLESv2,glFlush) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9977
I am not sure what exactly went wrong in tests, I see this in report ``` <testsuite name="winmm:mci" file="dlls/winmm/tests/mci.c" time="19.437000" tests="0" failures="0" skipped="0"> <testcase classname="winmm:mci" name="winmm:mci status 1" file="dlls/winmm/tests/mci.c" assertions="0" time="19.437000"> <system-out>Test exited with status 1</system-out> <failure/> </testcase> </testsuite> ``` while I see correct test output in the log (except X11 error, probably). ``` winmm:mci start dlls/winmm/tests/mci.c ALSA lib seq_hw.c:540:(snd_seq_hw_open) open /dev/snd/seq failed: No such file or directory X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 142 (Composite) Minor opcode of failed request: 3 () Value in failed request: 0x18001d2 Serial number of failed request: 2226 Current serial number in output stream: 2241 mci.c:233:0.029 Test marked todo: open notify: MCIERR_EXTENSION_NOT_FOUND ... mci.c:1259:16.666 Wine style MCI auto-close upon notification mci.c:1425:17.740 Test succeeded mci.c:1574:18.904 Test succeeded winmm:mci:04d8 done (1) in 19s 4162B ``` -- https://gitlab.winehq.org/wine/wine/-/merge_requests/9977#note_128092
participants (2)
-
Twaik Yont -
Twaik Yont (@twaik)