mirror of
https://github.com/libsdl-org/SDL.git
synced 2026-04-26 03:18:47 +02:00
* dos: Some initial work. * dos: Turn off buffer on stdio SDL_IOStreams. Seeking breaks otherwise. We might be able to just fflush() before or seeking instead? * dos: Audio implementation using the Sound Blaster 16. * dos: remove audio Pump interface. Turns out DosBox-X was having trouble with the Sound Blaster or something; standard DosBox works correctly directly from the interrupt handler, and without doubling the buffer size. * dos: just dump and restore the stdio buffer when seeking. This is MUCH faster than just leaving buffering disabled, and also works around getting bogus reads after an fseek. SDL_LoadWAV on test/sample.wav no longer takes several seconds to finish, and comes up with the correct data. I wonder if we're triggering this in LoadWAV because we're malloc'ing data between seeks/reads, and it's causing the djgpp transfer buffer to change. Or maybe the Fat DS trick is confusing it? I don't know, I haven't had time to debug it, it might just be a legit libc bug in djgpp too, for all I know. * dos: Protect audio device "thread" iterations when streams are locked. This uses an old trick we used in SDL 1.2 for MacOS Classic, which did its audio callback in a hardware interrupt. If the audio is locked when the interrupt fires, make a note of it and return immediately. When the lock is released, if the interrupt has been fired, run the audio device iteration right then. Since there isn't a big device lock in SDL3 (available to the app, at least), this keeps a counter of when any SDL_AudioStream is locked, which is probably good enough. * dos: Implemented initial video subsystem. This uses VESA interfaces to manage the display and works with the software renderer. Events aren't hooked up yet, so prepare to close DosBox on each run. :) * dos: Whoops, forgot to add these to revision control. Core and Main support. * dos: Wired up basic filesystem support. This gets most of the rendering examples, which use SDL_GetBasePath() to find textures to load, working. * dos: Fixed compiler warning. * dos: Initial mouse support! * dos: Move interrupt hooking code into core/dos. * dos: Initial keyboard support! * dos: Use a simple ring buffer for keyboard events. Of course Quake 1 solved this better, haha. It's smart: less memory, dirt simple, and you don't even have to worry about synchronizing with the interrupt handler, because it's safe for both sides no matter when an interrupt fires. * ci: add djgpp job [sdl-ci-filter djgpp] [sdl-ci-artifacts] * dos: Fix build issues after rebase onto current main - SDL_runapp.c: Add SDL_PLATFORM_DOS to the exclusion list so the generic SDL_RunApp() is disabled when the DOS-specific one is compiled. - SDL.c: Exclude SDL_Gtk_Quit() on DOS. DJGPP defines __unix__ which sets SDL_PLATFORM_UNIX, but DOS has no GTK/display server. The GTK source is not compiled (CMake UNIX is false for DOS) so this was a link error. - sdlplatform.cmake: Add DOS case to SDL_DetectCMakePlatform so the platform is properly detected from CMAKE_SYSTEM_NAME=DOS. - i586-pc-msdosdjgpp.cmake: Add i386-pc-msdosdjgpp-gcc as a fallback compiler name, since some DJGPP toolchain builds use the i386 prefix. * Add 8-bit palette support to DOS VESA driver * Add VBE page-flipping, state restore, and robust keyboard handling - Implement double-buffered page-flipping for VBE modes with >1 image page - Save and restore full VBE state on video init/quit for clean mode switching - Improve DOS keyboard handling: support extended scancodes and Pause key - Lock ISR code/data to prevent page faults during interrupts - Always vsync when blitting in single-buffered modes to reduce tearing * Refactor Sound Blaster audio mixing to main loop Move audio mixing out of IRQ handler to main loop for improved stability and to avoid reentrancy issues. Add SDL_DOS_PumpAudio function, update DMA buffer handling, and adjust sample rate to 22050 Hz. Silence stale DMA buffer halves to prevent stutter during load. * Add DOS timer support and update build config * Add support for pre-SB16 8-bit mono Sound Blaster audio Detect SB version and select 8-bit mono or 16-bit stereo mode. Handle DMA and DSP setup for both SB16 and pre-SB16 hardware. Add FORCE_SB_8BIT option for testing in DOSBox. * Add SB Pro stereo support and simplify IRQ handler * Add DOS joystick driver support * Improve DOS hardware handling and clarify memory allocation - Poll Sound Blaster DSP status instead of fixed delay after speaker-on - Clarify DPMI conventional memory is always locked; update comments - Document and justify DMA memory allocation strategy - Free IRET wrapper after restoring interrupt vector to avoid leaks - Throttle joystick axis polling to ~60 Hz to reduce BIOS timing loop cost - Always poll joystick buttons directly for responsiveness * Query and use mouse sensitivity from INT 33h function 0x1B * Add support for VESA banked framebuffer modes Implement banked framebuffer access for VBE 1.2+ modes without LFB. Detect and initialize banked modes, copy framebuffer data using bank switching, and blank the framebuffer on mode set. Page-flipping is disabled in banked mode. * Add optional vsync to page flipping in DOS VESA driver * Add cooperative threading support for DOS platform * Move SoundBlaster audio mixing to SDL audio thread * Fix DOS platform comments and workarounds for DJGPP support * Fix SoundBlaster IRQ handling and DMA setup for DOS - Pass IRQ number to DOS_EndOfInterrupt and handle slave PIC EOI - Validate DMA channel from BLASTER variable - Correct DMA page register selection for SB16 - Improve BLASTER variable parsing and error messages - Unmask/mask IRQs on correct PIC in DOS_HookInterrupt - Rename SDL_dosjoystick.c to SDL_sysjoystick.c - Include SDL_main_callbacks.h in SDL_sysmain_runapp.c - Add include guard to SDL_systhread_c.h * Add DOS platform options and preseed cache for DJGPP Disable unsupported SDL features when building for DOS. Add PreseedDOSCache.cmake to pre-populate CMake cache variables for DJGPP. * cmake: use a 8.3 naming scheme for tests on DOS * Apply code style * Update include/SDL3/SDL_platform_defines.h Co-authored-by: Anonymous Maarten <madebr@users.noreply.github.com> * Code review clean up - Split DOS VESA mode-setting into its own file - Replace magic numbers with named constants - Update copyright dates to 2026 - Substract time taken by other threads form delays * Fix DOS bugs and improve compatibility - Disable fseeko64 for DJGPP due to broken implementation - Refactor DOS timer delay to always yield and avoid busy-waiting - Fix animated cursor rendering in DOS VESA backend - Always set display mode when creating DOS VESA window - Work around DJGPP allowing invalid file access in testfile.c - Bump max threads to 16 - Apply workarounds for threading tests * Add DOS platform documentation and fix a few issues - Fix fullscreen default resolution - Improve best mode matching - Fix builds on GCC older than 7.0 - Fix text input events * Fix keyboard mapping of "*" * Fix running, and existing, under PCem * Apply suggestions from code review Co-authored-by: Cameron Cawley <ccawley2011@gmail.com> * Pre-mix audio in ring buffer and copy to DMA via IRQ thread * Video fixes and optimizations * DOS: Fix Intel 740 and VGA compatability * DOS: Update readme * DOS: Fix thread ID, get GPU name * DOS: Cap mouse range * DOS: Map test resources to 8.3 names * DOS: Skip unsupported WM color modes * Fix "windowed" resolution selection * DOS: Hide INDEX8 modes behind SDL_DOS_ALLOW_INDEX8_MODES * Remove SDL_HINT_DOS_ALLOW_INDEX8_MODES and order modes logically * Don't convert cursor if dest is not INDEX8 --------- Co-authored-by: Ryan C. Gordon <icculus@icculus.org> Co-authored-by: Anonymous Maarten <anonymous.maarten@gmail.com> Co-authored-by: Cameron Cawley <ccawley2011@gmail.com> Co-authored-by: Gleb Mazovetskiy <glex.spb@gmail.com> Co-authored-by: Jay Petacat <jay@jayschwa.net> Tested-by: Cameron Cawley <ccawley2011@gmail.com>
915 lines
44 KiB
CMake
915 lines
44 KiB
CMake
#
|
|
# CMake script for building the SDL tests
|
|
#
|
|
|
|
cmake_minimum_required(VERSION 3.16)
|
|
|
|
if(NOT DEFINED CMAKE_C_STANDARD)
|
|
set(CMAKE_C_STANDARD 99)
|
|
endif()
|
|
|
|
set(SDL3_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/..")
|
|
|
|
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../cmake")
|
|
|
|
include(CheckIncludeFile)
|
|
include(CheckStructHasMember)
|
|
include(CMakePushCheckState)
|
|
include(sdlcompilers)
|
|
|
|
find_package(Python3 COMPONENTS Interpreter)
|
|
if(NOT PYTHON3_EXECUTABLE)
|
|
set(PYTHON3_EXECUTABLE "python3")
|
|
endif()
|
|
|
|
if(SDL_TESTS_LINK_SHARED)
|
|
set(sdl_name_component SDL3-shared)
|
|
else()
|
|
set(sdl_name_component SDL3-static)
|
|
endif()
|
|
set(HAVE_TESTS_LINK_SHARED "${SDL_TESTS_LINK_SHARED}" PARENT_SCOPE)
|
|
|
|
# CMake incorrectly detects opengl32.lib being present on MSVC ARM64
|
|
if(NOT (MSVC AND SDL_CPU_ARM64))
|
|
# Prefer GLVND, if present
|
|
set(OpenGL_GL_PREFERENCE GLVND)
|
|
find_package(OpenGL)
|
|
endif()
|
|
|
|
add_library(sdltests_utils OBJECT
|
|
testutils.c
|
|
)
|
|
target_link_libraries(sdltests_utils PRIVATE SDL3::Headers)
|
|
|
|
file(GLOB RESOURCE_FILES *.png *.wav *.csv *.hex moose.dat utf8.txt)
|
|
|
|
option(SDLTEST_TRACKMEM "Run tests with --trackmem" OFF)
|
|
|
|
if(WIN32)
|
|
option(SDLTEST_PROCDUMP "Run tests using sdlprocdump for minidump generation" OFF)
|
|
add_executable(sdlprocdump win32/sdlprocdump.c)
|
|
SDL_AddCommonCompilerFlags(sdlprocdump)
|
|
if(SDLTEST_PROCDUMP)
|
|
set(CMAKE_TEST_LAUNCHER "$<TARGET_FILE:sdlprocdump>;--")
|
|
else()
|
|
set_property(TARGET sdlprocdump PROPERTY EXCLUDE_FROM_ALL "1")
|
|
endif()
|
|
else()
|
|
option(SDLTEST_GDB "Run tests using headless gdb" OFF)
|
|
find_program(GDB_BIN NAMES "gdb")
|
|
if(SDLTEST_GDB AND GDB_BIN)
|
|
set(CMAKE_TEST_LAUNCHER "${GDB_BIN};-batch;-nx;-x;${CMAKE_CURRENT_SOURCE_DIR}/unix/gdbcmds.txt;--args")
|
|
endif()
|
|
endif()
|
|
|
|
if(EMSCRIPTEN)
|
|
set(SDLTEST_BROWSER "firefox" CACHE STRING "Browser in which to run SDL unit tests (chrome or firefox)")
|
|
set(SDLTEST_PORT "8080" CACHE STRING "Port on which to serve the tests")
|
|
set(SDLTEST_CHROME_BINARY "" CACHE STRING "Chrome/Chromium browser binary (optional)")
|
|
if(TARGET Python3::Interpreter)
|
|
add_custom_target(serve-sdl-tests
|
|
COMMAND Python3::Interpreter "${CMAKE_CURRENT_SOURCE_DIR}/emscripten/server.py"
|
|
"${SDLTEST_PORT}"
|
|
-d "${CMAKE_CURRENT_BINARY_DIR}"
|
|
--map "${SDL3_SOURCE_DIR}:/SDL")
|
|
endif()
|
|
endif()
|
|
|
|
if(CMAKE_RUNTIME_OUTPUT_DIRECTORY)
|
|
set(test_bin_dir "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}")
|
|
if(NOT IS_ABSOLUTE "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}")
|
|
set(test_bin_dir "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_RUNTIME_OUTPUT_DIRECTORY}")
|
|
endif()
|
|
else()
|
|
set(test_bin_dir "${CMAKE_CURRENT_BINARY_DIR}")
|
|
endif()
|
|
if(NOT CMAKE_VERSION VERSION_LESS 3.20)
|
|
get_property(is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
|
|
set(test_bin_dir "${test_bin_dir}$<$<BOOL:${is_multi_config}>:/$<CONFIG>>")
|
|
endif()
|
|
|
|
if(DOS)
|
|
set(NAME83_LONG "unifont-15.1.05.hex;unifont-15.1.05-license.txt;physaudiodev.png;logaudiodev.png;audiofile.png;soundboard.png;soundboard_levels.png;trashcan.png;msdf_font.png;msdf_font.csv;gamepad_front.png;gamepad_back.png;gamepad_face_abxy.png;gamepad_face_axby.png;gamepad_face_bayx.png;gamepad_face_sony.png;gamepad_battery.png;gamepad_battery_unknown.png;gamepad_battery_wired.png;gamepad_touchpad.png;gamepad_button.png;gamepad_button_small.png;gamepad_button_background.png;gamepad_axis.png;gamepad_axis_arrow.png;gamepad_wired.png;gamepad_wireless.png;sdl-test_round.png")
|
|
set(DOS83_SHORT "UNIFONT.HEX;UNIFONTL.TXT;PHYSADEV.PNG;LOGADEV.PNG;AUDIOFIL.PNG;SNDBRD.PNG;SNDLVL.PNG;TRASHCAN.PNG;MSDFFONT.PNG;MSDFFONT.CSV;GP_FRONT.PNG;GP_BACK.PNG;GP_FABXY.PNG;GP_FAXBY.PNG;GP_FBAYX.PNG;GP_FSONY.PNG;GP_BATT.PNG;GP_BATTX.PNG;GP_BATTW.PNG;GP_TOUCH.PNG;GP_BTN.PNG;GP_BTNSM.PNG;GP_BTNBG.PNG;GP_AXIS.PNG;GP_AXARW.PNG;GP_WIRED.PNG;GP_WLESS.PNG;SDLROUND.PNG")
|
|
endif()
|
|
|
|
set(RESOURCE_FILE_NAMES)
|
|
set(RESOURCE_FILES_BINDIR)
|
|
foreach(resource_file IN LISTS RESOURCE_FILES)
|
|
get_filename_component(res_file_name ${resource_file} NAME)
|
|
set(output_name "${res_file_name}")
|
|
if(DOS)
|
|
list(FIND DOS83_LONG "${res_file_name}" _dos83_idx)
|
|
if(NOT _dos83_idx EQUAL -1)
|
|
list(GET DOS83_SHORT ${_dos83_idx} output_name)
|
|
endif()
|
|
endif()
|
|
list(APPEND RESOURCE_FILE_NAMES "${output_name}")
|
|
set(resource_file_bindir "${test_bin_dir}/${output_name}")
|
|
set(depends_resource_file "${resource_file}")
|
|
if(PROJECT_SOURCE_DIR STREQUAL PROJECT_BINARY_DIR)
|
|
set(depends_resource_file "${CMAKE_CURRENT_LIST_FILE}")
|
|
endif()
|
|
add_custom_command(OUTPUT "${resource_file_bindir}"
|
|
COMMAND "${CMAKE_COMMAND}" -E copy "${resource_file}" "${resource_file_bindir}"
|
|
DEPENDS "${depends_resource_file}"
|
|
)
|
|
list(APPEND RESOURCE_FILES_BINDIR "${resource_file_bindir}")
|
|
endforeach()
|
|
add_custom_target(copy-sdl-test-resources
|
|
DEPENDS "${RESOURCE_FILES_BINDIR}"
|
|
)
|
|
|
|
define_property(TARGET PROPERTY SDL_NONINTERACTIVE BRIEF_DOCS "If true, target is a non-interactive test executable." FULL_DOCS "If true, target is a noninteractive test executable.")
|
|
define_property(TARGET PROPERTY SDL_NONINTERACTIVE_ARGUMENTS BRIEF_DOCS "Argument(s) to run executable in non-interactive mode." FULL_DOCS "Argument(s) to run executable in non-interactive mode.")
|
|
define_property(TARGET PROPERTY SDL_NONINTERACTIVE_TIMEOUT BRIEF_DOCS "Timeout for noninteractive executable." FULL_DOCS "Timeout for noninteractive executable.")
|
|
|
|
if(HAVE_X11)
|
|
find_package(X11 QUIET)
|
|
if(NOT TARGET X11::X11)
|
|
set(HAVE_X11 OFF)
|
|
endif()
|
|
endif()
|
|
|
|
if(HAVE_WAYLAND)
|
|
find_package(PkgConfig QUIET)
|
|
pkg_check_modules(PkgWaylandClient QUIET IMPORTED_TARGET wayland-client)
|
|
if(NOT TARGET PkgConfig::PkgWaylandClient)
|
|
set(HAVE_WAYLAND OFF)
|
|
endif()
|
|
endif()
|
|
|
|
function(add_sdl_test_executable TARGET)
|
|
cmake_parse_arguments(AST "BUILD_DEPENDENT;NONINTERACTIVE;NEEDS_RESOURCES;TESTUTILS;THREADS;MAIN_CALLBACKS;NOTRACKMEM" "NAME83" "DEPENDS;DISABLE_THREADS_ARGS;NONINTERACTIVE_TIMEOUT;NONINTERACTIVE_ARGS;INSTALLED_ARGS;SOURCES" ${ARGN})
|
|
if(AST_UNPARSED_ARGUMENTS)
|
|
message(FATAL_ERROR "Unknown argument(s): ${AST_UNPARSED_ARGUMENTS}")
|
|
endif()
|
|
if(NOT AST_SOURCES)
|
|
message(FATAL_ERROR "add_sdl_test_executable needs at least one source")
|
|
endif()
|
|
if(AST_TESTUTILS)
|
|
list(APPEND AST_SOURCES $<TARGET_OBJECTS:sdltests_utils>)
|
|
endif()
|
|
set(EXTRA_SOURCES "")
|
|
if(AST_NEEDS_RESOURCES)
|
|
list(APPEND EXTRA_SOURCES ${RESOURCE_FILES})
|
|
endif()
|
|
if(ANDROID)
|
|
add_library(${TARGET} SHARED ${AST_SOURCES} ${EXTRA_SOURCES})
|
|
else()
|
|
add_executable(${TARGET} ${AST_SOURCES} ${EXTRA_SOURCES})
|
|
endif()
|
|
target_compile_definitions(${TARGET} PRIVATE HAVE_BUILD_CONFIG)
|
|
SDL_AddCommonCompilerFlags(${TARGET})
|
|
target_include_directories(${TARGET} PRIVATE "${SDL3_SOURCE_DIR}/src/video/khronos")
|
|
target_link_libraries(${TARGET} PRIVATE SDL3::SDL3_test SDL3::${sdl_name_component})
|
|
if(AST_DEPENDS)
|
|
add_dependencies(${TARGET} ${AST_DEPENDS})
|
|
endif()
|
|
|
|
set_propertY(TARGET ${TARGET} PROPERTY SDL_INSTALL "1")
|
|
set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" APPEND PROPERTY SDL_TEST_EXECUTABLES "${TARGET}")
|
|
set_property(TARGET ${TARGET} PROPERTY SDL_NOTRACKMEM ${AST_NOTRACKMEM})
|
|
if(AST_NONINTERACTIVE)
|
|
set_property(TARGET ${TARGET} PROPERTY SDL_NONINTERACTIVE 1)
|
|
endif()
|
|
set_property(TARGET ${TARGET} PROPERTY SDL_DISABLE_THREADS_ARGS "${AST_DISABLE_THREADS_ARGS}")
|
|
set_property(TARGET ${TARGET} PROPERTY SDL_THREADS "${AST_THREADS}")
|
|
if(AST_NONINTERACTIVE_ARGS)
|
|
set_property(TARGET ${TARGET} PROPERTY SDL_NONINTERACTIVE_ARGUMENTS "${AST_NONINTERACTIVE_ARGS}")
|
|
endif()
|
|
if(AST_INSTALLED_ARGS)
|
|
set_property(TARGET ${TARGET} PROPERTY SDL_INSTALLED_ARGUMENTS "${AST_INSTALLED_ARGS}")
|
|
elseif(AST_NONINTERACTIVE_ARGS)
|
|
set_property(TARGET ${TARGET} PROPERTY SDL_INSTALLED_ARGUMENTS "${AST_NONINTERACTIVE_ARGS}")
|
|
endif()
|
|
if(AST_NONINTERACTIVE_TIMEOUT)
|
|
set_property(TARGET ${TARGET} PROPERTY SDL_NONINTERACTIVE_TIMEOUT "${AST_NONINTERACTIVE_TIMEOUT}")
|
|
endif()
|
|
if(AST_NEEDS_RESOURCES)
|
|
if(PSP OR PS2 OR N3DS)
|
|
add_custom_command(TARGET ${TARGET} POST_BUILD
|
|
COMMAND ${CMAKE_COMMAND} ARGS -E make_directory $<TARGET_FILE_DIR:${TARGET}>/sdl-${TARGET}
|
|
COMMAND ${CMAKE_COMMAND} ARGS -E copy_if_different ${RESOURCE_FILES} $<TARGET_FILE_DIR:${TARGET}>/sdl-${TARGET})
|
|
else()
|
|
add_dependencies(${TARGET} copy-sdl-test-resources)
|
|
endif()
|
|
if(APPLE)
|
|
# Make sure resource files get installed into macOS/iOS .app bundles.
|
|
set_target_properties(${TARGET} PROPERTIES RESOURCE "${RESOURCE_FILES}")
|
|
endif()
|
|
if(EMSCRIPTEN)
|
|
foreach(res IN LISTS RESOURCE_FILES)
|
|
get_filename_component(res_name "${res}" NAME)
|
|
target_link_options(${TARGET} PRIVATE "SHELL:--embed-file ${res}@${res_name}")
|
|
set_property(TARGET ${TARGET} APPEND PROPERTY LINK_DEPENDS "${res}")
|
|
endforeach()
|
|
endif()
|
|
set_property(TARGET ${TARGET} APPEND PROPERTY ADDITIONAL_CLEAN_FILES "$<TARGET_FILE_DIR:${TARGET}>/$<JOIN:${RESOURCE_FILE_NAMES},$<SEMICOLON>$<TARGET_FILE_DIR:${TARGET}>/>")
|
|
endif()
|
|
if(AST_BUILD_DEPENDENT)
|
|
target_include_directories(${TARGET} BEFORE PRIVATE $<TARGET_PROPERTY:SDL3::${sdl_name_component},INCLUDE_DIRECTORIES>)
|
|
target_include_directories(${TARGET} BEFORE PRIVATE ${SDL3_SOURCE_DIR}/src)
|
|
if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.20")
|
|
target_include_directories(${TARGET} AFTER PRIVATE "${SDL3_SOURCE_DIR}/include/build_config")
|
|
endif()
|
|
endif()
|
|
|
|
if(WINDOWS)
|
|
# CET support was added in VS 16.7
|
|
if(MSVC_VERSION GREATER 1926 AND CMAKE_GENERATOR_PLATFORM MATCHES "Win32|x64")
|
|
set_property(TARGET ${TARGET} APPEND_STRING PROPERTY LINK_FLAGS " -CETCOMPAT")
|
|
endif()
|
|
elseif(PSP)
|
|
target_link_libraries(${TARGET} PRIVATE GL)
|
|
elseif(EMSCRIPTEN)
|
|
set_property(TARGET ${TARGET} PROPERTY SUFFIX ".html")
|
|
target_link_options(${TARGET} PRIVATE "SHELL:--pre-js ${CMAKE_CURRENT_SOURCE_DIR}/emscripten/pre.js")
|
|
target_link_options(${TARGET} PRIVATE "-sEXIT_RUNTIME=1")
|
|
set_property(TARGET ${TARGET} APPEND PROPERTY LINK_DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/emscripten/pre.js")
|
|
set_property(TARGET ${TARGET} APPEND PROPERTY EXTRA_INSTALL
|
|
"$<TARGET_FILE_DIR:${TARGET}>/$<TARGET_FILE_BASE_NAME:${TARGET}>.js"
|
|
"$<TARGET_FILE_DIR:${TARGET}>/$<TARGET_FILE_BASE_NAME:${TARGET}>.wasm"
|
|
"$<TARGET_FILE_DIR:${TARGET}>/$<TARGET_FILE_BASE_NAME:${TARGET}>.wasm.map")
|
|
elseif(NGAGE)
|
|
string(MD5 TARGET_MD5 "${TARGET}")
|
|
string(SUBSTRING "${TARGET_MD5}" 0 8 TARGET_MD5_8)
|
|
target_link_options(${TARGET} PRIVATE "SHELL:-s UID3=0x${TARGET_MD5_8}")
|
|
if(NOT AST_MAIN_CALLBACKS)
|
|
set_property(TARGET ${TARGET} PROPERTY "EXCLUDE_FROM_ALL" "1")
|
|
set_propertY(TARGET ${TARGET} PROPERTY SDL_INSTALL "0")
|
|
endif()
|
|
elseif(DOS)
|
|
if(AST_NAME83)
|
|
set_property(TARGET ${TARGET} PROPERTY OUTPUT_NAME "${AST_NAME83}")
|
|
endif()
|
|
endif()
|
|
|
|
if(OPENGL_FOUND)
|
|
target_compile_definitions(${TARGET} PRIVATE HAVE_OPENGL)
|
|
endif()
|
|
|
|
# FIXME: only add "${SDL3_BINARY_DIR}/include-config-$<LOWER_CASE:$<CONFIG>>" + include paths of external dependencies
|
|
target_include_directories(${TARGET} PRIVATE "$<TARGET_PROPERTY:SDL3::${sdl_name_component},INCLUDE_DIRECTORIES>")
|
|
endfunction()
|
|
|
|
check_include_file(signal.h LIBC_HAS_SIGNAL_H)
|
|
if(LIBC_HAS_SIGNAL_H)
|
|
add_definitions(-DHAVE_SIGNAL_H)
|
|
endif()
|
|
|
|
check_include_file(libudev.h HAVE_LIBUDEV_H)
|
|
if(HAVE_LIBUDEV_H)
|
|
add_definitions(-DHAVE_LIBUDEV_H)
|
|
endif()
|
|
|
|
function(files2headers OUTPUT)
|
|
set(xxd "${SDL3_SOURCE_DIR}/cmake/xxd.py")
|
|
set(inputs ${ARGN})
|
|
set(outputs )
|
|
foreach(input IN LISTS inputs)
|
|
get_filename_component(file_we "${input}" NAME_WE)
|
|
set(intermediate "${CMAKE_CURRENT_BINARY_DIR}/${file_we}.h")
|
|
set(output "${CMAKE_CURRENT_SOURCE_DIR}/${file_we}.h")
|
|
list(APPEND outputs "${output}")
|
|
if(TARGET Python3::Interpreter AND NOT CMAKE_CROSSCOMPILING)
|
|
list(APPEND outputs "${intermediate}")
|
|
# Don't add the 'output' header to the output, to avoid marking them as GENERATED
|
|
# (generated files are removed when running the CLEAN target)
|
|
add_custom_command(OUTPUT "${intermediate}"
|
|
COMMAND Python3::Interpreter "${xxd}" -i "${CMAKE_CURRENT_SOURCE_DIR}/${input}" "-o" "${intermediate}"
|
|
COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${intermediate}" "${output}"
|
|
DEPENDS "${xxd}" "${png}"
|
|
)
|
|
endif()
|
|
endforeach()
|
|
set(${OUTPUT} "${outputs}" PARENT_SCOPE)
|
|
add_custom_target(generate-${OUTPUT} DEPENDS ${outputs})
|
|
endfunction()
|
|
|
|
files2headers(gamepad_image_headers
|
|
gamepad_axis_arrow.png
|
|
gamepad_axis.png
|
|
gamepad_back.png
|
|
gamepad_battery.png
|
|
gamepad_battery_wired.png
|
|
gamepad_button_background.png
|
|
gamepad_button.png
|
|
gamepad_button_small.png
|
|
gamepad_face_abxy.png
|
|
gamepad_face_axby.png
|
|
gamepad_face_bayx.png
|
|
gamepad_face_sony.png
|
|
gamepad_front.png
|
|
gamepad_touchpad.png
|
|
gamepad_wired.png
|
|
gamepad_wireless.png
|
|
)
|
|
files2headers(icon_png_header icon.png)
|
|
files2headers(glass_png_header glass.png)
|
|
|
|
set(FFmpeg_FIND_COMPONENTS AVCODEC AVFORMAT AVUTIL SWSCALE)
|
|
include("${CMAKE_CURRENT_LIST_DIR}/../cmake/FindFFmpeg.cmake")
|
|
if(FFmpeg_FOUND)
|
|
cmake_push_check_state()
|
|
list(APPEND CMAKE_REQUIRED_INCLUDES "${FFmpeg_AVUTIL_INCLUDE_DIRS}")
|
|
list(APPEND CMAKE_REQUIRED_INCLUDES "${SDL3_SOURCE_DIR}/src/video/khronos")
|
|
check_struct_has_member("AVFrame" "ch_layout" "libavutil/frame.h" LIBAVUTIL_AVFRAME_HAS_CH_LAYOUT)
|
|
check_struct_has_member("AVVulkanFramesContext" "format" "libavutil/hwcontext_vulkan.h" LIBAVUTIL_AVFULKANFRAMESCONTEXT_HAS_FORMAT)
|
|
cmake_pop_check_state()
|
|
endif()
|
|
if(FFmpeg_FOUND AND LIBAVUTIL_AVFRAME_HAS_CH_LAYOUT)
|
|
add_sdl_test_executable(testffmpeg SOURCES testffmpeg.c testffmpeg_vulkan.c ${icon_png_header} DEPENDS generate-icon_png_header)
|
|
if(LIBAVUTIL_AVFULKANFRAMESCONTEXT_HAS_FORMAT)
|
|
target_compile_definitions(testffmpeg PRIVATE FFMPEG_VULKAN_SUPPORT)
|
|
endif()
|
|
if(APPLE)
|
|
target_link_options(testffmpeg PRIVATE "-Wl,-framework,CoreVideo")
|
|
endif()
|
|
if(TARGET OpenGL::EGL)
|
|
message(DEBUG "Enabling EGL support in testffmpeg")
|
|
target_link_libraries(testffmpeg PRIVATE OpenGL::EGL)
|
|
target_compile_definitions(testffmpeg PRIVATE HAVE_EGL)
|
|
endif()
|
|
target_include_directories(testffmpeg SYSTEM BEFORE PRIVATE ${SDL3_SOURCE_DIR}/src/video/khronos)
|
|
target_link_libraries(testffmpeg PRIVATE ${FFMPEG_LIBRARIES})
|
|
else()
|
|
message(STATUS "Can't find ffmpeg 5.1.3 or newer, skipping testffmpeg")
|
|
endif()
|
|
|
|
add_sdl_test_executable(checkkeys SOURCES checkkeys.c NAME83 chkkeys)
|
|
add_sdl_test_executable(loopwave NEEDS_RESOURCES TESTUTILS MAIN_CALLBACKS SOURCES loopwave.c)
|
|
add_sdl_test_executable(testsurround SOURCES testsurround.c NAME83 surround)
|
|
add_sdl_test_executable(testresample NEEDS_RESOURCES SOURCES testresample.c NAME83 resample)
|
|
add_sdl_test_executable(testaudioinfo SOURCES testaudioinfo.c NAME83 audioinf)
|
|
add_sdl_test_executable(testaudiostreamdynamicresample NEEDS_RESOURCES TESTUTILS SOURCES testaudiostreamdynamicresample.c NAME83 audynres)
|
|
|
|
file(GLOB TESTAUTOMATION_SOURCE_FILES testautomation*.c)
|
|
add_sdl_test_executable(testautomation NONINTERACTIVE NONINTERACTIVE_TIMEOUT 120 NEEDS_RESOURCES BUILD_DEPENDENT SOURCES ${TESTAUTOMATION_SOURCE_FILES} NAME83 automat)
|
|
if(EMSCRIPTEN)
|
|
target_link_options(testautomation PRIVATE -sALLOW_MEMORY_GROWTH=1 -sMAXIMUM_MEMORY=1gb)
|
|
endif()
|
|
add_sdl_test_executable(testmultiaudio NEEDS_RESOURCES TESTUTILS SOURCES testmultiaudio.c NAME83 multaudi)
|
|
add_sdl_test_executable(testaudiohotplug NEEDS_RESOURCES TESTUTILS SOURCES testaudiohotplug.c NAME83 audhotpl)
|
|
add_sdl_test_executable(testaudiorecording MAIN_CALLBACKS SOURCES testaudiorecording.c NAME83 aurecord)
|
|
add_sdl_test_executable(testatomic NONINTERACTIVE DISABLE_THREADS_ARGS "--no-threads" SOURCES testatomic.c NAME83 atomic)
|
|
add_sdl_test_executable(testintersections SOURCES testintersections.c NAME83 intersec)
|
|
add_sdl_test_executable(testrelative SOURCES testrelative.c NAME83 relative)
|
|
add_sdl_test_executable(testhittesting SOURCES testhittesting.c NAME83 hittest)
|
|
add_sdl_test_executable(testdraw SOURCES testdraw.c NAME83 draw)
|
|
add_sdl_test_executable(testdrawchessboard SOURCES testdrawchessboard.c NAME83 drawches)
|
|
add_sdl_test_executable(testdropfile MAIN_CALLBACKS SOURCES testdropfile.c NAME83 dropfile)
|
|
add_sdl_test_executable(testerror NONINTERACTIVE DISABLE_THREADS_ARGS "--no-threads" SOURCES testerror.c NAME83 error)
|
|
add_sdl_test_executable(testsymbols NONINTERACTIVE NOTRACKMEM NONINTERACTIVE_ARGS 0 10 20 40 80 160 320 640 SOURCES testsymbols.c NAME83 symbols)
|
|
|
|
set(build_options_dependent_tests )
|
|
|
|
add_sdl_test_executable(testevdev BUILD_DEPENDENT NONINTERACTIVE SOURCES testevdev.c NAME83 evdev)
|
|
|
|
if(MACOS)
|
|
add_sdl_test_executable(testnative BUILD_DEPENDENT NEEDS_RESOURCES TESTUTILS
|
|
SOURCES
|
|
testnative.c
|
|
testnativecocoa.m
|
|
testnativex11.c
|
|
)
|
|
elseif(WINDOWS)
|
|
add_sdl_test_executable(testnative BUILD_DEPENDENT NEEDS_RESOURCES TESTUTILS SOURCES testnative.c testnativew32.c)
|
|
elseif(HAVE_X11 OR HAVE_WAYLAND)
|
|
add_sdl_test_executable(testnative BUILD_DEPENDENT NEEDS_RESOURCES TESTUTILS SOURCES testnative.c)
|
|
if(HAVE_X11)
|
|
target_sources(testnative PRIVATE testnativex11.c)
|
|
target_link_libraries(testnative PRIVATE X11::X11)
|
|
endif()
|
|
if(HAVE_WAYLAND)
|
|
set_property(SOURCE ${SDL3_BINARY_DIR}/wayland-generated-protocols/xdg-shell-protocol.c PROPERTY GENERATED 1)
|
|
target_sources(testnative PRIVATE testnativewayland.c "${SDL3_BINARY_DIR}/wayland-generated-protocols/xdg-shell-protocol.c")
|
|
|
|
# Needed to silence the documentation warning in the generated header file
|
|
target_compile_options(testnative PRIVATE -Wno-documentation-unknown-command)
|
|
target_link_libraries(testnative PRIVATE PkgConfig::PkgWaylandClient)
|
|
endif ()
|
|
endif()
|
|
|
|
add_sdl_test_executable(testasyncio MAIN_CALLBACKS NEEDS_RESOURCES TESTUTILS SOURCES testasyncio.c NAME83 asyncio)
|
|
add_sdl_test_executable(testaudio MAIN_CALLBACKS NEEDS_RESOURCES TESTUTILS SOURCES testaudio.c NAME83 audio)
|
|
add_sdl_test_executable(testcolorspace SOURCES testcolorspace.c NAME83 colorspc)
|
|
add_sdl_test_executable(testfile NONINTERACTIVE SOURCES testfile.c)
|
|
add_sdl_test_executable(testcontroller TESTUTILS SOURCES testcontroller.c gamepadutils.c ${gamepad_image_headers} DEPENDS generate-gamepad_image_headers NAME83 control)
|
|
add_sdl_test_executable(testdlopennote TESTUTILS SOURCES testdlopennote.c NAME83 dlnote)
|
|
add_sdl_test_executable(testgeometry TESTUTILS SOURCES testgeometry.c NAME83 geometry)
|
|
add_sdl_test_executable(testgl SOURCES testgl.c NAME83 gl)
|
|
add_sdl_test_executable(testgles SOURCES testgles.c NAME83 tstgles NAME83 gles)
|
|
add_sdl_test_executable(testgpu_simple_clear SOURCES testgpu_simple_clear.c NAME83 gpuclear)
|
|
add_sdl_test_executable(testgpu_spinning_cube SOURCES testgpu_spinning_cube.c ${icon_png_header} DEPENDS generate-icon_png_header NAME83 gpucube)
|
|
add_sdl_test_executable(testgpurender_effects MAIN_CALLBACKS NEEDS_RESOURCES TESTUTILS SOURCES testgpurender_effects.c NAME83 gpufx)
|
|
add_sdl_test_executable(testgpurender_msdf MAIN_CALLBACKS NEEDS_RESOURCES TESTUTILS SOURCES testgpurender_msdf.c NAME83 gpumsdf)
|
|
add_sdl_test_executable(testgpu_spinning_cube_xr SOURCES testgpu_spinning_cube_xr.c NAME83 gpucubxr)
|
|
|
|
if(ANDROID)
|
|
target_link_libraries(testgles PRIVATE GLESv1_CM)
|
|
elseif(IOS OR TVOS)
|
|
find_library(GLES_LIB OpenGLES REQUIRED)
|
|
target_link_libraries(testgles PRIVATE "${GLES_LIB}")
|
|
endif()
|
|
add_sdl_test_executable(testgles2 SOURCES testgles2.c NAME83 gles2)
|
|
add_sdl_test_executable(testhaptic SOURCES testhaptic.c NAME83 haptic)
|
|
add_sdl_test_executable(testhotplug SOURCES testhotplug.c NAME83 hotplug)
|
|
add_sdl_test_executable(testpen SOURCES testpen.c NAME83 pen)
|
|
add_sdl_test_executable(testrumble SOURCES testrumble.c NAME83 rumble)
|
|
add_sdl_test_executable(testthread NONINTERACTIVE THREADS NONINTERACTIVE_TIMEOUT 40 SOURCES testthread.c NAME83 thread)
|
|
add_sdl_test_executable(testiconv NEEDS_RESOURCES TESTUTILS SOURCES testiconv.c NAME83 iconv)
|
|
add_sdl_test_executable(testime NEEDS_RESOURCES TESTUTILS SOURCES testime.c NAME83 ime)
|
|
add_sdl_test_executable(testkeys SOURCES testkeys.c NAME83 keys)
|
|
add_sdl_test_executable(testloadso SOURCES testloadso.c NAME83 loadso)
|
|
add_sdl_test_executable(testlocale NONINTERACTIVE SOURCES testlocale.c NAME83 locale)
|
|
add_sdl_test_executable(testlock SOURCES testlock.c NAME83 lock)
|
|
add_sdl_test_executable(testrwlock SOURCES testrwlock.c NONINTERACTIVE NONINTERACTIVE_TIMEOUT 20 NAME83 rwlock)
|
|
add_sdl_test_executable(testmouse SOURCES testmouse.c NAME83 mouse)
|
|
|
|
add_sdl_test_executable(testoverlay NEEDS_RESOURCES TESTUTILS SOURCES testoverlay.c NAME83 overlay)
|
|
add_sdl_test_executable(testplatform NONINTERACTIVE SOURCES testplatform.c NAME83 platform)
|
|
add_sdl_test_executable(testpower NONINTERACTIVE SOURCES testpower.c NAME83 power)
|
|
add_sdl_test_executable(testfilesystem NONINTERACTIVE SOURCES testfilesystem.c NAME83 filesyst)
|
|
if(WIN32 AND CMAKE_SIZEOF_VOID_P EQUAL 4)
|
|
add_sdl_test_executable(pretest SOURCES pretest.c NONINTERACTIVE NONINTERACTIVE_TIMEOUT 60)
|
|
endif()
|
|
add_sdl_test_executable(testrendertarget NEEDS_RESOURCES TESTUTILS SOURCES testrendertarget.c NAME83 rendrtgt)
|
|
add_sdl_test_executable(testrotate SOURCES testrotate.c NAME83 rotate)
|
|
add_sdl_test_executable(testscale NEEDS_RESOURCES TESTUTILS SOURCES testscale.c NAME83 scale)
|
|
add_sdl_test_executable(testsem NONINTERACTIVE DISABLE_THREADS_ARGS "--no-threads" NONINTERACTIVE_ARGS 10 NONINTERACTIVE_TIMEOUT 30 SOURCES testsem.c NAME83 sem)
|
|
add_sdl_test_executable(testsensor SOURCES testsensor.c NAME83 sensor)
|
|
add_sdl_test_executable(testshader NEEDS_RESOURCES TESTUTILS SOURCES testshader.c NAME83 shader)
|
|
if(EMSCRIPTEN)
|
|
target_link_options(testshader PRIVATE "-sLEGACY_GL_EMULATION")
|
|
endif()
|
|
add_sdl_test_executable(testshape NEEDS_RESOURCES SOURCES testshape.c ${glass_png_header} DEPENDS generate-glass_png_header NAME83 shape)
|
|
add_sdl_test_executable(testsoftwaretransparent SOURCES testsoftwaretransparent.c NAME83 swtransp)
|
|
add_sdl_test_executable(testsprite MAIN_CALLBACKS NEEDS_RESOURCES TESTUTILS SOURCES testsprite.c NAME83 sprite)
|
|
add_sdl_test_executable(testspriteminimal SOURCES testspriteminimal.c ${icon_png_header} DEPENDS generate-icon_png_header NAME83 spritmin)
|
|
add_sdl_test_executable(testspritesurface SOURCES testspritesurface.c ${icon_png_header} DEPENDS generate-icon_png_header NAME83 spritsrf)
|
|
add_sdl_test_executable(testpalette SOURCES testpalette.c NAME83 palette)
|
|
add_sdl_test_executable(testtimer NONINTERACTIVE NONINTERACTIVE_ARGS --no-interactive NONINTERACTIVE_TIMEOUT 60 SOURCES testtimer.c NAME83 timer)
|
|
add_sdl_test_executable(testurl SOURCES testurl.c NAME83 url)
|
|
add_sdl_test_executable(testver NONINTERACTIVE NOTRACKMEM SOURCES testver.c NAME83 versdl)
|
|
set_property(TARGET testver PROPERTY C_STANDARD 90)
|
|
add_sdl_test_executable(testcamera MAIN_CALLBACKS SOURCES testcamera.c NAME83 camera)
|
|
add_sdl_test_executable(testclipboard MAIN_CALLBACKS SOURCES testclipboard.c ${icon_png_header} DEPENDS generate-icon_png_header NAME83 clipbrd)
|
|
add_sdl_test_executable(testviewport NEEDS_RESOURCES TESTUTILS SOURCES testviewport.c NAME83 viewport)
|
|
add_sdl_test_executable(testwm SOURCES testwm.c NAME83 wm)
|
|
add_sdl_test_executable(testyuv NONINTERACTIVE NONINTERACTIVE_ARGS "--automated" NEEDS_RESOURCES TESTUTILS SOURCES testyuv.c testyuv_cvt.c NAME83 yuv)
|
|
add_sdl_test_executable(torturethread NONINTERACTIVE THREADS NONINTERACTIVE_TIMEOUT 30 SOURCES torturethread.c NAME83 tortthrd)
|
|
add_sdl_test_executable(testrendercopyex NEEDS_RESOURCES TESTUTILS SOURCES testrendercopyex.c NAME83 rndcopex)
|
|
add_sdl_test_executable(testmessage SOURCES testmessage.c NAME83 message)
|
|
add_sdl_test_executable(testdisplayinfo SOURCES testdisplayinfo.c NAME83 dispinfo)
|
|
add_sdl_test_executable(testqsort NONINTERACTIVE SOURCES testqsort.c NAME83 qsort)
|
|
if(EMSCRIPTEN)
|
|
target_link_options(testqsort PRIVATE -sALLOW_MEMORY_GROWTH)
|
|
endif()
|
|
add_sdl_test_executable(testbounds NONINTERACTIVE SOURCES testbounds.c NAME83 bounds)
|
|
add_sdl_test_executable(testcustomcursor SOURCES testcustomcursor.c NAME83 custcurs)
|
|
add_sdl_test_executable(testvulkan SOURCES testvulkan.c NAME83 vulkan)
|
|
add_sdl_test_executable(testoffscreen SOURCES testoffscreen.c NAME83 offscrn)
|
|
add_sdl_test_executable(testpopup SOURCES testpopup.c NAME83 popup)
|
|
add_sdl_test_executable(testdialog SOURCES testdialog.c NAME83 dialog)
|
|
add_sdl_test_executable(testtime SOURCES testtime.c NAME83 timesdl)
|
|
add_sdl_test_executable(testmanymouse SOURCES testmanymouse.c NAME83 manymous)
|
|
add_sdl_test_executable(testmodal SOURCES testmodal.c NAME83 modal)
|
|
add_sdl_test_executable(testtray NEEDS_RESOURCES TESTUTILS SOURCES testtray.c NAME83 tray)
|
|
|
|
|
|
add_sdl_test_executable(testprocess
|
|
NONINTERACTIVE THREADS
|
|
NONINTERACTIVE_ARGS $<TARGET_FILE:childprocess>
|
|
INSTALLED_ARGS "${CMAKE_INSTALL_FULL_LIBEXECDIR}/installed-tests/SDL3/childprocess${CMAKE_EXECUTABLE_SUFFIX}"
|
|
SOURCES testprocess.c
|
|
NAME83 process
|
|
)
|
|
add_sdl_test_executable(childprocess SOURCES childprocess.c NAME83 chldproc)
|
|
add_dependencies(testprocess childprocess)
|
|
|
|
get_property(SDL_TEST_EXECUTABLES DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" PROPERTY SDL_TEST_EXECUTABLES)
|
|
|
|
if (HAVE_WAYLAND)
|
|
# Set the GENERATED property on the protocol file, since it is first created at build time
|
|
set_property(SOURCE ${SDL3_BINARY_DIR}/wayland-generated-protocols/xdg-shell-protocol.c PROPERTY GENERATED 1)
|
|
add_sdl_test_executable(testwaylandcustom NEEDS_RESOURCES SOURCES testwaylandcustom.c ${SDL3_BINARY_DIR}/wayland-generated-protocols/xdg-shell-protocol.c)
|
|
# Needed to silence the documentation warning in the generated header file
|
|
target_compile_options(testwaylandcustom PRIVATE -Wno-documentation-unknown-command)
|
|
target_link_libraries(testwaylandcustom PRIVATE PkgConfig::PkgWaylandClient)
|
|
endif()
|
|
|
|
check_c_compiler_flag(-Wformat-overflow HAVE_WFORMAT_OVERFLOW)
|
|
if(HAVE_WFORMAT_OVERFLOW)
|
|
target_compile_definitions(testautomation PRIVATE HAVE_WFORMAT_OVERFLOW)
|
|
endif()
|
|
|
|
check_c_compiler_flag(-Wformat HAVE_WFORMAT)
|
|
if(HAVE_WFORMAT)
|
|
target_compile_definitions(testautomation PRIVATE HAVE_WFORMAT)
|
|
endif()
|
|
|
|
cmake_push_check_state()
|
|
if(HAVE_WFORMAT)
|
|
# Some compilers ignore -Wformat-extra-args without -Wformat
|
|
string(APPEND CMAKE_REQUIRED_FLAGS " -Wformat")
|
|
endif()
|
|
check_c_compiler_flag(-Wformat-extra-args HAVE_WFORMAT_EXTRA_ARGS)
|
|
cmake_pop_check_state()
|
|
if(HAVE_WFORMAT_EXTRA_ARGS)
|
|
target_compile_definitions(testautomation PRIVATE HAVE_WFORMAT_EXTRA_ARGS)
|
|
endif()
|
|
|
|
if(SDL_DUMMYAUDIO)
|
|
set_property(TARGET testaudioinfo PROPERTY SDL_NONINTERACTIVE 1)
|
|
endif()
|
|
|
|
if(SDL_DUMMYVIDEO)
|
|
set_property(TARGET testkeys PROPERTY SDL_NONINTERACTIVE 1)
|
|
set_property(TARGET testbounds PROPERTY SDL_NONINTERACTIVE 1)
|
|
set_property(TARGET testdisplayinfo PROPERTY SDL_NONINTERACTIVE 1)
|
|
endif()
|
|
|
|
if(OPENGL_FOUND)
|
|
if(TARGET OpenGL::GL)
|
|
target_link_libraries(testshader PRIVATE OpenGL::GL)
|
|
target_link_libraries(testgl PRIVATE OpenGL::GL)
|
|
else()
|
|
if(EMSCRIPTEN AND OPENGL_gl_LIBRARY STREQUAL "nul")
|
|
set(OPENGL_gl_LIBRARY GL)
|
|
endif()
|
|
# emscripten's FindOpenGL.cmake does not create OpenGL::GL
|
|
target_link_libraries(testshader PRIVATE ${OPENGL_gl_LIBRARY})
|
|
target_link_libraries(testgl PRIVATE ${OPENGL_gl_LIBRARY})
|
|
endif()
|
|
endif()
|
|
if(MACOS)
|
|
target_link_options(testnative PRIVATE "-Wl,-framework,Cocoa")
|
|
endif()
|
|
if(APPLE)
|
|
cmake_push_check_state()
|
|
check_c_compiler_flag(-Wno-error=deprecated-declarations HAVE_WNO_ERROR_DEPRECATED_DECLARATIONS)
|
|
cmake_pop_check_state()
|
|
if(HAVE_WNO_ERROR_DEPRECATED_DECLARATIONS)
|
|
set_property(SOURCE "testnativecocoa.m" APPEND PROPERTY COMPILE_OPTIONS "-Wno-error=deprecated-declarations")
|
|
set_property(TARGET testgles APPEND PROPERTY COMPILE_OPTIONS "-Wno-error=deprecated-declarations")
|
|
endif()
|
|
endif()
|
|
|
|
|
|
if(PSP)
|
|
# Build EBOOT files if building for PSP
|
|
foreach(APP ${SDL_TEST_EXECUTABLES})
|
|
create_pbp_file(
|
|
TARGET ${APP}
|
|
TITLE SDL-${APP}
|
|
ICON_PATH NULL
|
|
BACKGROUND_PATH NULL
|
|
PREVIEW_PATH NULL
|
|
OUTPUT_DIR $<TARGET_FILE_DIR:${APP}>/sdl-${APP}
|
|
)
|
|
endforeach()
|
|
endif()
|
|
|
|
if(N3DS)
|
|
foreach(APP ${SDL_TEST_EXECUTABLES})
|
|
get_target_property(TARGET_BINARY_DIR ${APP} BINARY_DIR)
|
|
set(ROMFS_DIR "${TARGET_BINARY_DIR}/sdl-${APP}")
|
|
set(SMDH_FILE "${TARGET_BINARY_DIR}/${APP}.smdh")
|
|
file(MAKE_DIRECTORY ${ROMFS_DIR})
|
|
ctr_generate_smdh("${SMDH_FILE}"
|
|
NAME "SDL-${APP}"
|
|
DESCRIPTION "SDL3 Test suite"
|
|
AUTHOR "SDL3 Contributors"
|
|
ICON "${CMAKE_CURRENT_SOURCE_DIR}/n3ds/logo48x48.png"
|
|
)
|
|
ctr_create_3dsx(
|
|
${APP}
|
|
ROMFS "${ROMFS_DIR}"
|
|
SMDH "${SMDH_FILE}"
|
|
)
|
|
endforeach()
|
|
endif()
|
|
|
|
if(RISCOS)
|
|
set(SDL_TEST_EXECUTABLES_AIF)
|
|
foreach(APP ${SDL_TEST_EXECUTABLES})
|
|
set_property(TARGET ${APP} APPEND_STRING PROPERTY LINK_FLAGS " -static")
|
|
add_custom_command(
|
|
OUTPUT ${APP},ff8
|
|
COMMAND elf2aif ${APP} ${APP},ff8
|
|
DEPENDS ${APP}
|
|
)
|
|
add_custom_target(${APP}-aif ALL DEPENDS ${APP},ff8)
|
|
list(APPEND SDL_TEST_EXECUTABLES_AIF ${CMAKE_CURRENT_BINARY_DIR}/${APP},ff8)
|
|
endforeach()
|
|
endif()
|
|
|
|
# Set Apple App ID / Bundle ID. This is needed to launch apps on some Apple
|
|
# platforms (iOS, for example).
|
|
if(APPLE)
|
|
foreach(CURRENT_TARGET ${SDL_TEST_EXECUTABLES})
|
|
set_target_properties("${CURRENT_TARGET}" PROPERTIES
|
|
MACOSX_BUNDLE_GUI_IDENTIFIER "org.libsdl.${CURRENT_TARGET}"
|
|
MACOSX_BUNDLE_BUNDLE_VERSION "${SDL3_VERSION}"
|
|
MACOSX_BUNDLE_SHORT_VERSION_STRING "${SDL3_VERSION}"
|
|
)
|
|
endforeach()
|
|
endif()
|
|
|
|
set(SDLTEST_TIMEOUT_MULTIPLIER "1" CACHE STRING "SDL test time-out multiplier")
|
|
|
|
set(SDLTEST_AUDIO_DRIVER_DEFAULT "dummy")
|
|
set(SDLTEST_VIDEO_DRIVER_DEFAULT "dummy")
|
|
if(EMSCRIPTEN)
|
|
set(SDLTEST_AUDIO_DRIVER_DEFAULT "emscripten")
|
|
set(SDLTEST_VIDEO_DRIVER_DEFAULT "emscripten")
|
|
endif()
|
|
set(SDLTEST_AUDIO_DRIVER "${SDLTEST_AUDIO_DRIVER_DEFAULT}" CACHE STRING "SDL audio driver for CTest")
|
|
set(SDLTEST_VIDEO_DRIVER "${SDLTEST_VIDEO_DRIVER_DEFAULT}" CACHE STRING "SDL video driver for CTest")
|
|
|
|
set(TESTS_ENVIRONMENT
|
|
"SDL_AUDIO_DRIVER=${SDLTEST_AUDIO_DRIVER}"
|
|
"SDL_VIDEO_DRIVER=${SDLTEST_VIDEO_DRIVER}"
|
|
"SDL_ASSERT=abort"
|
|
)
|
|
|
|
function(add_sdl_test TEST TARGET)
|
|
cmake_parse_arguments(ast "INSTALL" "" "" ${ARGN})
|
|
get_property(noninteractive TARGET ${TARGET} PROPERTY SDL_NONINTERACTIVE)
|
|
if(noninteractive)
|
|
if(EMSCRIPTEN)
|
|
set(command "${PYTHON3_EXECUTABLE};${CMAKE_CURRENT_SOURCE_DIR}/emscripten/driver.py;--server;http://localhost:${SDLTEST_PORT};--browser;${SDLTEST_BROWSER}")
|
|
if(SDLTEST_CHROME_BINARY)
|
|
list(APPEND command "--chrome-binary;${SDLTEST_CHROME_BINARY}")
|
|
endif()
|
|
list(APPEND command "--;${TARGET}")
|
|
else()
|
|
set(command ${TARGET})
|
|
endif()
|
|
get_property(noninteractive_arguments TARGET ${TARGET} PROPERTY SDL_NONINTERACTIVE_ARGUMENTS)
|
|
get_property(installed_arguments_list TARGET ${TARGET} PROPERTY SDL_INSTALLED_ARGUMENTS)
|
|
# This assumes that none of the arguments need quoting
|
|
list(JOIN installed_arguments_list " " installed_arguments)
|
|
get_property(disable_threads_args TARGET ${TARGET} PROPERTY SDL_DISABLE_THREADS_ARGS)
|
|
get_property(uses_threads TARGET ${TARGET} PROPERTY SDL_THREADS)
|
|
if(noninteractive_arguments)
|
|
list(APPEND command ${noninteractive_arguments})
|
|
endif()
|
|
if(SDLTEST_TRACKMEM)
|
|
get_property(notrackmem TARGET ${TARGET} PROPERTY SDL_NOTRACKMEM)
|
|
if(NOT notrackmem)
|
|
list(APPEND command --trackmem)
|
|
endif()
|
|
endif()
|
|
if(EMSCRIPTEN)
|
|
list(APPEND command ${disable_threads_args})
|
|
endif()
|
|
add_test(
|
|
NAME ${TEST}
|
|
COMMAND ${command}
|
|
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
|
)
|
|
if(WIN32 AND CMAKE_VERSION VERSION_GREATER_EQUAL "3.27")
|
|
set_property(TEST ${TEST} APPEND PROPERTY ENVIRONMENT_MODIFICATION "PATH=path_list_prepend:$<TARGET_RUNTIME_DLL_DIRS:${TARGET}>")
|
|
endif()
|
|
if(NOT notrackmem)
|
|
set_property(TEST ${TEST} PROPERTY FAIL_REGULAR_EXPRESSION "Total: [0-9]+\\.[0-9]+ Kb in [1-9][0-9]* allocations")
|
|
endif()
|
|
set_tests_properties(${TEST} PROPERTIES ENVIRONMENT "${TESTS_ENVIRONMENT}")
|
|
if(EMSCRIPTEN AND uses_threads)
|
|
set_tests_properties(${TEST} PROPERTIES DISABLED 1)
|
|
endif()
|
|
get_property(noninteractive_timeout TARGET ${TARGET} PROPERTY SDL_NONINTERACTIVE_TIMEOUT)
|
|
if(NOT noninteractive_timeout)
|
|
set(noninteractive_timeout 10)
|
|
endif()
|
|
math(EXPR noninteractive_timeout "${noninteractive_timeout}*${SDLTEST_TIMEOUT_MULTIPLIER}")
|
|
set_tests_properties(${TEST} PROPERTIES TIMEOUT "${noninteractive_timeout}")
|
|
if(ast_INSTALL AND SDL_INSTALL_TESTS)
|
|
set(exe ${TARGET})
|
|
set(installedtestsdir "${CMAKE_INSTALL_FULL_LIBEXECDIR}/installed-tests/SDL3")
|
|
configure_file(template.test.in "${exe}.test" @ONLY)
|
|
install(
|
|
FILES "${CMAKE_CURRENT_BINARY_DIR}/${exe}.test"
|
|
DESTINATION ${CMAKE_INSTALL_DATADIR}/installed-tests/SDL3
|
|
)
|
|
endif()
|
|
if(TARGET pretest AND NOT "${TARGET}" MATCHES "pretest")
|
|
set_property(TEST ${TEST} APPEND PROPERTY DEPENDS pretest)
|
|
endif()
|
|
endif()
|
|
endfunction()
|
|
|
|
foreach(TARGET ${SDL_TEST_EXECUTABLES})
|
|
add_sdl_test(${TARGET} ${TARGET} INSTALL)
|
|
endforeach()
|
|
|
|
if(NOT EMSCRIPTEN)
|
|
add_sdl_test(testautomation-no-simd testautomation)
|
|
add_sdl_test(testplatform-no-simd testplatform)
|
|
set_property(TEST testautomation-no-simd testplatform-no-simd APPEND PROPERTY ENVIRONMENT "SDL_CPU_FEATURE_MASK=-all")
|
|
|
|
# testautomation creates temporary files which might conflict
|
|
set_property(TEST testautomation-no-simd testautomation PROPERTY RUN_SERIAL TRUE)
|
|
endif()
|
|
|
|
if(SDL_INSTALL_TESTS)
|
|
if(RISCOS)
|
|
install(
|
|
FILES ${SDL_TEST_EXECUTABLES_AIF}
|
|
DESTINATION ${CMAKE_INSTALL_LIBEXECDIR}/installed-tests/SDL3
|
|
)
|
|
else()
|
|
foreach(test IN LISTS SDL_TEST_EXECUTABLES)
|
|
get_property(install_target TARGET ${test} PROPERTY "SDL_INSTALL")
|
|
if(install_target)
|
|
install(
|
|
TARGETS ${test}
|
|
DESTINATION ${CMAKE_INSTALL_LIBEXECDIR}/installed-tests/SDL3
|
|
)
|
|
get_property(extra_install TARGET ${test} PROPERTY "EXTRA_INSTALL")
|
|
if(extra_install)
|
|
install(
|
|
FILES ${extra_install}
|
|
DESTINATION ${CMAKE_INSTALL_LIBEXECDIR}/installed-tests/SDL3
|
|
OPTIONAL
|
|
)
|
|
endif()
|
|
endif()
|
|
endforeach()
|
|
endif()
|
|
if(MSVC)
|
|
foreach(test IN LISTS SDL_TEST_EXECUTABLES)
|
|
SDL_install_pdb(${test} "${CMAKE_INSTALL_LIBEXECDIR}/installed-tests/SDL3")
|
|
endforeach()
|
|
endif()
|
|
install(
|
|
FILES ${RESOURCE_FILES}
|
|
DESTINATION ${CMAKE_INSTALL_LIBEXECDIR}/installed-tests/SDL3
|
|
)
|
|
endif()
|
|
|
|
if(ANDROID AND TARGET SDL3::Jar)
|
|
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../cmake/android")
|
|
find_package(SdlAndroid MODULE)
|
|
if(SdlAndroid_FOUND)
|
|
set(apks "")
|
|
set(packages "")
|
|
|
|
include(SdlAndroidFunctions)
|
|
sdl_create_android_debug_keystore(SDL_test-debug-keystore)
|
|
sdl_android_compile_resources(SDL_test-resources RESFOLDER android/res)
|
|
add_custom_target(sdl-test-apks)
|
|
foreach(TEST ${SDL_TEST_EXECUTABLES})
|
|
set(ANDROID_MANIFEST_APP_NAME "${TEST}")
|
|
set(ANDROID_MANIFEST_LABEL "${TEST}")
|
|
set(ANDROID_MANIFEST_LIB_NAME "$<TARGET_FILE_BASE_NAME:${TEST}>")
|
|
set(ANDROID_MANIFEST_PACKAGE "org.libsdl.sdl.test.${TEST}")
|
|
set(generated_manifest_path "${CMAKE_CURRENT_BINARY_DIR}/android/${TEST}-src/AndroidManifest.xml")
|
|
string(REPLACE "." "/" JAVA_PACKAGE_DIR "${ANDROID_MANIFEST_PACKAGE}")
|
|
set(GENERATED_SRC_FOLDER "${CMAKE_CURRENT_BINARY_DIR}/android/${TEST}-src")
|
|
set(GENERATED_RES_FOLDER "${GENERATED_SRC_FOLDER}/res")
|
|
set(JAVA_PACKAGE_DIR "${GENERATED_SRC_FOLDER}/${JAVA_PACKAGE_DIR}")
|
|
configure_file(android/cmake/SDLEntryTestActivity.java.cmake "${JAVA_PACKAGE_DIR}/SDLEntryTestActivity.java" @ONLY)
|
|
configure_file(android/cmake/SDLTestActivity.java.cmake "${JAVA_PACKAGE_DIR}/SDLTestActivity.java" @ONLY)
|
|
configure_file(android/cmake/res/values/strings.xml.cmake android/res/values/strings-${TEST}.xml @ONLY)
|
|
configure_file(android/cmake/res/xml/shortcuts.xml.cmake "${GENERATED_RES_FOLDER}/xml/shortcuts.xml" @ONLY)
|
|
# Use XR-specific manifest for XR tests, standard manifest for others
|
|
if("${TEST}" MATCHES "_xr$")
|
|
# Meta Quest-specific manifest sections (enabled by default, set to empty to disable)
|
|
# These are ignored by non-Meta runtimes but required for proper Quest integration
|
|
if(NOT DEFINED SDL_ANDROID_XR_META_SUPPORT OR SDL_ANDROID_XR_META_SUPPORT)
|
|
set(ANDROID_XR_META_FEATURES
|
|
" <!-- Meta Quest hand tracking support -->
|
|
<uses-feature android:name=\"oculus.software.handtracking\" android:required=\"false\" />
|
|
")
|
|
set(ANDROID_XR_META_METADATA
|
|
" <!-- Meta Quest supported devices -->
|
|
<meta-data android:name=\"com.oculus.supportedDevices\" android:value=\"quest|quest2|questpro|quest3|quest3s\" />
|
|
<meta-data android:name=\"com.oculus.vr.focusaware\" android:value=\"true\" />
|
|
<!-- Hand tracking support level (V2 allows launching without controllers) -->
|
|
<meta-data android:name=\"com.oculus.handtracking.version\" android:value=\"V2.0\" />
|
|
<meta-data android:name=\"com.oculus.handtracking.frequency\" android:value=\"HIGH\" />
|
|
")
|
|
set(ANDROID_XR_META_INTENT_CATEGORY
|
|
" <!-- VR intent category for Meta Quest -->
|
|
<category android:name=\"com.oculus.intent.category.VR\" />")
|
|
else()
|
|
set(ANDROID_XR_META_FEATURES "")
|
|
set(ANDROID_XR_META_METADATA "")
|
|
set(ANDROID_XR_META_INTENT_CATEGORY "")
|
|
endif()
|
|
configure_file(android/cmake/AndroidManifest.xr.xml.cmake "${generated_manifest_path}" @ONLY)
|
|
else()
|
|
configure_file(android/cmake/AndroidManifest.xml.cmake "${generated_manifest_path}" @ONLY)
|
|
endif()
|
|
file(GENERATE
|
|
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/android/${TEST}-$<CONFIG>/res/values/strings.xml"
|
|
INPUT "${CMAKE_CURRENT_BINARY_DIR}/android/res/values/strings-${TEST}.xml"
|
|
)
|
|
|
|
sdl_android_compile_resources(${TEST}-resources
|
|
RESOURCES
|
|
"${CMAKE_CURRENT_BINARY_DIR}/android/${TEST}-$<CONFIG>/res/values/strings.xml"
|
|
"${GENERATED_RES_FOLDER}/xml/shortcuts.xml"
|
|
)
|
|
|
|
sdl_android_link_resources(${TEST}-apk-linked
|
|
MANIFEST "${generated_manifest_path}"
|
|
PACKAGE ${ANDROID_MANIFEST_PACKAGE}
|
|
RES_TARGETS SDL_test-resources ${TEST}-resources
|
|
TARGET_SDK_VERSION 31
|
|
)
|
|
|
|
set(CMAKE_JAVA_COMPILE_FLAGS "-encoding;utf-8")
|
|
set(classes_path "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${TEST}-java.dir/classes")
|
|
# Some CMake versions have a slow `cmake -E make_directory` implementation
|
|
if(NOT IS_DIRECTORY "${classes_path}")
|
|
execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory "${classes_path}")
|
|
endif()
|
|
set(OUT_JAR "${CMAKE_CURRENT_BINARY_DIR}/${TEST}.jar")
|
|
add_custom_command(
|
|
OUTPUT "${OUT_JAR}"
|
|
COMMAND ${CMAKE_COMMAND} -E rm -rf "${classes_path}"
|
|
COMMAND ${CMAKE_COMMAND} -E make_directory "${classes_path}"
|
|
COMMAND ${Java_JAVAC_EXECUTABLE}
|
|
-source 1.8 -target 1.8
|
|
-bootclasspath "$<TARGET_PROPERTY:SDL3::Jar,JAR_FILE>"
|
|
"${JAVA_PACKAGE_DIR}/SDLEntryTestActivity.java"
|
|
"${JAVA_PACKAGE_DIR}/SDLTestActivity.java"
|
|
$<TARGET_PROPERTY:${TEST}-apk-linked,JAVA_R>
|
|
-cp "$<TARGET_PROPERTY:SDL3::Jar,JAR_FILE>:${SDL_ANDROID_PLATFORM_ANDROID_JAR}"
|
|
-d "${classes_path}"
|
|
COMMAND ${Java_JAR_EXECUTABLE} cf "${OUT_JAR}" -C "${classes_path}" .
|
|
DEPENDS $<TARGET_PROPERTY:${TEST}-apk-linked,OUTPUTS> "$<TARGET_PROPERTY:SDL3::Jar,JAR_FILE>" "${JAVA_PACKAGE_DIR}/SDLTestActivity.java" "${JAVA_PACKAGE_DIR}/SDLEntryTestActivity.java"
|
|
)
|
|
add_custom_target(${TEST}-jar DEPENDS "${OUT_JAR}")
|
|
set_property(TARGET ${TEST}-jar PROPERTY OUTPUT "${OUT_JAR}")
|
|
|
|
set(dexworkdir "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${TEST}-dex.dir")
|
|
# Some CMake versions have a slow `cmake -E make_directory` implementation
|
|
if(NOT IS_DIRECTORY "${dexworkdir}")
|
|
execute_process(COMMAND "${CMAKE_COMMAND}" -E make_directory "${dexworkdir}")
|
|
endif()
|
|
set(classes_dex_base_name "classes.dex")
|
|
set(classes_dex "${dexworkdir}/${classes_dex_base_name}")
|
|
add_custom_command(
|
|
OUTPUT "${classes_dex}"
|
|
COMMAND SdlAndroid::d8
|
|
$<TARGET_PROPERTY:${TEST}-jar,OUTPUT>
|
|
$<TARGET_PROPERTY:SDL3::Jar,JAR_FILE>
|
|
--lib "${SDL_ANDROID_PLATFORM_ANDROID_JAR}"
|
|
--output "${dexworkdir}"
|
|
DEPENDS $<TARGET_PROPERTY:${TEST}-jar,OUTPUT> $<TARGET_PROPERTY:SDL3::Jar,JAR_FILE>
|
|
)
|
|
add_custom_target(${TEST}-dex DEPENDS "${classes_dex}")
|
|
set_property(TARGET ${TEST}-dex PROPERTY OUTPUT "${classes_dex}")
|
|
set_property(TARGET ${TEST}-dex PROPERTY OUTPUT_BASE_NAME "${classes_dex_base_name}")
|
|
|
|
sdl_add_to_apk_unaligned(${TEST}-unaligned-apk
|
|
APK_IN ${TEST}-apk-linked
|
|
OUTDIR "${CMAKE_CURRENT_BINARY_DIR}/intermediates"
|
|
ASSETS ${RESOURCE_FILES}
|
|
NATIVE_LIBS SDL3::SDL3-shared ${TEST}
|
|
DEX ${TEST}-dex
|
|
)
|
|
|
|
sdl_apk_align(${TEST}-aligned-apk ${TEST}-unaligned-apk
|
|
OUTDIR "${CMAKE_CURRENT_BINARY_DIR}/intermediates"
|
|
)
|
|
sdl_apk_sign(${TEST}-apk ${TEST}-aligned-apk
|
|
KEYSTORE SDL_test-debug-keystore
|
|
)
|
|
add_dependencies(sdl-test-apks ${TEST}-apk)
|
|
|
|
if(TARGET SdlAndroid::adb)
|
|
add_custom_target(install-${TEST}
|
|
COMMAND "${CMAKE_COMMAND}" -DACTION=install "-DAPKS=$<TARGET_PROPERTY:${TEST}-apk,OUTPUT>" -P "${SDL3_SOURCE_DIR}/cmake/android/SdlAndroidScript.cmake"
|
|
DEPENDS "${TEST}-apk"
|
|
)
|
|
add_custom_target(start-${TEST}
|
|
COMMAND "${ADB_BIN}" shell am start-activity -S "${ANDROID_MANIFEST_PACKAGE}/.SDLTestActivity"
|
|
)
|
|
add_custom_target(build-install-start-${TEST}
|
|
COMMAND "${CMAKE_COMMAND}" -DACTION=build-install-run "-DEXECUTABLES=${TEST}" "-DBUILD_FOLDER=${CMAKE_BINARY_DIR}" -P "${SDL3_SOURCE_DIR}/cmake/android/SdlAndroidScript.cmake"
|
|
)
|
|
endif()
|
|
|
|
list(APPEND packages "${ANDROID_MANIFEST_PACKAGE}")
|
|
list(APPEND install_targets install-${TEST})
|
|
endforeach()
|
|
|
|
if(TARGET SdlAndroid::adb)
|
|
add_custom_target(install-sdl-test-apks
|
|
DEPENDS ${install_targets}
|
|
VERBATIM
|
|
)
|
|
add_custom_target(uninstall-sdl-test-apks
|
|
COMMAND "${CMAKE_COMMAND}" "-DADB=$<TARGET_FILE:SdlAndroid::adb>" -DACTION=uninstall "-DPACKAGES=${packages}" -P "${SDL3_SOURCE_DIR}/cmake/android/SdlAndroidScript.cmake"
|
|
VERBATIM
|
|
)
|
|
endif()
|
|
endif()
|
|
endif()
|