SDL2 + CMake + Android (on Windows)

I believe my changes are useful and would like to see them mainlined.
I have successfully been using them to make prebuilt SDL binaries that
I can use in projects, as well as other people using my prebuilt
binaries in their projects. This provides an alternative to embedding
the entire SDL source tree into your project and building world. Build
systems are hard, and Android is particularly bad. And I spent a lot
of time vetting the compiler switches used by the CMake toolchain to
try to match what Android wants to do natively.

But before this should be mainlined, there were some concerns brought
up by Gabriel Jacobo. I was supposed to talk to you or Sam directly,
but I got sidetracked. I wanted to have more real world cases
demonstrating how these things are used, and thus beneficial. It?s
been a long time so my memory is hazy, but I think the crux of the
concerns were my changes to decouple Android application specific
things from the libSDL core. This manifested itself first by shifting
stuff to libSDLmain. But even that has some very per-application stuff
that prevents pre-compiling a libSDLmain, so I think the second thing
was I had to suggest a convention for the user?s main application .so.
There are #ifdef concenssions to try to not break existing behavior
where you compile everything as one gi-normous blob (though they
probably need to be retested since I haven?t touched them in so long).

Anyway, I?m happy to discuss these things in more detail. I want to
make sure everybody is happy before this gets pushed in. You did
happen to catch me at a strange time. I?m trying to get SwiftAndroid
working as we speak. This potentially may stress my changes. I?m
hoping to see that everything still holds without changes.

Thanks,
EricOn 2/21/16, Ryan C. Gordon wrote:

So, as an FYI, I think all these things had been addressed in my
aforementioned AndroidCMake branch.

Having not followed this conversation (sorry!)…should I pull this branch
into the main repo? Is it generally useful at this point?

–ryan.

Any progress on this? I tried compiling SDL from gradle with cmake, but got a bunch of compile errors so I’m guessing the suggested changes were never pulled.

Now that the standard android gradle plugin supports cmake directly it would be nice to finally migrate to cmake on android too.

I tried to build the current SDL main branch also with ndk-build just to be sure the problem is when using cmake. There was a separate problem: the armeabi build was spilling a lot of strange errors when using clang (Same errors that someone was having here: https://stackoverflow.com/questions/42674298/sdl2-sample-build-error-with-android-ndk-r14). Seems that armeabi build with clang is broken at the moment.

I did a little more digging and testing on the cmake problem and I was able to build the branch by Eric Wing with a super simple gradle configuration pretty much directly from android studio. Very nice.

Just by adding something like this to my android studio generated build.gradle:

externalNativeBuild {
    cmake {
        path "../../../libs/SDL_AndroidCMake/CMakeLists.txt"
    }
}

Well. Almost. The build was still giving errors on armeabi-v7a abi:

C:\Users\xxx\AppData\Local\Temp\SDL_spinlock-745b5e.s: Assembler messages:
C:\Users\xxx\AppData\Local\Temp\SDL_spinlock-745b5e.s:53: Error: thumb conditional instruction should be in IT block -- `strexeq r3,r2,[r0]'
    clang.exe: error: assembler command failed with exit code 1 (use -v to see invocation)
    ninja: build stopped: subcommand failed.

After some quick googling I fixed it by adding a build flag “-Wa,-mimplicit-it=thumb” (don’t really know what that actually does, but I just wanted to see if things will compile). The problem with that was that android cmake integration doesn’t allow defining per abi flags. Looking at the source I figured that if I switched to GCC, instead of the default clang, that part of code would not be compiled. So by forcing GCC I was able to produce valid looking libSDL2.so and libSDL2main.so

defaultConfig {
    externalNativeBuild {
        cmake {
            //cFlags "-Wa,-mimplicit-it=thumb"
            arguments "-DANDROID_TOOLCHAIN=gcc"
        }            
    }
}

Seems that SDLs Android.mk adds “.arm” to the end of the file that is causing the error and it’s somehow forcing the file to be compiled in ARM mode instead of THUMB and it makes it work. Should the same thing be done in the cmake build? Or would adding the implicit-it=thumb flag somewhere in the SDL CmakeLists.txt do the trick?

I’m still ramping up on all the issues & shortcomings of the Android
Studio fork of CMake. Even though I’m still ramping up, I’ve already
hit quite a list of roadblocks like this one. (It’s a real shame
Google managed to ignore all the work done by both the open source
community at large on the OpenCV toolchain and the work done by the
official CMake team.)

I don’t think adding the thumb switch globally is the right thing to
do. I think it only makes sense on ARM architectures and not the x86 &
MIPS architectures.

And gcc is also not the right thing. gcc is already deprecated and
Google is trying very hard to completely remove it from the NDK.

I’m not familiar enough with thumb to know if there is another way to
approach this.

But I suspect the per-architecture flags are ultimately the right and
best solution. Even if there is a workaround for this, I suspect we’ll
eventually want those flags for other things. For example, in the
audio thread going on in the list right now, Ryan mentioned a desire
for a NEON backend for the resampler. Unless Android is automatically
making NEON switches the default now, (originally it was not because
originally Google decided to make NEON optional for the armeabi-v7a
architecture which was a terrible mistake), we would need a per-arch
switch for that.

I know Google/Android bug reports often go nowhere, but occasionally a
few get the attention of Google. Is there any traction or ETA when
they might fix this in their CMake fork?

-Eric

Yeah, reverting back to GCC is definitely not a solution. I was just testing things to get stuff to compile. Also I really have little to no knowledge on arm/thumb assembly or why the one file needs to be in ARM mode. Again I was just twiddling with things trying to get SDL to compile.

I think that the per architecture flags are not actually a problem because you can set them on the cmake side. Cmake is called separately for each abi and there are some variables passed in that you can check to see what abi is being built at the moment (https://developer.android.com/ndk/guides/cmake.html). I was just trying to do it directly from the gradle config, because I didn’t want to modify the SDL build files if possible.

There is an issue to make it possible to configure per abi options directly from gradle too: https://issuetracker.google.com/issues/37124186 but like I said, I think all this configuration should be done on the cmake side of things anyway.

But what I could not figure out is a proper way to set the arm mode on a per file basis from cmake. The only way I came up with was adding something like this to SDL/CMakeLists.txt:

if (ANDROID_ABI STREQUAL "armeabi" OR
    ANDROID_ABI STREQUAL "armeabi-v7a" OR
    ANDROID_ABI STREQUAL "armeabi-v7a with NEON")
  set_source_files_properties(${SDL2_SOURCE_DIR}/src/atomic/SDL_spinlock.c PROPERTIES COMPILE_FLAGS -marm)
endif()

The android cmake stuff is defining -mthumb for all compiled source but this adds -marm after that for that one file that overrides the earlier setting. It works but having to override the compiler options directly is not very nice.

I also took a look at the nightmare that is SDLmain. I think that it’s the biggest obstacle currently for making a sane android build env. SDLmain and the app entry point is such a pain to deal with on so many platforms that I kind of wish the whole concept could be reworked.

I looks like the Gradle side has a feature to specify arm mode instead of thumb. Have you tried flipping it to arm?

As for SDLmain and the app entry point, my branch has some changes to make the app entry point more flexible and decoupled. I have a different experiment elsewhere where I even make is overridable in the AndroidManifest.xml which I might bring over some day.

There are also fundamental changes I would like to see in SDLmain, such as a new alternative one people could opt-into that works on the main UI thread and has callback hooks similar to the iOS and Emscripten support SDL has. (The non-main thread issue creates massive headaches the moment you have to start integrating features that touch native UI, plus people currently seem to hit nasty edge case life-cycle bugs with the current background/resume/quit stuff.)

But fundamentally, the concept of SDLmain can’t really go away. Because Android treats the native side as a second class citizen and all apps must originate in Java, there is no real alternative for this.

What things did you have in mind to fix/rework SDLmain?

Maybe I haven’t really thought this though, but if I was starting from scratch I’d maybe dump the whole separate SDL_main library and do something a lot of header only libraries do: basically the user would define something before including sdl in EXACTLY one source file and the include would add the appropriate entry point code there. So on windows a WinMain would be inserted to that file and on android a jni callback and so on.

Usage would be something like:

#define SDL_ENTRY_POINT
#include <SDL.h>

int SDL_Main(int argc, char **argv) {
    return 0;
}

I’d also probably drop abusing int main(int argc, char **argv) because the redefinition seems to just add confusion and I don’t really see the benefit in it.

Now that I think of it, this kind of system would probably be possible to add in addition to the current stuff. So you would just not link to SDL_main if you defined the entry point already like above.

I tried but I don’t think it can be used to change the type for individual files. I created an issue about this: https://issuetracker.google.com/issues/62264618

I cleaned up my testings a bit and put it on github if you want to check it out.

Basically my goal is to create a simple and clean cmake based SDL project template that is crossplatform without so much hassle to setup for each platform.

1 Like

Actually, I was suggesting you try building everything under ARM instead of Thumb.

I kind of doubt SDL is getting any significant benefits from thumb anyway.

I took a stab at fixing SDL CMakeLists to work with android. I looked at the changes in your fork, but decided not to try to merge those back to the current SDL also partly because there already were some related fixes there.

Also I was thinking that maybe the changes could make it to 2.0.6 and maybe it’s better to not do any bigger changes to handling the SDLmain stuff for now to have a better chance at getting the fix pulled and getting at least something working in.

I’d appreciate if you or somebody who has been using cmake with SDL and android took a look if the changes look OK. Mainly because I haven’t used cmake to build android without gradle so I don’t know if the changes would cause any problems to that approach. The current official SDL version was compiling Android_main.c as part of SDL2.so and just had a dummy SDLmain. I’m not sure what the reason for that was, but I changed it and I didn’t see any linking problems.

I updated the github test project linked earlier to use this patched SDL version:
https://github.com/suikki/simpleSDL/blob/master/contrib/android_fixes.patch