How to add OpenGL ES to C++ project with SDL3 that compiles with Gradle for Android

Hello,

I found this example: sdl3-sample that compiles with Gradle for Android. I built it and run on Android (on emulator and physical device). But now I can change rendering from SDL3 to OpenGL ES. I made it for Desktop without Gradle. Now I want to build it with Gradle.

At first I see that OpenGL ES was added in AndroidManifest.xml:

I try to build the example (see the main.cpp below) with the gradlew assembleDebug command in the directory sdl3-sample/SDL/android-project. I have these error:

C/C++: E:/_Projects/SDL3/sdl3-sample/src/main.cpp:38: error: undefined reference to 'glClearColor'
C/C++: E:/_Projects/SDL3/sdl3-sample/src/main.cpp:39: error: undefined reference to 'glClear'

This is the linker errors. I need to say to Gradle where to find the OpenGL. This is full log and the code example:

Log:

E:\_Projects\SDL3\sdl3-sample\SDL\android-project>gradlew assembleDebug

> Configure project :app
[CXX5202] This app only has 32-bit [armeabi-v7a] native libraries. Beginning August 1, 2019 Google Play store requires that all apps that include native libraries must provide 64-bit versions. For more information, visit https://g.co/64-bit-requirement
[CXX5202] This app only has 32-bit [armeabi-v7a] native libraries. Beginning August 1, 2019 Google Play store requires that all apps that include native libraries must provide 64-bit versions. For more information, visit https://g.co/64-bit-requirement
WARNING:[CXX5202] This app only has 32-bit [armeabi-v7a] native libraries. Beginning August 1, 2019 Google Play store requires that all apps that include native libraries must provide 64-bit versions. For more information, visit https://g.co/64-bit-requirement
[CXX5202] This app only has 32-bit [armeabi-v7a] native libraries. Beginning August 1, 2019 Google Play store requires that all apps that include native libraries must provide 64-bit versions. For more information, visit https://g.co/64-bit-requirement
WARNING:[CXX5202] This app only has 32-bit [armeabi-v7a] native libraries. Beginning August 1, 2019 Google Play store requires that all apps that include native libraries must provide 64-bit versions. For more information, visit https://g.co/64-bit-requirement
[CXX5202] This app only has 32-bit [armeabi-v7a] native libraries. Beginning August 1, 2019 Google Play store requires that all apps that include native libraries must provide 64-bit versions. For more information, visit https://g.co/64-bit-requirement
Warning: unexpected element (uri:"", local:"base-extension"). Expected elements are <{}codename>,<{}layoutlib>,<{}api-level>

> Task :app:buildCMakeDebug FAILED
C/C++: ninja: Entering directory `E:\_Projects\SDL3\sdl3-sample\SDL\android-project\app\.cxx\Debug\3oy3nw31\armeabi-v7a'
C/C++: E:/_Projects/SDL3/sdl3-sample/src/main.cpp:44: error: undefined reference to 'glClearColor'
C/C++: E:/_Projects/SDL3/sdl3-sample/src/main.cpp:45: error: undefined reference to 'glClear'
C/C++: clang++: error: linker command failed with exit code 1 (use -v to see invocation)

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:buildCMakeDebug'.
> Build command failed.
  Error while executing process ninja.exe with arguments {-C E:\_Projects\SDL3\sdl3-sample\SDL\android-project\app\.cxx\Debug\3oy3nw31\armeabi-v7a SDL3-shared main}
  ninja: Entering directory `E:\_Projects\SDL3\sdl3-sample\SDL\android-project\app\.cxx\Debug\3oy3nw31\armeabi-v7a'
  [1/1] Linking CXX shared library Debug\libmain.so
  FAILED: Debug/libmain.so
  C:\Windows\system32\cmd.exe /C "cd . && E:\AppData\Android\SDK\ndk\21.4.7075529\toolchains\llvm\prebuilt\windows-x86_64\bin\clang++.exe --target=armv7-none-linux-androideabi16 --gcc-toolchain=E:/AppData/Android/SDK/ndk/21.4.7075529/toolchains/llvm/prebuilt/windows-x86_64 --sysroot=E:/AppData/Android/SDK/ndk/21.4.7075529/toolchains/llvm/prebuilt/windows-x86_64/sysroot -fPIC -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 -shared -Wl,-soname,libmain.so -o Debug\libmain.so CMakeFiles/main.dir/src/main.cpp.o  Debug/libSDL3.so  -latomic -lm && cd ."
  E:/_Projects/SDL3/sdl3-sample/src/main.cpp:44: error: undefined reference to 'glClearColor'
  E:/_Projects/SDL3/sdl3-sample/src/main.cpp:45: error: undefined reference to 'glClear'
  clang++: error: linker command failed with exit code 1 (use -v to see invocation)
  ninja: build stopped: subcommand failed.



* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 5s
14 actionable tasks: 2 executed, 12 up-to-date

main.cpp

#include <iostream>
#include <SDL.h>
#include <cmath>

// #include <SDL_opengles2.h>
#include "egl.h"
#include "glext.h"
#include "gl.h"
#include "glplatform.h"

#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)
//On UWP, we need to not have SDL_main otherwise we'll get a linker error
#define SDL_MAIN_HANDLED
#endif
#include <SDL_main.h>
#if __EMSCRIPTEN__
#include <emscripten.h>
#endif

void SDL_Fail(){
    SDL_LogError(SDL_LOG_CATEGORY_CUSTOM, "Error %s", SDL_GetError());
    exit(1);
}

static bool app_quit = false;
SDL_Window* window = nullptr;

void main_loop() {
    // Get events. If you are making a game, you probably want SDL_PollEvent instead of SDL_WaitEvent.
    // you cannot use WaitEvent on Emscripten, because you cannot block the main thread there.

    SDL_Event event;
    while (SDL_PollEvent(&event)) {
        if (event.type == SDL_EVENT_QUIT)
            app_quit = true;
        break;
    }

    // draw a color
    auto time = SDL_GetTicks() / 1000.f;
    auto red = (std::sin(time) + 1) / 2.0;
    auto green = (std::sin(time / 2) + 1) / 2.0;
    auto blue = (std::sin(time) * 2 + 1) / 2.0;
    glClearColor(red, green, blue, 1.f);
    glClear(GL_COLOR_BUFFER_BIT);

    SDL_GL_SwapWindow(window);
}

// Note: your main function __must__ take this form, otherwise on nonstandard platforms (iOS, etc), your app will not launch.
int main(int argc, char* argv[]){
    
    // init the library, here we make a window so we only need the Video capabilities.
    if (SDL_Init(SDL_INIT_VIDEO)){
        SDL_Fail();
    }
    
    // create a window
    SDL_Window* window = SDL_CreateWindow("Window", 352, 430, SDL_WINDOW_OPENGL);
    if (!window){
        SDL_Fail();
    }

    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
    SDL_GLContext glContext = SDL_GL_CreateContext(window);
    if (!glContext)
    {
        SDL_Fail();
    }

    // print some information about the window
    SDL_ShowWindow(window);
    {
        int width, height, bbwidth, bbheight;
        SDL_GetWindowSize(window, &width, &height);
        SDL_GetWindowSizeInPixels(window, &bbwidth, &bbheight);
        SDL_Log("Window size: %ix%i", width, height);
        SDL_Log("Backbuffer size: %ix%i", bbwidth, bbheight);
        if (width != bbwidth){
            SDL_Log("This is a highdpi environment.");
        }
    }
    
    SDL_Log("Application started successfully!");
    
#if __EMSCRIPTEN__
    // on Emscripten, we cannot have an infinite loop in main. Instead, we must
    // tell emscripten to call our main loop.
    emscripten_set_main_loop(main_loop, 0, 1);
#else
    while (!app_quit) {
        main_loop();
    }
#endif

    // cleanup everything at the end
#if !__EMSCRIPTEN__
    // SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    SDL_Quit();
    SDL_Log("Application quit successfully!");
#endif
    return 0;
}

The problem is not related to Gradle. I added some libraries to CMakeLists.txt and the gradlew assembleDebug works:

CMakeLists.txt

target_link_libraries(${EXECUTABLE_NAME} PUBLIC SDL3::SDL3 android EGL GLESv2)

Cross-refs: