Integrating SDL3_ttf Library with CMake on Windows & Ubuntu (SDL_Renderer) Интеграция C++-библиотеки SDL3_ttf с CMake под Windows и Ubuntu (SDL_Renderer)
A step-by-step guide to configuring and integrating the SDL3_ttf satellite library and SDL_Renderer in your CMake projects on Windows and Ubuntu. Пошаговое руководство по настройке и интеграции вспомогательной библиотеки SDL3_ttf и SDL_Renderer в проекты CMake под Windows и Ubuntu.
- Building FreeType Static Library for Windows (MinGW & CMake) Сборка статической библиотеки FreeType для Windows (MinGW и CMake)
- Building FreeType Static Library for Ubuntu (GCC, CMake & Ninja) Сборка статической библиотеки FreeType для Ubuntu (GCC, CMake и Ninja)
- Building SDL3_ttf Static Library for Windows (MinGW & CMake) Сборка статической библиотеки SDL3_ttf для Windows (MinGW и CMake)
- Building SDL3_ttf Static Library for Ubuntu (GCC, CMake & Ninja) Сборка статической библиотеки SDL3_ttf для Ubuntu (GCC, CMake и Ninja)
Step 1: Create Project Directory & Assets Folder Шаг 1: Создание директории проекта и папки ресурсов
Create a workspace folder, a new project directory, and an assets/fonts folder for your font assets:
Создайте рабочую папку, новую директорию проекта и папку assets/fonts для файлов шрифтов:
Windows (Command Prompt / PowerShell)
mkdir C:\projects\sdl3-ttf-test
mkdir C:\projects\sdl3-ttf-test\assets\fonts
cd C:\projects\sdl3-ttf-test
Ubuntu (Terminal)
mkdir -p ~/projects/sdl3-ttf-test/assets/fonts
cd ~/projects/sdl3-ttf-test
liberation-fonts-ttf-x.y.z.tar.gz from GitHub Releases, extract it, and place LiberationSans-Regular.ttf directly inside your assets/fonts/ directory (path: assets/fonts/LiberationSans-Regular.ttf).
Пожалуйста, скачайте liberation-fonts-ttf-x.y.z.tar.gz со страницы GitHub Releases, распакуйте архив и поместите файл LiberationSans-Regular.ttf непосредственно в папку assets/fonts/ (путь: assets/fonts/LiberationSans-Regular.ttf).
Step 2: Create Source Files (main.cpp & CMakeLists.txt) Шаг 2: Создание исходных файлов (main.cpp и CMakeLists.txt)
You can create these files using Notepad / Sublime Text on Windows, or nano in Ubuntu terminal:
Вы можете создать эти файлы через Блокнот / Sublime Text в Windows или с помощью nano в терминале Ubuntu:
Windows (Terminal / Notepad)
notepad main.cpp
notepad CMakeLists.txt
Ubuntu (Terminal / Nano)
nano main.cpp
nano CMakeLists.txt
1A. File Contents for main.cpp (Classic Loop) 1A. Содержимое файла main.cpp (Классический цикл)
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
#include <SDL3_ttf/SDL_ttf.h>
int main(int argc, char* argv[]) {
if (!SDL_Init(SDL_INIT_VIDEO)) {
SDL_Log("SDL Initialization failed: %s", SDL_GetError());
return -1;
}
if (!TTF_Init()) {
SDL_Log("TTF_Init failed: %s", SDL_GetError());
SDL_Quit();
return -1;
}
SDL_Window* window = SDL_CreateWindow("SDL3_ttf Example Window (Classic)", 800, 450, 0);
if (!window) {
SDL_Log("Window creation failed: %s", SDL_GetError());
TTF_Quit();
SDL_Quit();
return -1;
}
SDL_Renderer* renderer = SDL_CreateRenderer(window, NULL);
if (!renderer) {
SDL_Log("Renderer creation failed: %s", SDL_GetError());
SDL_DestroyWindow(window);
TTF_Quit();
SDL_Quit();
return -1;
}
TTF_Font* font = TTF_OpenFont("assets/fonts/LiberationSans-Regular.ttf", 36.0f);
if (!font) {
SDL_Log("Failed to load font: %s", SDL_GetError());
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
TTF_Quit();
SDL_Quit();
return -1;
}
SDL_Color textColor = { 20, 20, 20, 255 };
SDL_Surface* textSurface = TTF_RenderText_Blended(font, "Hello, SDL3_ttf!", 0, textColor);
if (!textSurface) {
SDL_Log("Failed to render text surface: %s", SDL_GetError());
TTF_CloseFont(font);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
TTF_Quit();
SDL_Quit();
return -1;
}
SDL_Texture* textTexture = SDL_CreateTextureFromSurface(renderer, textSurface);
SDL_DestroySurface(textSurface);
if (!textTexture) {
SDL_Log("Failed to create texture from surface: %s", SDL_GetError());
TTF_CloseFont(font);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
TTF_Quit();
SDL_Quit();
return -1;
}
float textWidth = 0.0f;
float textHeight = 0.0f;
SDL_GetTextureSize(textTexture, &textWidth, &textHeight);
SDL_FRect dstRect = {
(800.0f - textWidth) / 2.0f,
(450.0f - textHeight) / 2.0f,
textWidth,
textHeight
};
bool running = true;
while (running) {
SDL_Event event;
while (SDL_PollEvent(&event)) {
if (event.type == SDL_EVENT_QUIT) {
running = false;
}
}
SDL_SetRenderDrawColor(renderer, 230, 245, 235, 255);
SDL_RenderClear(renderer);
SDL_RenderTexture(renderer, textTexture, NULL, &dstRect);
SDL_RenderPresent(renderer);
}
SDL_DestroyTexture(textTexture);
TTF_CloseFont(font);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
TTF_Quit();
SDL_Quit();
return 0;
}
1B. File Contents for main.cpp (SDL3 Callbacks API) 1B. Содержимое файла main.cpp (SDL3 Callbacks API)
#define SDL_MAIN_USE_CALLBACKS 1
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
#include <SDL3_ttf/SDL_ttf.h>
struct AppState {
SDL_Window* window = nullptr;
SDL_Renderer* renderer = nullptr;
TTF_Font* font = nullptr;
SDL_Texture* textTexture = nullptr;
SDL_FRect dstRect = { 0 };
};
SDL_AppResult SDL_AppInit(void** appstate, int argc, char* argv[]) {
if (!SDL_Init(SDL_INIT_VIDEO)) {
SDL_Log("SDL Initialization failed: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
if (!TTF_Init()) {
SDL_Log("TTF_Init failed: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
AppState* state = new AppState();
*appstate = state;
state->window = SDL_CreateWindow("SDL3_ttf Example Window (Callbacks)", 800, 450, 0);
if (!state->window) {
SDL_Log("Window creation failed: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
state->renderer = SDL_CreateRenderer(state->window, NULL);
if (!state->renderer) {
SDL_Log("Renderer creation failed: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
state->font = TTF_OpenFont("assets/fonts/LiberationSans-Regular.ttf", 36.0f);
if (!state->font) {
SDL_Log("Failed to load font: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
SDL_Color textColor = { 20, 20, 20, 255 };
SDL_Surface* textSurface = TTF_RenderText_Blended(state->font, "Hello, SDL3_ttf!", 0, textColor);
if (!textSurface) {
SDL_Log("Failed to render text surface: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
state->textTexture = SDL_CreateTextureFromSurface(state->renderer, textSurface);
SDL_DestroySurface(textSurface);
if (!state->textTexture) {
SDL_Log("Failed to create texture from surface: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
float textWidth = 0.0f;
float textHeight = 0.0f;
SDL_GetTextureSize(state->textTexture, &textWidth, &textHeight);
state->dstRect = {
(800.0f - textWidth) / 2.0f,
(450.0f - textHeight) / 2.0f,
textWidth,
textHeight
};
return SDL_APP_CONTINUE;
}
SDL_AppResult SDL_AppEvent(void* appstate, SDL_Event* event) {
if (event->type == SDL_EVENT_QUIT) {
return SDL_APP_SUCCESS;
}
return SDL_APP_CONTINUE;
}
SDL_AppResult SDL_AppIterate(void* appstate) {
auto* state = static_cast<AppState*>(appstate);
SDL_SetRenderDrawColor(state->renderer, 230, 245, 235, 255);
SDL_RenderClear(state->renderer);
SDL_RenderTexture(state->renderer, state->textTexture, NULL, &state->dstRect);
SDL_RenderPresent(state->renderer);
return SDL_APP_CONTINUE;
}
void SDL_AppQuit(void* appstate, SDL_AppResult result) {
if (appstate) {
auto* state = static_cast<AppState*>(appstate);
if (state->textTexture) {
SDL_DestroyTexture(state->textTexture);
}
if (state->font) {
TTF_CloseFont(state->font);
}
if (state->renderer) {
SDL_DestroyRenderer(state->renderer);
}
if (state->window) {
SDL_DestroyWindow(state->window);
}
delete state;
}
TTF_Quit();
SDL_Quit();
}
Option 1A uses the traditional main() event loop. Option 1B uses the new SDL3 recommended Callbacks API (via SDL_MAIN_USE_CALLBACKS). The Callbacks API hands main loop control over to the OS, preventing window rendering freezes during drag/resize operations and enabling seamless cross-platform support across WebAssembly, iOS, and Android.
Вариант 1A использует традиционный цикл событий main(). Вариант 1B использует новый рекомендуемый в SDL3 Callbacks API (через SDL_MAIN_USE_CALLBACKS). Callbacks API передаёт управление основным циклом операционной системе, что предотвращает зависание рендеринга при перетаскивании или изменении размера окна и обеспечивает нативную кроссплатформенность для WebAssembly, iOS и Android.
2. File Contents for CMakeLists.txt 2. Содержимое файла CMakeLists.txt
cmake_minimum_required(VERSION 3.21)
# Default to Debug if CMAKE_BUILD_TYPE is not set via command line
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Debug")
endif()
project(sdl3_ttf_test CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# -----------------------------------------------------------------------------
# Locate FreeType, SDL3, and SDL3_ttf Packages via Custom Paths
# -----------------------------------------------------------------------------
if(WIN32)
set(freetype_DIR "C:/libs/freetype-2.14.3-mingw/lib/cmake/freetype")
set(FREETYPE_INCLUDE_DIRS "C:/libs/freetype-2.14.3-mingw/include/freetype2")
set(FREETYPE_LIBRARY "C:/libs/freetype-2.14.3-mingw/lib/libfreetype.a")
set(SDL3_DIR "C:/libs/sdl3-3.4.16-mingw/lib/cmake/SDL3")
set(SDL3_ttf_DIR "C:/libs/sdl3-ttf-3.2.2-mingw/lib/cmake/SDL3_ttf")
else()
set(freetype_DIR "$ENV{HOME}/libs/freetype-2.14.3-ubuntu/lib/cmake/freetype")
set(FREETYPE_INCLUDE_DIRS "$ENV{HOME}/libs/freetype-2.14.3-ubuntu/include/freetype2")
set(FREETYPE_LIBRARY "$ENV{HOME}/libs/freetype-2.14.3-ubuntu/lib/libfreetype.a")
set(SDL3_DIR "$ENV{HOME}/libs/sdl3-3.4.16-ubuntu/lib/cmake/SDL3")
set(SDL3_ttf_DIR "$ENV{HOME}/libs/sdl3-ttf-3.2.2-ubuntu/lib/cmake/SDL3_ttf")
endif()
find_package(freetype REQUIRED CONFIG)
find_package(SDL3 REQUIRED CONFIG)
find_package(SDL3_ttf REQUIRED CONFIG)
# -----------------------------------------------------------------------------
# Target Definition
# -----------------------------------------------------------------------------
set(PROJECT_SOURCES
main.cpp
)
add_executable(app ${PROJECT_SOURCES})
# Link SDL3 and SDL3_ttf statically (automatically brings in include dirs and system libraries)
target_link_libraries(app PRIVATE SDL3::SDL3-static SDL3_ttf::SDL3_ttf-static)
# Automatically copy assets directory to output directory post-build
add_custom_command(
TARGET app POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory
${CMAKE_CURRENT_SOURCE_DIR}/assets
$<TARGET_FILE_DIR:app>/assets
)
# -----------------------------------------------------------------------------
# Platform-Specific Compiler & Linker Flags
# -----------------------------------------------------------------------------
if(WIN32)
target_compile_options(app PRIVATE -Os)
target_link_options(app PRIVATE -static -s -static-libgcc)
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
target_link_options(app PRIVATE -mconsole)
else()
target_link_options(app PRIVATE -mwindows)
endif()
endif()
Step 3: Create Build & Execution Scripts Шаг 3: Создание скриптов сборки и запуска
Windows (MinGW / Batch Scripts)
config-exe.bat
cmake -G Ninja -S . -B dist/win
build-exe.bat
cmake --build dist/win
run-exe.bat
@echo off
.\dist\win\app.exe
Run the scripts sequentially in Command Prompt or PowerShell: Последовательно запустите скрипты в командной строке или PowerShell:
config-exe.bat
build-exe.bat
run-exe.bat
Ubuntu (Bash Scripts)
config-bin.sh
#!/usr/bin/env bash
set -e
cmake -G Ninja -S . -B dist/linux
build-bin.sh
#!/usr/bin/env bash
set -e
cmake --build dist/linux
run-bin.sh
#!/usr/bin/env bash
set -e
./dist/linux/app
Grant execute permissions on Ubuntu before running: Предоставьте права на выполнение в Ubuntu перед запуском:
chmod +x config-bin.sh build-bin.sh run-bin.sh
./config-bin.sh
./build-bin.sh
./run-bin.sh
Step 4: Expected Output Шаг 4: Ожидаемый результат
After running the build and execution scripts, a window will appear, displaying the rendered text "Hello, SDL3_ttf!" centered on the screen, with the window title: После запуска скриптов сборки и выполнения появится окно с отображённым текстом "Hello, SDL3_ttf!", выровненным по центру экрана, с заголовком:
SDL3_ttf Example Window (Classic)
or (if using the Callbacks API version): или (если используется версия с Callbacks API):
SDL3_ttf Example Window (Callbacks)
Support 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 Поддержка криптовалютой