libsdl-org / SDL

Simple Directmedia Layer
https://libsdl.org
zlib License
9.79k stars 1.82k forks source link

Error when compiling CMake project for android #5944

Closed Evaghetti closed 2 years ago

Evaghetti commented 2 years ago

Hello, I'm currently developing a game with SDL and decided to try to port it to Android, i'm currently following this tutorial: https://github.com/libsdl-org/SDL/blob/main/docs/README-android.md I'm trying to use the steps described for compiling with CMake, my project consists of two targets, one is a .so that has most of the game's logic, and the game itself that uses SDL2 to show what happens inside the .so, as far as i'm aware the project was able to compile the .so fine, whoever when it tries to compile the SDL side of the project, i get this error repeatedly: 2022-07-22T00:39:16.607-0300 [ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter] /home/enzo/Android/Sdk/ndk/21.4.7075529/toolchains/llvm/prebuilt/linux-x86_64/lib64/clang/9.0.9/include/mmintrin.h:504:12: error: invalid conversion between vector type '__m64' (vector of 1 'long long' value) and integer type 'int' of different size 2022-07-22T00:39:16.607-0300 [ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter] return (__m64)__builtin_ia32_psubb((__v8qi)__m1, (__v8qi)__m2); 2022-07-22T00:39:16.607-0300 [ERROR] [org.gradle.internal.buildevents.BuildExceptionReporter] ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ I tried googling for what this error means but couldn't find a correct answer for it, could someone help me? I attached the CMakeLists from my project, it's my first time trying to compile anything with NDK, so if there's anything more that i can provide you just have to ask, thanks CMakeLists.txt

Evaghetti commented 2 years ago

Ok, so i was able to make progress, now i'm struggling to compile my projects with SDL_image, SDL_ttf and SDL_net I removed the comments on CMakeLists inside the app/jni folder related to these methods and i got past the generating phase, but i got errors in the building phase, here's what i g

CMake Error: install(EXPORT "SDL2ImageExports" ...) includes target "SDL2_image" which requires target "SDL2" that is not in this export set, but in multiple other export sets: lib/cmake/SDL2/SDL2Targets.cmake, share/ndk-modules/SDL2/Android.mk. An exported target cannot depend upon another target which is exported multiple times. Consider consolidating the exports of the "SDL2" target to a single export. CMake Error: install(EXPORT "SDL2_ttfTargets" ...) includes target "SDL2_ttf" which requires target "SDL2" that is not in this export set, but in multiple other export sets: lib/cmake/SDL2/SDL2Targets.cmake, share/ndk-modules/SDL2/Android.mk. An exported target cannot depend upon another target which is exported multiple times. Consider consolidating the exports of the "SDL2" target to a single export. CMake Error: install(EXPORT "SDL2NetExports" ...) includes target "SDL2_net" which requires target "SDL2" that is not in this export set, but in multiple other export sets: lib/cmake/SDL2/SDL2Targets.cmake, share/ndk-modules/SDL2/Android.mk. An exported target cannot depend upon another target which is exported multiple times. Consider consolidating the exports of the "SDL2" target to a single export. CMake Warning: Manually-specified variables were not used by the project:

ANDROID_APP_PLATFORM

CMake Generate step failed. Build files cannot be regenerated correctly.

I'll update the title to this issue since the problem has changed

madebr commented 2 years ago

The error requires target "SDL2" that is not in this export set" is due to CMake requiring all linked public targets of an installed targets needing to be in the same export set.

I think we need to modify the cmake scripts of SDL2_(image|mixer|ttf) to only link to SDL2 at build time. This can be done by replacing

target_link_libraries(SDL2_image PRIVATE ${sdl2_target_name})

with

target_link_libraries(SDL2_image PRIVATE $<BUILD_INTERFACE:${sdl2_target_name}>)

@Evaghetti Can you apply this change to the cmake scripts of SDL2_image/SDL2_mixer/SDL2_ttf and check whether the cmake error disappears?

To avoid having having to carry a patch, you can avoid installing of SDL2_mixer/SDL2_ttf/SDL2_net by configuring your application with -DSDL2IMAGE_INSTALL=OFF -DSDL2TTF_INSTALL=OFF -DSDL2NET_INSTALL=OFF

Evaghetti commented 2 years ago

@Evaghetti Can you apply this change to the cmake scripts of SDL2_image/SDL2_mixer/SDL2_ttf and check whether the cmake error disappears?

Changing the lines you said gave me the same error as before, however...

To avoid having having to carry a patch, you can avoid installing of SDL2_mixer/SDL2_ttf/SDL2_net by configuring your application with -DSDL2IMAGE_INSTALL=OFF -DSDL2TTF_INSTALL=OFF -DSDL2NET_INSTALL=OFF

This worked! Now it is failing at building time, i receive the following error:

/home/enzo/Android/Sdk/ndk/21.4.7075529/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/arm-linux-androideabi/16/crtbegin_dynamic.o:crtbegin.c:function _start_main: error: undefined reference to 'main'

But my CMakeLists.txt already links to SDL2main:

target_link_libraries(${DIGIVICE_TARGET} digilib SDL2 SDL2main SDL2_image SDL2_ttf SDL2_net)

Do i need to change something else?

madebr commented 2 years ago

On Android, you should not build an executable but build a shared library. SDL2Activity will then load these libraries. https://github.com/libsdl-org/SDL/blob/aad7ef6eafc01fd90677118340dc33f2f7ba9726/android-project/app/src/main/java/org/libsdl/app/SDLActivity.java#L266-L282 You can extend SL2Activity in java/kotlin and override these (and other) methods.

Evaghetti commented 2 years ago

So, i did that, as follows:

if(${BUILD_DIGIVICE})
    message(STATUS "Will build digivice")
    if (${CMAKE_SYSTEM_NAME} STREQUAL "Android")
        set(DIGIVICE_TARGET "libmain")
        add_library(${DIGIVICE_TARGET} SHARED)
        target_compile_definitions(${DIGIVICE_TARGET} PUBLIC SDL_DISABLE_IMMINTRIN_H)
    else()
        set(DIGIVICE_TARGET "digivice")
        add_executable(${DIGIVICE_TARGET})
    endif()
    target_sources(${DIGIVICE_TARGET} PRIVATE digivice.c source/digivice/game.c source/digivice/texture.c source/digivice/animation.c source/digivice/menu.c source/digivice/avatar.c source/digivice/button.c source/digivice/battle.c source/digivice/globals.c)
    target_link_libraries(${DIGIVICE_TARGET} digilib SDL2 SDL2main SDL2_image SDL2_ttf SDL2_net)
    include_directories(include/digivice)
endif()

Still, it isn't able to find libmain it seems, in fact it seems to get stuck before compiling it, i ran gradlew installDebug and saved the log if you want to check it out, but it seems to be failling to compile some stuff from SDL

[1/32] Linking C executable /home/enzo/android-test/app/build/intermediates/cxx/Debug/142el305/obj/armeabi-v7a/showimage
FAILED: /home/enzo/android-test/app/build/intermediates/cxx/Debug/142el305/obj/armeabi-v7a/showimage 
: && /home/enzo/Android/Sdk/ndk/21.4.7075529/toolchains/llvm/prebuilt/linux-x86_64/bin/clang --target=armv7-none-linux-androideabi16 --gcc-toolchain=/home/enzo/Android/Sdk/ndk/21.4.7075529/toolchains/llvm/prebuilt/linux-x86_64 --sysroot=/home/enzo/Android/Sdk/ndk/21.4.7075529/toolchains/llvm/prebuilt/linux-x86_64/sysroot -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -march=armv7-a -mthumb -Wformat -Werror=format-security  -O0 -fno-limit-debug-info  -Wl,--exclude-libs,libgcc.a -Wl,--exclude-libs,libgcc_real.a -Wl,--exclude-libs,libatomic.a -static-libstdc++ -Wl,--build-id -Wl,--fatal-warnings -Wl,--exclude-libs,libunwind.a -Wl,--no-undefined -Qunused-arguments -Wl,--gc-sections SDL_image/CMakeFiles/showimage.dir/showimage.c.o  -o /home/enzo/android-test/app/build/intermediates/cxx/Debug/142el305/obj/armeabi-v7a/showimage  /home/enzo/android-test/app/build/intermediates/cxx/Debug/142el305/obj/armeabi-v7a/libSDL2_image.so  SDL/libSDL2main.a  /home/enzo/android-test/app/build/intermediates/cxx/Debug/142el305/obj/armeabi-v7a/libSDL2.so  -latomic -lm && :
/home/enzo/Android/Sdk/ndk/21.4.7075529/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/arm-linux-androideabi/16/crtbegin_dynamic.o:crtbegin.c:function _start_main: error: undefined reference to 'main'
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Is there somewhere i can speak with you more easily so i can send files and such? Thanks for the help by the way

madebr commented 2 years ago

The error is not with your main application, but with the samples built by SDL2_image and others. These are cli apps, not meant for Android. You should configure with -DSDL2IMAGE_SAMPLES=OFF -DSDL2NET_SAMPLES=OFF -DSDL2TTF_SAMPLES=OFF -DSDL2MIXER_SAMPLES=OFF.

libmain.so is your application (libdigivice.so in your case).

So far, you're hitting issues with the cmake build script which we probably should fix here.

Evaghetti commented 2 years ago

The error is not with your main application, but with the samples built by SDL2_image and others. These are cli apps, not meant for Android.

I see, i added those flags you sent, got the same error as before

So far, you're hitting issues with the cmake build script which we probably should fix here.

For now i'm adding the flags to the CMakeLists.txt in the folder app/jni, as such

cmake_minimum_required(VERSION 3.6)

project(GAME)

# armeabi-v7a requires cpufeatures library
# include(AndroidNdkModules)
# android_ndk_import_module_cpufeatures()

option(SDL2IMAGE_INSTALL "" OFF) 
option(SDL2TTF_INSTALL "" OFF) 
option(SDL2NET_INSTALL "" OFF)
option(SDL2IMAGE_SAMPLES "" OFF) 
option(SDL2NET_SAMPLES "" OFF) 
option(SDL2TTF_SAMPLES "" OFF) 
option(SDL2MIXER_SAMPLES "" OFF)
option(SDL2TTF_VENDORED "" ON)

option(BUILD_DIGIVICE "" ON)

# SDL sources are in a subfolder named "SDL"
add_subdirectory(SDL)

# Compilation of companion libraries
add_subdirectory(SDL_image)
#add_subdirectory(SDL_mixer)
add_subdirectory(SDL_ttf)
add_subdirectory(SDL_net)

# Your game and its CMakeLists.txt are in a subfolder named "src"
add_subdirectory(src)

After we get the project up and running i can remove the parts that are relevant to my project and open a PR with these changes, if you think this is enough of a solution.

madebr commented 2 years ago

Be aware that CMake caches option values. If you added option(SDL2IMAGE_SAMPLES "" OFF) after a first configuration, SDL2IMAGE_SAMPLES will still be True. Do this instead

set(SDL2IMAGE_SAMPLES OFF CACHE BOOL "" FORCE)

Can you give the error message? If the error is still with showimage, then you didn't disable building the SDL2_image samples.

Evaghetti commented 2 years ago

Probably i had some options cached from a previous build, changing to these commands you sent did fix the build and it generated an apk, although it crashes, i'm almost certain that it's a problem with my application now, since i didn't change anything from the desktop source to the android build. My final CMakeLists follows:

cmake_minimum_required(VERSION 3.6)

project(GAME)

# armeabi-v7a requires cpufeatures library
# include(AndroidNdkModules)
# android_ndk_import_module_cpufeatures()
set(SDL2IMAGE_INSTALL OFF CACHE BOOL "" FORCE) 
set(SDL2TTF_INSTALL OFF CACHE BOOL "" FORCE) 
set(SDL2NET_INSTALL OFF CACHE BOOL "" FORCE)
set(SDL2IMAGE_SAMPLES OFF CACHE BOOL "" FORCE)
set(SDL2NET_SAMPLES OFF CACHE BOOL "" FORCE) 
set(SDL2TTF_SAMPLES OFF CACHE BOOL "" FORCE) 
set(SDL2MIXER_SAMPLES OFF CACHE BOOL "" FORCE)
set(SDL2TTF_VENDORED ON CACHE BOOL "" FORCE)

option(BUILD_DIGIVICE "" ON)

# SDL sources are in a subfolder named "SDL"
add_subdirectory(SDL)

# Compilation of companion libraries
add_subdirectory(SDL_image)
#add_subdirectory(SDL_mixer)
add_subdirectory(SDL_ttf)
add_subdirectory(SDL_net)

# Your game and its CMakeLists.txt are in a subfolder named "src"
add_subdirectory(src)

Do you want me to open a PR with it? Also, i had to change the CMakeLists.txt for SDL_ttf, it was not compiling because of this line:

set_target_properties(SDL2::ttf PROPERTIES
    INTERFACE_LINK_LIBRARIES "SDL2_ttf"
    DEPRECATION "Use SDL2_ttf::SDL2_ttf or SDL2_ttf::SDL2_ttf-static instead"
)

The error i was getting:

  CMake Error at SDL_ttf/CMakeLists.txt:399 (set_target_properties):
    INTERFACE_LIBRARY targets may only have whitelisted properties.  The
    property "DEPRECATION" is not allowed.

Just removing the whole DEPRECATION section worked, didn't mention it before because i fixed it before talking with you.

madebr commented 2 years ago

I will push fixes to the SDL libraries tomorrow. Their cmake scripts should become smarter and not enable the install targets when included as a subproject. Same goes for the samples.

Good luck with debugging your application :) Make sure to post a link once you feel comfortable with it.

About the deprecation issue, what CMake version are you using? I suppose < 3.17? Looks like an issue which was already fixed in other SDL2_xx libraries but not ported to SDL2_ttf.

Evaghetti commented 2 years ago

Good luck with debugging your application :) Make sure to post a link once you feel comfortable with it.

Thanks :) it is open source actually, i just did not put the SDL side of things to the main branch as of yet, here is the link if you are curious

About the deprecation issue, what CMake version are you using? I suppose < 3.17? Looks like an issue which was already fixed in other SDL2_xx libraries but not ported to SDL2_ttf.

Correct, i'm using 3.16.3, glad to hear it is already fixed then

I will push fixes to the SDL libraries tomorrow. Their cmake scripts should become smarter and not enable the install targets when included as a subproject. Same goes for the samples.

I see, ok then, good luck with that and thank you so much for helping me, was banging my head against the computer for about 3 hours before you showed up! Can i close this issue or do you want me to keep it open so you can reference it later?

madebr commented 2 years ago

I'll close it once I have pushed the fixed to the repo's. It's a reminder that something needs to be fixed :)

madebr commented 2 years ago

Can you remove the build folder, remove all the set(... CACHE BOOL "" FORCE) workarounds, update all the SDL libraries you use to latest master and try again?

Evaghetti commented 2 years ago

Sure, i uninstalled all the stuff that i build before, configured and build it again and removed the stuff from my android project's CMAkeLists, i got the following error:

CMake Error: install(EXPORT "SDL2ImageExports" ...) includes target "SDL2_image" which requires target "SDL2" that is not in any export set.
  CMake Error: install(EXPORT "SDL2NetExports" ...) includes target "SDL2_net" which requires target "SDL2" that is not in any export set.

My current CMakeLists:

cmake_minimum_required(VERSION 3.6)

project(GAME)

# armeabi-v7a requires cpufeatures library
# include(AndroidNdkModules)
# android_ndk_import_module_cpufeatures()

option(BUILD_DIGIVICE "" ON)

# SDL sources are in a subfolder named "SDL"
add_subdirectory(SDL)

# Compilation of companion libraries
add_subdirectory(SDL_image)
#add_subdirectory(SDL_mixer)
add_subdirectory(SDL_ttf)
add_subdirectory(SDL_net)

# Your game and its CMakeLists.txt are in a subfolder named "src"
add_subdirectory(src)

For SDL and SDL_ttf i didn't get any errors, also the DEPRECATION thing didn't happen

madebr commented 2 years ago

Just to be sure, did you you upgrade all libraries including SDL_image and SDL_net to latest master?

The installation target should not be enabled by default since https://github.com/libsdl-org/SDL_image/commit/57274809dec691e0c7477ff4936bb99873434717 The SDL2 target should not be in the export set since https://github.com/libsdl-org/SDL_image/commit/5d9ee78d7117e98721799596395ca69751e0cf13

Evaghetti commented 2 years ago

Just to be sure, did you you upgrade all libraries including SDL_image and SDL_net to latest master?

I thought so, but when i double checked it i saw that i had only pulled SDL and SDL_ttf, after doing so for the rest it compiled and installed the apk without the need to change the CMakeLists, so i guess it's solved Can i close this issue?

madebr commented 2 years ago

I will close it. Good luck with the Android port!

I don't have much experience with Android development, so I can't really help you with that.