Compiling TGUI for Android

Started by glagan, 12 October 2018, 22:13:29

glagan

Hi, i'm trying to build (well, link) TGUI version 0.8 for Android but i'm having a bit of trouble.
I'm on Windows 10 and using GCC-6.3.0-1.

I already compiled SFML for Android with success, using the armeab-v7a ABI architecture and the example application is working fine.
I used the tutorial they have on Github (https://github.com/SFML/SFML/wiki/Tutorial%3A-Building-SFML-for-Android).

I also used the NDK r17c since it wasn't working with r18b, and SFML is in the /third_party folder as it should be.

So, everything is set up (I followed your tutorial) and I used cmake:
cmake -DCMAKE_SYSTEM_NAME=Android -DCMAKE_ANDROID_NDK=/ndk -DCMAKE_ANDROID_ARCH_ABI=armeabi-v7a -DCMAKE_ANDROID_STL_TYPE=c++_static -DCMAKE_BUILD_TYPE=Debug .. -G "MinGW Makefiles"
-- Android: Targeting API '28' with architecture 'arm', ABI 'armeabi-v7a', and processor 'armv7-a'
-- Android: Selected GCC toolchain 'arm-linux-androideabi-4.9'
-- The C compiler identification is GNU 4.9.0
-- The CXX compiler identification is GNU 4.9.0
-- Check for working C compiler: /ndk/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64/bin/arm-linux-androideabi-gcc.exe
-- Check for working C compiler: /ndk/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64/bin/arm-linux-androideabi-gcc.exe -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /ndk/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64/bin/arm-linux-androideabi-g++.exe
-- Check for working CXX compiler: /ndk/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64/bin/arm-linux-androideabi-g++.exe -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found SFML 2.5.0 in C:/SFML/lib/cmake/SFML
-- Configuring done
-- Generating done
-- Build files have been written to: /TGUI/armeabi-v7a


I shortened the ndk path but I used a good and working one. Everything is still fine, so I build TGUI.
mingw32-make
... everything compile ...
[97%] Linking CXX shared library ..\..\lib\libtgui-d.so
/ndk/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.9.x/../../../../arm-linux-androideabi/bin/ld.exe: error: C:\SFML\bin\sfml-graphics-d-2.dll:1:3: invalid character
/ndk/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.9.x/../../../../arm-linux-androideabi/bin/ld.exe: error: C:\SFML\bin\sfml-graphics-d-2.dll:1:3: syntax error, unexpected $end
/ndk/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.9.x/../../../../arm-linux-androideabi/bin/ld.exe: error: C:\SFML\bin\sfml-graphics-d-2.dll: not an object or archive
/ndk/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.9.x/../../../../arm-linux-androideabi/bin/ld.exe: error: C:\SFML\bin\sfml-window-d-2.dll:1:3: invalid character
/ndk/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.9.x/../../../../arm-linux-androideabi/bin/ld.exe: error: C:\SFML\bin\sfml-window-d-2.dll:1:3: syntax error, unexpected $end
/ndk/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.9.x/../../../../arm-linux-androideabi/bin/ld.exe: error: C:\SFML\bin\sfml-window-d-2.dll: not an object or archive
/ndk/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.9.x/../../../../arm-linux-androideabi/bin/ld.exe: error: C:\SFML\bin\sfml-system-d-2.dll:1:3: invalid character
/ndk/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.9.x/../../../../arm-linux-androideabi/bin/ld.exe: error: C:\SFML\bin\sfml-system-d-2.dll:1:3: syntax error, unexpected $end
/ndk/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.9.x/../../../../arm-linux-androideabi/bin/ld.exe: error: C:\SFML\bin\sfml-system-d-2.dll: not an object or archive
collect2.exe: error: ld returned 1 exit status
src\TGUI\CMakeFiles\tgui.dir\build.make:2176: recipe for target 'lib/libtgui-d.so' failed
mingw32-make[2]: *** [lib/libtgui-d.so] Error 1
CMakeFiles\Makefile2:86: recipe for target 'src/TGUI/CMakeFiles/tgui.dir/all' failed
mingw32-make[1]: *** [src/TGUI/CMakeFiles/tgui.dir/all] Error 2
Makefile:128: recipe for target 'all' failed
mingw32-make: *** [all] Error 2


And that's the error, the .dll used when linking have "invalid character", but the .dll are working and I am using them, I also compiled them myself using the same compiler.
Am I supposed to build SFML with the same toolchain as the one used by the NDK, or do I need to pass the toolchain I used ?
Also, is the linker supposed to use the lib build for Windows and not those build for Android (in the ndk folder) ?

Thanks.

texus

It has to use the android libraries. Based on the output it is using the windows libraries of SFML which is why it isn't working.
The original problem already occurs when running cmake where it prints "Found SFML 2.5.0 in C:/SFML/lib/cmake/SFML". The path that gets printed should be inside the NDK directory.

I never actually tried compiling for android on windows (only on linux), but my cmake script should try to find SFML in "${CMAKE_ANDROID_NDK}/sources/third_party/sfml/lib/${CMAKE_ANDROID_ARCH_ABI}/cmake/SFML". If you copy the exact path "/ndk/sources/third_party/sfml/lib/armeabi-v7a/cmake/SFML" in explorer, does it open the folder containing *.cmake files?

You can manually specify the SFML version by adding the following to your cmake command:
-DSFML_DIR=/ndk/sources/third_party/sfml/lib/armeabi-v7a/cmake/SFML

But I do like to find out why it isn't automatically finding that SFML version. If the folder is correct and specifying SFML_DIR fixes the problem then it means I will have to find a way to improve my cmake script.

glagan

Ok, thanks for the answer. I saw the line in the CMake script that try to find SFML in the NDK folder, and the .cmake files do exist.

So the command
cmake -DSFML_DIR=/ndk/sources/third_party/sfml/lib/armeabi-v7a/cmake/SFML -DCMAKE_SYSTEM_NAME=Android -DCMAKE_ANDROID_NDK=/ndk -DCMAKE_ANDROID_ARCH_ABI=x86 -DCMAKE_ANDROID_STL_TYPE=c++_static -DCMAKE_BUILD_TYPE=Debug .. -G "MinGW Makefiles"
worked !

It's weird that the CMake script didn't use that folder since it's written to search that folder, line 169:
...
elseif(TGUI_OS_ANDROID)  # Search for SFML in the android NDK (if no other directory is specified)
    find_package(SFML 2 COMPONENTS graphics window system PATHS "${CMAKE_ANDROID_NDK}/sources/third_party/sfml/lib/${CMAKE_ANDROID_ARCH_ABI}/cmake/SFML")
...


Now I have another problem, when I start the application the activity start but the SFML window don't show...
Also, I couldn't build the example using your tutorial since it says that the android program is deprecated, and the command "update project --name TGUI --path . --target android-23" doesn't exist, so I made it using Gradle and following the SFML Android example and adding the tgui lines needed, but it doesn't work :|

I tried many tests to find why, and I managed to make the sfml example to work with TGUI https://i.imgur.com/6Now8YD.jpg, the difference between the elements is huge but I think it's just a font size problem since the text that is not from a TGUI Widget have a font size of 64.

What blocked the example from working is the meta-data in the AndroidManifest.xml:
<meta-data android:name="android.app.lib_name" android:value="sfml-activity-d" />
<meta-data android:name="tgui.app.lib_name" android:value="tgui-activity-d" />
<meta-data android:name="sfml.app.lib_name" android:value="sfml-example" />

Having them with these names make it work, even with the tgui one last.

With a working project I replaced the SFML example main.cpp with your TGUI example main.cpp and it works fine.
I uploaded the working example: http://files.nikurasu.org/tgui/example.zip, you only need to change the file local.properties with your Android SDK and NDK path, and an optionnal path to the file "tools.jar" found in Android Studio jre folder (used by gradle) which wasn't in the default Java folder for me.

Maybe the example in the repository need to be updated, but I don't know if the one I uploaded is fine, since I just copy/paste it from SFML without knowing a lot about it :/

texus

The AndroidManifest.xml change looks weird to me. When the program starts, it loads what is in "android.app.lib_name", which is "sfml-activity-d". When sfml-activity is finished, it loads what is in "sfml.app.lib_name". This should be the tgui-activity, otherwise my activity would never be loaded. When my activity finishes it jumps to "tgui.app.lib_name", which would cause an infinite loop according to that manifest. The only purpose of tgui-activity is to load the tgui library, so I have no idea how TGUI could work like that.

I did notice that your Android.mk file also contains "LOCAL_SHARED_LIBRARIES += sfml-activity-d". Looking at the SFML example, it seems like this was added when they changed to gradle. Maybe loading the SFML or TGUI activity there affects what has to be placed in the manifest?

I'm not sure why you had to change to gradle, I tested the example with NDK 17b, I would be surprised if they removed stuff in 17c. If it is deprecated then it should still be possible to use it. What exactly is the error when running "android update project --name TGUI --path . --target android-23"?
If you just run "android" without any parameters, the SDK manager should open. Is the "SDK Platform" installed for "Android 6.0 (API 23)"?

I'll have a look at updating to gradle though, I have to do it at some point. Building SFML for android is left in a bit of a WIP state and I was hoping that they would fix these issues first, but I can't keep waiting forever. I don't know much about gradle either (other than the things I pieced together when I updated the android tutorial on the SFML wiki) so I was also just going to copy it from SFML. But I want to have the issue with AndroidManifest.xml sorted out before I publish the new example, I need to at least understand how and where my library gets loaded.

glagan

When I just use "android" it says:
**************************************************************************
The "android" command is deprecated.
For manual SDK, AVD, and project management, please use Android Studio.
For command-line tools, use tools\bin\sdkmanager.bat
and tools\bin\avdmanager.bat
**************************************************************************

Invalid or unsupported command ""

Supported commands are:
android list target
android list avd
android list device
android create avd
android move avd
android delete avd
android list sdk
android update sdk


But maybe it's because it's from the SDK shipped with Android Studio, but I don't think thats the problem since i'm using this SDK with gradle and it works.
And yes, SFML for Android is even too much of a WIP state, I don't think i'm going to use it in the end :s It's too troublesome, and I have a simple error that I can't find for 2 days now while it compile and run fine on desktop...

Thanks for the answers though, I managed to make the example work ^^'

texus

For future reference, the example has now been updated to use gradle.
It worked for me without changing AndroidManifest.xml, but I did have to change Android.mk to get it working.