Integrating compiled libSDL3.so on Android (OpenGL ES 3.0) Интеграция собранной библиотеки libSDL3.so на Android (OpenGL ES 3.0)
A step-by-step guide to creating a test application, linking your compiled libSDL3.so, rendering a colored triangle using modern OpenGL ES 3.0 in C++, building an APK, and running it on an Android device. Пошаговое руководство по созданию тестового приложения, связыванию собранной библиотеки libSDL3.so, рендерингу цветного треугольника с помощью современного OpenGL ES 3.0 на C++, сборке APK и запуску на Android-устройстве.
Step 1: Download SDL3 Source Code Шаг 1: Скачивание исходного кода SDL3
Check and download the latest release (3.4.18) directly from the official SDL repository on GitHub:
Проверьте и скачайте последнюю версию (3.4.18) напрямую со страницы релизов SDL на GitHub:
Open SDL3 Releases (GitHub) Открыть релизы SDL3 (GitHub) Download SDL3 3.4.18 (.zip) Скачать SDL3 3.4.18 (.zip)
SDL3-3.4.18.zip) from the release assets, not the auto-generated "Source code (zip)" link at the bottom, which lacks pre-generated configuration files.
Обязательно скачивайте основной архив релиза (например, SDL3-3.4.18.zip) из файлов релиза, а не автоматически сгенерированный архив «Source code (zip)», в котором отсутствуют предварительно созданные файлы конфигурации.
Step 2: Copy the Android Template Project Шаг 2: Копирование шаблонного проекта Android
Extract SDL3-3.4.18.zip and locate the ready-to-use Gradle template project in:
Распакуйте SDL3-3.4.18.zip и найдите готовый шаблонный проект Gradle по пути:
SDL3-3.4.18/build-scripts/android-project
Create your new application directory C:\projects\android-app-sdl3-opengl-cpp and copy the android-project folder into it.
Создайте новую директорию приложения C:\projects\android-app-sdl3-opengl-cpp и скопируйте в неё папку android-project.
Step 3: Project Directory Structure Шаг 3: Структура директории проекта
Set up your workspace so it mirrors the following structure: Организуйте рабочую область в соответствии со следующей структурой:
C:\projects\android-app-sdl3-opengl-cpp\
├── android-project\
│ ├── app\
│ │ ├── build.gradle
│ │ └── src\
│ │ └── main\
│ │ ├── AndroidManifest.xml
│ │ └── java\
│ │ └── com\
│ │ └── example\
│ │ └── myapp\
│ │ └── MyActivity.java
│ ├── build.gradle
│ ├── settings.gradle
│ └── gradlew.bat
├── src\
│ └── main.cpp
├── CMakeLists.txt
├── build-android.bat
└── install-android.bat
Step 4: Configure Gradle (app/build.gradle) Шаг 4: Настройка Gradle (app/build.gradle)
Open android-project/app/build.gradle and update it with the following configuration:
Откройте android-project/app/build.gradle и примените следующую конфигурацию:
plugins {
id 'com.android.application'
}
android {
namespace "com.example.myapp"
compileSdkVersion 35
defaultConfig {
applicationId 'com.example.myapp'
minSdkVersion 21
targetSdkVersion 35
versionCode 1
versionName '1.0'
externalNativeBuild {
cmake {
arguments '-DANDROID_STL=c++_shared'
abiFilters 'arm64-v8a'
}
}
}
externalNativeBuild {
cmake {
path '../../CMakeLists.txt'
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
buildFeatures {
prefab false
}
}
dependencies {
implementation 'androidx.appcompat:appcompat:1.5.1'
}
Step 5: Configure AndroidManifest.xml Шаг 5: Настройка AndroidManifest.xml
Open android-project/app/src/main/AndroidManifest.xml and make the following two modifications:
Откройте android-project/app/src/main/AndroidManifest.xml и внесите следующие два изменения:
1. Change the OpenGL ES version from 2.0 to 3.0: Измените версию OpenGL ES с 2.0 на 3.0:
<!-- OpenGL ES 3.0 -->
<uses-feature android:glEsVersion="0x00030000" android:required="true" />
2.
Update android:name inside the <activity> tag from "SDLActivity" to your custom activity:
Замените значение android:name внутри тега <activity> с "SDLActivity" на вашу активность:
<activity
android:name="com.example.myapp.MyActivity"
Step 6: Create MyActivity.java Шаг 6: Создание MyActivity.java
Create android-project/app/src/main/java/com/example/myapp/MyActivity.java. SDL requires loading libraries in dependency order: c++_shared, then SDL3, and finally your native application library main:
Создайте файл android-project/app/src/main/java/com/example/myapp/MyActivity.java. SDL требует загрузки библиотек в порядке зависимостей: сначала c++_shared, затем SDL3, и в конце библиотека приложения main:
package com.example.myapp;
import org.libsdl.app.SDLActivity;
public class MyActivity extends SDLActivity {
@Override
protected String[] getLibraries() {
return new String[] {
"c++_shared",
"SDL3",
"main"
};
}
}
Step 7: Configure CMakeLists.txt Шаг 7: Настройка CMakeLists.txt
Create CMakeLists.txt in the project root directory. It sets the C++20 standard, specifies the ABI-specific include directory and compiled libSDL3.so path, and links OpenGL ES 3.0 (GLESv3) and EGL:
Создайте файл CMakeLists.txt в корневой папке проекта. Он задаёт стандарт C++20, указывает путь к заголовочным файлам для текущего ABI и собранной библиотеке libSDL3.so, а также связывает OpenGL ES 3.0 (GLESv3) и EGL:
cmake_minimum_required(VERSION 3.21)
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release")
endif()
project(myapp CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# -----------------------------------------------------------------------------
# Paths
# -----------------------------------------------------------------------------
set(SDL3_DIR "C:/libs/sdl3-3.4.18-android")
# -----------------------------------------------------------------------------
# Native Shared Library Target
# -----------------------------------------------------------------------------
add_library(main SHARED
src/main.cpp
)
# -----------------------------------------------------------------------------
# Include Directories
# -----------------------------------------------------------------------------
target_include_directories(main PRIVATE
${SDL3_DIR}/${ANDROID_ABI}/include
)
# -----------------------------------------------------------------------------
# Link SDL3 & Android System Libraries
# -----------------------------------------------------------------------------
target_link_libraries(main PRIVATE
${SDL3_DIR}/${ANDROID_ABI}/lib/libSDL3.so
GLESv3
EGL
android
log
)
Step 8: OpenGL ES 3.0 Source Code (src/main.cpp) Шаг 8: Исходный код OpenGL ES 3.0 (src/main.cpp)
Create src/main.cpp. This modern C++ program requests an OpenGL ES 3.0 context, compiles vertex and fragment shaders using #version 300 es, uploads a colored triangle to a VAO/VBO, and renders it in the main loop:
Создайте файл src/main.cpp. Эта программа на современном C++ инициализирует контекст OpenGL ES 3.0, компилирует вершинный и фрагментный шейдеры с #version 300 es, загружает цветной треугольник в VAO/VBO и отрисовывает его в основном цикле:
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
#include <GLES3/gl3.h>
const char* vertexShaderSource =
"#version 300 es\n"
"layout (location = 0) in vec2 aPos;\n"
"layout (location = 1) in vec3 aColor;\n"
"out vec3 vColor;\n"
"void main() {\n"
" gl_Position = vec4(aPos, 0.0, 1.0);\n"
" vColor = aColor;\n"
"}\0";
const char* fragmentShaderSource =
"#version 300 es\n"
"precision mediump float;\n"
"in vec3 vColor;\n"
"out vec4 FragColor;\n"
"void main() {\n"
" FragColor = vec4(vColor, 1.0);\n"
"}\0";
GLuint compileShader(GLenum type, const char* source) {
GLuint shader = glCreateShader(type);
glShaderSource(shader, 1, &source, nullptr);
glCompileShader(shader);
GLint success;
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
if (!success) {
char infoLog[512];
glGetShaderInfoLog(shader, 512, nullptr, infoLog);
SDL_Log("Shader compilation error: %s", infoLog);
}
return shader;
}
int main(int argc, char* argv[]) {
(void)argc;
(void)argv;
if (!SDL_Init(SDL_INIT_VIDEO)) {
SDL_Log("Unable to initialize SDL: %s", SDL_GetError());
return 1;
}
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
SDL_Window* window = SDL_CreateWindow(
"SDL3 OpenGL ES 3.0",
800, 600,
SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE
);
if (!window) {
SDL_Log("Failed to create window: %s", SDL_GetError());
SDL_Quit();
return 1;
}
SDL_GLContext glContext = SDL_GL_CreateContext(window);
if (!glContext) {
SDL_Log("Failed to create OpenGL context: %s", SDL_GetError());
SDL_DestroyWindow(window);
SDL_Quit();
return 1;
}
SDL_GL_SetSwapInterval(1);
GLuint vertexShader = compileShader(GL_VERTEX_SHADER, vertexShaderSource);
GLuint fragmentShader = compileShader(GL_FRAGMENT_SHADER, fragmentShaderSource);
GLuint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
float vertices[] = {
// positions // colors
0.0f, 0.5f, 1.0f, 0.0f, 0.0f, // top (red)
-0.5f, -0.5f, 0.0f, 1.0f, 0.0f, // bottom left (green)
0.5f, -0.5f, 0.0f, 0.0f, 1.0f // bottom right (blue)
};
GLuint VAO, VBO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// Position attribute
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// Color attribute
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(2 * sizeof(float)));
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
bool running = true;
SDL_Event event;
while (running) {
while (SDL_PollEvent(&event)) {
if (event.type == SDL_EVENT_QUIT) {
running = false;
}
}
int w, h;
SDL_GetWindowSizeInPixels(window, &w, &h);
glViewport(0, 0, w, h);
glClearColor(0.12f, 0.12f, 0.15f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shaderProgram);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
SDL_GL_SwapWindow(window);
}
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glDeleteProgram(shaderProgram);
SDL_GL_DestroyContext(glContext);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
Step 9: Build and Installation Scripts Шаг 9: Скрипты сборки и установки
Create build-android.bat in the root folder to compile the project and build the debug APK. Using pushd and popd ensures your command prompt returns to the root directory after building:
Создайте файл build-android.bat в корневой папке для компиляции проекта и сборки debug APK. Использование pushd и popd гарантирует возврат командной строки в корневую папку после сборки:
@echo off
pushd "%~dp0android-project"
call gradlew.bat assembleDebug
popd
Create install-android.bat to install the generated APK on your device or emulator and automatically start the activity:
Создайте файл install-android.bat для установки сгенерированного APK на устройство или эмулятор и автоматического запуска активности:
@echo off
set APK_PATH=%~dp0android-project\app\build\outputs\apk\debug\app-debug.apk
echo [*] Installing APK to device...
adb install -r "%APK_PATH%"
if errorlevel 1 (
echo [!] Installation failed.
exit /b 1
)
echo [*] Launching application...
adb shell am start -n com.example.myapp/com.example.myapp.MyActivity
Step 10: Build and Run Шаг 10: Сборка и запуск
Run the build script from your project root: Запустите скрипт сборки из корня проекта:
build-android.bat
Connect your Android device with USB debugging enabled, then run the installer directly from the same terminal: Подключите Android-устройство с включённой отладкой по USB и запустите установку прямо из этого же окна:
install-android.bat
You should see the application start in landscape mode, rendering a smooth colored triangle on top of an OpenGL ES 3.0 context. Приложение запустится в альбомной ориентации, отображая цветной треугольник на базе контекста OpenGL ES 3.0.
Complete source code for this project is available on GitHub: Полный исходный код проекта доступен на GitHub:
View on GitHub Смотреть на GitHubSupport My Work Поддержать проект
If these tutorials helped you, consider buying me a coffee! Если эти туториалы вам помогли, вы можете поддержать автора.
Sberbank (Russia only) Сбербанк (только для РФ)
Direct transfer via phone number (Russia only) Перевод по номеру телефона (только для РФ)
USDT TRC20
Support via Cryptocurrency Поддержка криптовалютой