Skip to content

cmake: support building a shared SDL3 DOS executable#15459

Draft
madebr wants to merge 4 commits intolibsdl-org:mainfrom
madebr:dynamic-SDL3
Draft

cmake: support building a shared SDL3 DOS executable#15459
madebr wants to merge 4 commits intolibsdl-org:mainfrom
madebr:dynamic-SDL3

Conversation

@madebr
Copy link
Copy Markdown
Contributor

@madebr madebr commented Apr 25, 2026

This adds supports for building SDL3 as a "dynamically loadable executable module" (dxe) using dxe3gen. This util is usually part of a djgpp toolchain.

Everything builds and links, but there is one small, not insignificant problem: starting the test executables fail immediately with a page fault.
With this pr I hope DOS specialists can find out what's wrong with my approach.
At the bottom of this message, I've posted a small script showing the steps needed to build and use a DOS module.

My implementation works by wrapping the linker with the build-scripts/djgpp-dxe-linker-wrapper.py python script.
The scripts modifies the linker arguments to ones that dxe3gen can handle (for -Y for the import library.
Because of linker errors, I have to explicitly add -lc and crt0.o to the linker arguments. Perhaps that's part of the reason it's currently failing?

  • I confirm that I am the author of this code and release it to the SDL project under the Zlib license. This contribution does not contain code from other sources, including code generated by a Large Language Model ("AI").

Steps to create and use a dxe module:

#!/bin/bash

set -ex

: Source of module.dxe
cat >lib.c <<EOF
int library_function(void)
{
  return 42;
}
EOF

: Source of main.exe
cat >main.c <<EOF
#include <stdio.h>

extern int library_function(void);

int main(int argc, char *argv[])
{
  (void) argc;
  (void) argv;
  printf("library_function: %d\n", library_function());
  return 0;
}
EOF

: Compile and link module.dxe
i586-pc-msdosdjgpp-gcc -c lib.c -o lib.o
DJDIR=dontcare DXE_LD_LIBRARY_PATH=dontcare dxe3gen -o module.dxe -Y libmodule.a lib.o

: Compile and link main.exe
i586-pc-msdosdjgpp-gcc -c main.c -o main.o
i586-pc-msdosdjgpp-gcc main.o libmodule.a -o main.exe

In DOS, you can now use main.exe which will automatically load module.dxe.

@madebr madebr marked this pull request as draft April 25, 2026 19:42
@sezero
Copy link
Copy Markdown
Contributor

sezero commented Apr 25, 2026

-lc may be a bad idea. -lgcc (maybe -lm) is good.

See #15377 (comment) for a solution about missing libc symbols in SDL3.dxe: Might be implemented in SDL_main for dos.

These are the missing symbols in my gcc-3.4 build - dxe generated like:
dxe3gen -o SDL3.dxe -U --whole-archive libSDL3.a -lgcc

Details
_environ
___dj_stderr
___dj_stdin
___djgpp_base_address
___djgpp_nearptr_enable
___dpmi_free_physical_address_mapping
___dpmi_int
___dpmi_physical_address_mapping
___dpmi_simulate_real_mode_procedure_retf
__go32_dpmi_allocate_dos_memory
__go32_dpmi_chain_protected_mode_interrupt_vector
__go32_dpmi_free_dos_memory
__go32_dpmi_get_protected_mode_interrupt_vector
__go32_dpmi_lock_code
__go32_dpmi_lock_data
__go32_dpmi_set_protected_mode_interrupt_vector
__go32_info_block
__Exit
_abort
_acos
_acosf
_asin
_asinf
_atan
_atan2
_atan2f
_atanf
_atof
_atoi
_calloc
_ceil
_ceilf
_clearerr
_close
_closedir
_copysign
_copysignf
_cos
_cosf
_delay
_dosmemput
_errno
_exp
_expf
_fclose
_ferror
_fflush
_fgets
_fileno
_floor
_floorf
_fmod
_fmodf
_fopen
_fprintf
_fread
_free
_fseeko64
_fstat
_ftello64
_fwrite
_getcwd
_getenv
_gethostname
_getpagesize
_gettimeofday
_gmtime_r
_itoa
_localtime_r
_log
_log10
_log10f
_logf
_longjmp
_lround
_lroundf
_lseek
_malloc
_memcpy
_memmove
_memset
_mkdir
_modf
_modff
_opendir
_pow
_powf
_read
_readdir
_realloc
_remove
_rename
_round
_roundf
_scalbn
_scalbnf
_searchpath
_setenv
_setjmp
_sigaction
_sin
_sinf
_sqrt
_sqrtf
_stat
_strchr
_strcmp
_strerror
_strlcat
_strlcpy
_strlen
_strncmp
_strnlen
_strpbrk
_strrchr
_strstr
_strtod
_strtok_r
_strtol
_strtoll
_strtoul
_strtoull
_tan
_tanf
_trunc
_truncf
_uclock
_unsetenv
_vsnprintf
_vsscanf
_write

As for exporting only the SDL symbols: dxe3gen from cvs has support
for --exports <file.exp>
The macos exports file should be good for it here: satellite libs
has added support for that, but it never happened in SDL itself...

@jwt27
Copy link
Copy Markdown

jwt27 commented Apr 25, 2026

As for exporting only the SDL symbols: dxe3gen from cvs has support
for --exports <file.exp>

Just chiming in to mention: I have an Ubuntu PPA for the djgpp toolchain, specifically for Github Actions and other CI. It includes dxe3gen (and libc and other utils) built from CVS sources. This may be useful here.

https://launchpad.net/~jwt27/+archive/ubuntu/djgpp-toolchain

Comment thread include/SDL3/SDL_main_impl.h Outdated
Comment thread include/SDL3/SDL_main_impl.h Outdated
@sezero
Copy link
Copy Markdown
Contributor

sezero commented Apr 26, 2026

P.S.: I can't build this branch at all: linkage fails with unrecognized switch -shared with my gcc-3.4 toolchain.

@madebr
Copy link
Copy Markdown
Contributor Author

madebr commented Apr 26, 2026

P.S.: I can't build this branch at all: linkage fails with unrecognized switch -shared with my gcc-3.4 toolchain.

I pushed a change that filters it out.
The build-scripts/djgpp-dxe-linker-wrapper.py script removes and adds a few arguments if you need to change more things.

@sezero
Copy link
Copy Markdown
Contributor

sezero commented Apr 26, 2026

P.S.: I can't build this branch at all: linkage fails with unrecognized switch -shared with my gcc-3.4 toolchain.

I pushed a change that filters it out. The build-scripts/djgpp-dxe-linker-wrapper.py script removes and adds a few arguments if you need to change more things.

Still no joy:

[ 54%] Linking C shared library SDL3.dxe
i586-pc-msdosdjgpp-gcc: unrecognized option `-shared'
/usr/local/cross-djgpp/lib/gcc/i586-pc-msdosdjgpp/3.4.6/../../../../i586-pc-msdosdjgpp/lib/crt0.o:crt0.s:(.data+0xc2): undefined reference to `_main'
/usr/local/cross-djgpp/lib/gcc/i586-pc-msdosdjgpp/3.4.6/../../../../i586-pc-msdosdjgpp/lib/libc.a(crt1.o):crt1.c:(.text+0x450): undefined reference to `_main'
collect2: ld returned 1 exit status
make[2]: *** [SDL3.dxe] Error 1
make[1]: *** [CMakeFiles/SDL3-shared.dir/all] Error 2
make: *** [all] Error 2

Here is the tar ball of my configuration directory: b.tar.gz

This was with cmake-3.18. Curiously, cmake-4.0 works OK...

@madebr
Copy link
Copy Markdown
Contributor Author

madebr commented Apr 26, 2026

Latest version I pushed works again for me, and is also valid c++.

@madebr
Copy link
Copy Markdown
Contributor Author

madebr commented Apr 26, 2026

This was with cmake-3.18. Curiously, cmake-4.0 works OK...

I'm using this property, which is 3.21+. Perhaps that's it. I'll add a CMake version check.

No wait, I use generator expressions as arguments. I need 3.27.

@madebr
Copy link
Copy Markdown
Contributor Author

madebr commented Apr 26, 2026

Apply this patch to see the actual dxe3gen command:

--- a/build-scripts/djgpp-dxe-linker-wrapper.py
+++ b/build-scripts/djgpp-dxe-linker-wrapper.py
@@ -70,6 +70,10 @@ if not "-nostlib" in original_linker_args:
 os.environ["DXE_LD_LIBRARY_PATH"] = "dontcare"
 os.environ["DJDIR"] = "dontcare"
 
+print("dxe3gen command:")
+import pprint
+pprint.pprint(dxe3gen_command)
+
 process_result = subprocess.run(dxe3gen_command)
 
 raise SystemExit(process_result.returncode)

@sezero
Copy link
Copy Markdown
Contributor

sezero commented Apr 26, 2026

Apply this patch to see the actual dxe3gen command:

Here goes, from a cmake-4.0 run:

Details
dxe3gen command:
['/usr/local/cross-djgpp/bin/dxe3gen',
 '-o',
 'SDL3.dxe',
 '-U',
 '-Y',
 '/tmp/SDL-sezero/b/libSDL3.dxe.a',
 '-L/usr/local/cross-djgpp/lib/gcc/i586-pc-msdosdjgpp/3.4.6/',
 '-L/usr/local/cross-djgpp/lib/gcc/i586-pc-msdosdjgpp/3.4.6//lib',
 '-L/usr/local/cross-djgpp/lib/gcc/i586-pc-msdosdjgpp/3.4.6/../../../../i586-pc-msdosdjgpp/lib//..',
 '-L/usr/local/cross-djgpp/lib/gcc/i586-pc-msdosdjgpp/3.4.6/../../../../i586-pc-msdosdjgpp/lib//../lib',
 '-L/usr/local/cross-djgpp/lib/gcc/i586-pc-msdosdjgpp/3.4.6/',
 '-L/usr/local/cross-djgpp/lib/gcc/i586-pc-msdosdjgpp/3.4.6//lib',
 '-L/usr/local/cross-djgpp/lib/gcc/i586-pc-msdosdjgpp/3.4.6/../../../../i586-pc-msdosdjgpp/lib//..',
 '-L/usr/local/cross-djgpp/lib/gcc/i586-pc-msdosdjgpp/3.4.6/../../../../i586-pc-msdosdjgpp/lib//../lib',
 'CMakeFiles/SDL3-shared.dir/src/SDL.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/SDL_assert.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/SDL_error.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/SDL_guid.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/SDL_hashtable.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/SDL_hints.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/SDL_list.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/SDL_log.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/SDL_properties.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/SDL_utils.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/atomic/SDL_atomic.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/atomic/SDL_spinlock.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/audio/SDL_audio.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/audio/SDL_audiocvt.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/audio/SDL_audiodev.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/audio/SDL_audioqueue.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/audio/SDL_audioresample.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/audio/SDL_audiotypecvt.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/audio/SDL_mixer.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/audio/SDL_wave.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/camera/SDL_camera.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/core/SDL_core_unsupported.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/cpuinfo/SDL_cpuinfo.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/dynapi/SDL_dynapi.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/events/SDL_categories.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/events/SDL_clipboardevents.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/events/SDL_displayevents.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/events/SDL_dropevents.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/events/SDL_events.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/events/SDL_eventwatch.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/events/SDL_keyboard.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/events/SDL_keymap.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/events/SDL_keysym_to_keycode.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/events/SDL_keysym_to_scancode.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/events/SDL_mouse.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/events/SDL_pen.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/events/SDL_quit.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/events/SDL_scancode_tables.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/events/SDL_touch.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/events/SDL_windowevents.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/events/imKStoUCS.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/filesystem/SDL_filesystem.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/gpu/SDL_gpu.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/gpu/xr/SDL_gpu_openxr.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/gpu/xr/SDL_openxrdyn.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/haptic/SDL_haptic.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/hidapi/SDL_hidapi.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/io/SDL_asyncio.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/io/SDL_iostream.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/io/generic/SDL_asyncio_generic.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/joystick/SDL_gamepad.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/joystick/SDL_joystick.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/joystick/SDL_steam_virtual_gamepad.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/joystick/controller_type.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/locale/SDL_locale.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/main/SDL_main_callbacks.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/main/SDL_runapp.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/misc/SDL_libusb.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/misc/SDL_url.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/power/SDL_power.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/render/SDL_render.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/render/SDL_render_unsupported.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/render/SDL_yuv_sw.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/render/direct3d/SDL_render_d3d.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/render/direct3d/SDL_shaders_d3d.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/render/direct3d11/SDL_render_d3d11.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/render/direct3d11/SDL_shaders_d3d11.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/render/direct3d12/SDL_render_d3d12.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/render/direct3d12/SDL_shaders_d3d12.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/render/gpu/SDL_pipeline_gpu.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/render/gpu/SDL_render_gpu.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/render/gpu/SDL_shaders_gpu.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/render/ngage/SDL_render_ngage.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/render/opengl/SDL_render_gl.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/render/opengl/SDL_shaders_gl.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/render/opengles2/SDL_render_gles2.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/render/opengles2/SDL_shaders_gles2.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/render/ps2/SDL_render_ps2.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/render/psp/SDL_render_psp.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/render/software/SDL_blendfillrect.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/render/software/SDL_blendline.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/render/software/SDL_blendpoint.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/render/software/SDL_drawline.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/render/software/SDL_drawpoint.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/render/software/SDL_render_sw.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/render/software/SDL_triangle.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/render/vitagxm/SDL_render_vita_gxm.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/render/vitagxm/SDL_render_vita_gxm_memory.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/render/vitagxm/SDL_render_vita_gxm_tools.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/render/vulkan/SDL_render_vulkan.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/render/vulkan/SDL_shaders_vulkan.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/sensor/SDL_sensor.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/stdlib/SDL_crc16.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/stdlib/SDL_crc32.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/stdlib/SDL_getenv.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/stdlib/SDL_iconv.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/stdlib/SDL_malloc.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/stdlib/SDL_memcpy.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/stdlib/SDL_memmove.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/stdlib/SDL_memset.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/stdlib/SDL_mslibc.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/stdlib/SDL_murmur3.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/stdlib/SDL_qsort.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/stdlib/SDL_random.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/stdlib/SDL_stdlib.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/stdlib/SDL_string.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/stdlib/SDL_strtokr.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/storage/SDL_storage.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/thread/SDL_thread.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/time/SDL_time.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/timer/SDL_timer.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/video/SDL_RLEaccel.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/video/SDL_blit.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/video/SDL_blit_0.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/video/SDL_blit_1.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/video/SDL_blit_A.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/video/SDL_blit_N.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/video/SDL_blit_auto.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/video/SDL_blit_copy.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/video/SDL_blit_slow.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/video/SDL_bmp.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/video/SDL_clipboard.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/video/SDL_egl.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/video/SDL_fillrect.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/video/SDL_pixels.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/video/SDL_rect.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/video/SDL_rotate.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/video/SDL_stb.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/video/SDL_stretch.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/video/SDL_surface.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/video/SDL_video.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/video/SDL_video_unsupported.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/video/SDL_vulkan_utils.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/video/SDL_yuv.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/video/yuv2rgb/yuv_rgb_lsx.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/video/yuv2rgb/yuv_rgb_sse.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/video/yuv2rgb/yuv_rgb_std.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/audio/dummy/SDL_dummyaudio.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/audio/disk/SDL_diskaudio.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/joystick/virtual/SDL_virtualjoystick.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/video/dummy/SDL_nullevents.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/video/dummy/SDL_nullframebuffer.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/video/dummy/SDL_nullvideo.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/main/dos/SDL_sysmain_runapp.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/core/dos/SDL_dos.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/core/dos/SDL_dos_scheduler.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/audio/dos/SDL_dosaudio_sb.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/video/dos/SDL_dosevents.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/video/dos/SDL_dosframebuffer.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/video/dos/SDL_dosmodes.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/video/dos/SDL_dosmouse.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/video/dos/SDL_dosvideo.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/filesystem/posix/SDL_sysfsops.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/filesystem/dos/SDL_sysfilesystem.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/time/unix/SDL_systime.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/timer/dos/SDL_systimer.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/joystick/dos/SDL_sysjoystick.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/thread/dos/SDL_sysmutex.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/thread/dos/SDL_syssem.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/thread/dos/SDL_systhread.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/thread/dos/SDL_systls.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/thread/generic/SDL_syscond.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/thread/generic/SDL_sysrwlock.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/dialog/SDL_dialog.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/process/SDL_process.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/tray/SDL_tray_utils.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/haptic/dummy/SDL_syshaptic.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/sensor/dummy/SDL_dummysensor.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/loadso/dummy/SDL_sysloadso.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/storage/generic/SDL_genericstorage.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/locale/dummy/SDL_syslocale.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/misc/dummy/SDL_sysurl.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/dialog/dummy/SDL_dummydialog.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/process/dummy/SDL_dummyprocess.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/tray/dummy/SDL_tray.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/camera/dummy/SDL_camera_dummy.c.obj',
 'CMakeFiles/SDL3-shared.dir/src/main/generic/SDL_sysmain_callbacks.c.obj',
 '-lm',
 'libSDL_uclibc.a',
 '-lgcc']
[100%] Built target SDL3-shared

@madebr
Copy link
Copy Markdown
Contributor Author

madebr commented Apr 26, 2026

Apply this patch to see the actual dxe3gen command:

Here goes, from a cmake-4.0 run:

Ignoring absolute paths, that's identical to mine.

@sezero
Copy link
Copy Markdown
Contributor

sezero commented Apr 26, 2026

P.S.: I get these annoying warnings from SDL_test_common.c:

Details
/tmp/SDL-sezero/src/test/SDL_test_common.c: In function `SDLTest_CommonInit':
/tmp/SDL-sezero/src/test/SDL_test_common.c:1232: warning: unsigned int format, SDL_DisplayID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1250: warning: unsigned int format, Uint32 arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1251: warning: unsigned int format, Uint32 arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1252: warning: unsigned int format, Uint32 arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1254: warning: unsigned int format, Uint32 arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1273: warning: unsigned int format, Uint32 arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1275: warning: unsigned int format, Uint32 arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1277: warning: unsigned int format, Uint32 arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1279: warning: unsigned int format, Uint32 arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c: In function `SDLTest_PrintEvent':
/tmp/SDL-sezero/src/test/SDL_test_common.c:1593: warning: unsigned int format, SDL_DisplayID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1599: warning: unsigned int format, SDL_DisplayID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1607: warning: unsigned int format, SDL_DisplayID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1612: warning: unsigned int format, SDL_DisplayID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1612: warning: int format, Sint32 arg (arg 3)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1612: warning: int format, Sint32 arg (arg 4)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1616: warning: unsigned int format, SDL_DisplayID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1616: warning: int format, Sint32 arg (arg 3)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1616: warning: int format, Sint32 arg (arg 4)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1620: warning: unsigned int format, SDL_DisplayID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1624: warning: unsigned int format, SDL_DisplayID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1628: warning: unsigned int format, SDL_DisplayID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1631: warning: unsigned int format, SDL_WindowID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1634: warning: unsigned int format, SDL_WindowID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1637: warning: unsigned int format, SDL_WindowID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1641: warning: unsigned int format, SDL_WindowID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1641: warning: int format, Sint32 arg (arg 3)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1641: warning: int format, Sint32 arg (arg 4)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1645: warning: unsigned int format, SDL_WindowID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1645: warning: int format, Sint32 arg (arg 3)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1645: warning: int format, Sint32 arg (arg 4)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1649: warning: unsigned int format, SDL_WindowID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1649: warning: int format, Sint32 arg (arg 3)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1649: warning: int format, Sint32 arg (arg 4)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1653: warning: unsigned int format, SDL_WindowID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1660: warning: unsigned int format, SDL_WindowID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1664: warning: unsigned int format, SDL_WindowID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1667: warning: unsigned int format, SDL_WindowID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1670: warning: unsigned int format, SDL_WindowID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1673: warning: unsigned int format, SDL_WindowID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1676: warning: unsigned int format, SDL_WindowID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1680: warning: unsigned int format, SDL_WindowID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1684: warning: unsigned int format, SDL_WindowID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1687: warning: unsigned int format, SDL_WindowID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1690: warning: unsigned int format, SDL_WindowID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1693: warning: unsigned int format, SDL_WindowID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1696: warning: unsigned int format, SDL_WindowID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1696: warning: int format, Sint32 arg (arg 3)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1699: warning: unsigned int format, SDL_WindowID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1702: warning: unsigned int format, SDL_WindowID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1705: warning: unsigned int format, SDL_WindowID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1708: warning: unsigned int format, SDL_WindowID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1711: warning: unsigned int format, SDL_WindowID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1714: warning: unsigned int format, SDL_WindowID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1718: warning: unsigned int format, SDL_KeyboardID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1722: warning: unsigned int format, SDL_KeyboardID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1740: warning: unsigned int format, SDL_WindowID arg (arg 3)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1740: warning: unsigned int format, SDL_Keycode arg (arg 6)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1745: warning: unsigned int format, SDL_WindowID arg (arg 3)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1749: warning: unsigned int format, SDL_WindowID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1753: warning: unsigned int format, SDL_WindowID arg (arg 3)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1760: warning: unsigned int format, SDL_MouseID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1764: warning: unsigned int format, SDL_MouseID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1770: warning: unsigned int format, SDL_WindowID arg (arg 6)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1775: warning: unsigned int format, SDL_WindowID arg (arg 6)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1780: warning: unsigned int format, SDL_WindowID arg (arg 6)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1784: warning: unsigned int format, SDL_WindowID arg (arg 5)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1788: warning: unsigned int format, SDL_JoystickID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1792: warning: unsigned int format, SDL_JoystickID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1798: warning: unsigned int format, SDL_JoystickID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1803: warning: int format, SDL_JoystickID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1838: warning: unsigned int format, SDL_JoystickID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1842: warning: unsigned int format, SDL_JoystickID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1846: warning: unsigned int format, SDL_JoystickID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1850: warning: unsigned int format, SDL_JoystickID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1854: warning: unsigned int format, SDL_JoystickID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1858: warning: unsigned int format, SDL_JoystickID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1862: warning: unsigned int format, SDL_JoystickID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1869: warning: unsigned int format, SDL_JoystickID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1874: warning: unsigned int format, SDL_JoystickID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1879: warning: unsigned int format, SDL_JoystickID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1915: warning: unsigned int format, SDL_WindowID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1918: warning: unsigned int format, SDL_WindowID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1921: warning: unsigned int format, SDL_WindowID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1943: warning: unsigned int format, SDL_WindowID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1946: warning: unsigned int format, SDL_WindowID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1949: warning: unsigned int format, SDL_WindowID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1952: warning: unsigned int format, SDL_WindowID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1960: warning: unsigned int format, SDL_AudioDeviceID arg (arg 3)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1965: warning: unsigned int format, SDL_AudioDeviceID arg (arg 3)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1970: warning: unsigned int format, SDL_AudioDeviceID arg (arg 3)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1974: warning: unsigned int format, SDL_CameraID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1978: warning: unsigned int format, SDL_CameraID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1982: warning: unsigned int format, SDL_CameraID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1986: warning: unsigned int format, SDL_CameraID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1990: warning: unsigned int format, SDL_SensorID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1994: warning: unsigned int format, SDL_PenID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:1998: warning: unsigned int format, SDL_PenID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:2002: warning: unsigned int format, SDL_PenID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:2006: warning: unsigned int format, SDL_PenID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:2010: warning: unsigned int format, SDL_PenID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:2014: warning: unsigned int format, SDL_PenID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:2018: warning: unsigned int format, SDL_PenID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:2022: warning: unsigned int format, SDL_PenID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:2031: warning: int format, Sint32 arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c:2034: warning: unsigned int format, Uint32 arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c: In function `SDLTest_CommonEventMainCallbacks':
/tmp/SDL-sezero/src/test/SDL_test_common.c:2328: warning: unsigned int format, SDL_DisplayID arg (arg 2)
/tmp/SDL-sezero/src/test/SDL_test_common.c: In function `SDLTest_CommonDrawWindowInfo':
/tmp/SDL-sezero/src/test/SDL_test_common.c:2834: warning: unsigned int format, SDL_DisplayID arg (arg 4)

Reason is djgpp int32_t is long, but that source doesn't include inttypes.h,
therefore SDL defaults to "u" for SDL_PRI_UINT32.

@madebr
Copy link
Copy Markdown
Contributor Author

madebr commented Apr 26, 2026

Reason is dlgpp int32_t is long, but that source doesn't include inttypes.h, therefore SDL defaults to "u" for SDL_PRI_UINT32.

__STDC_VERSION__ is 199901L on the version used in ci, so inttypes.h is included there.
I can reproduce your warnings when doing set_property(TARGET SDL3_test PROPERTY C_STANDARD 90) (-std=gnu90).

@madebr
Copy link
Copy Markdown
Contributor Author

madebr commented Apr 26, 2026

Is this a valid patch? Or completely inappropriate use of __ILP32__?

--- a/include/SDL3/SDL_stdinc.h
+++ b/include/SDL3/SDL_stdinc.h
@@ -774,23 +774,35 @@ typedef Sint64 SDL_Time;
 #ifdef PRId32
 #define SDL_PRIs32 PRId32
 #else
+#ifdef __ILP32__
+#define SDL_PRIs32 "ld"
+#else
 #define SDL_PRIs32 "d"
 #endif
 #endif
+#endif
 #ifndef SDL_PRIu32
 #ifdef PRIu32
 #define SDL_PRIu32 PRIu32
 #else
+#ifdef __ILP32__
+#define SDL_PRIu32 "lu"
+#else
 #define SDL_PRIu32 "u"
 #endif
 #endif
+#endif
 #ifndef SDL_PRIx32
 #ifdef PRIx32
 #define SDL_PRIx32 PRIx32
 #else
+#ifdef __ILP32__
+#define SDL_PRIx32 "lx"
+#else
 #define SDL_PRIx32 "x"
 #endif
 #endif
+#endif
 #ifndef SDL_PRIX32
 #ifdef PRIX32
 #define SDL_PRIX32 PRIX32

@sezero
Copy link
Copy Markdown
Contributor

sezero commented Apr 26, 2026

Is this a valid patch? Or completely inappropriate use of __ILP32__?

No, it doesn't look correct to me.

@sezero
Copy link
Copy Markdown
Contributor

sezero commented Apr 26, 2026

__STDC_VERSION__ is 199901L on the version used in ci, so inttypes.h is included there

Why don't we explicitly require C99+ for SDL_test, like we do for the normal sources?

@madebr
Copy link
Copy Markdown
Contributor Author

madebr commented Apr 26, 2026

__STDC_VERSION__ is 199901L on the version used in ci, so inttypes.h is included there

Why don't we explicitly require C99+ for SDL_test, like we do for the normal sources?

I guess because SDL_test did not see much development that required the more convenient c99.
We still need to do something about the headers: this is visible for user applications. The following code in c90 user code emits a warning:

    Uint32 c = 42;
    SDL_Log("Uint32 c = %" SDL_PRIu32, c);

@sezero
Copy link
Copy Markdown
Contributor

sezero commented Apr 26, 2026

__STDC_VERSION__ is 199901L on the version used in ci, so inttypes.h is included there

Why don't we explicitly require C99+ for SDL_test, like we do for the normal sources?

I guess because SDL_test did not see much development that required the more convenient c99.

I say we should

We still need to do something about the headers: this is visible for user applications. The following code in c90 user code emits a warning:

    Uint32 c = 42;
    SDL_Log("Uint32 c = %" SDL_PRIu32, c);

That's user code where user can explicitly include inttypes.h, or define SDL_INCLUDE_INTTYPES_H, therefore not much of an issue IMO.

@madebr
Copy link
Copy Markdown
Contributor Author

madebr commented Apr 26, 2026

Doing the SDL_INCLUDE_INTTYPES_H macro, I get a warning about the SDL_Swap32 macro (__builtin_bswap32 actually) returning a unsigned int instead of long unsigned int in testplatform.c: its output is used directly in SDL_Log.
Adding a cast fixes the warning. Where does it belong? To the macro, or in testplatform.c?

@sezero
Copy link
Copy Markdown
Contributor

sezero commented Apr 26, 2026

Adding a cast fixes the warning. Where does it belong? To the macro, or in testplatform.c?

An (Uint32) cast to the macro, I guess..

madebr added 4 commits April 26, 2026 21:43
This fixes a compile warning when using the output of SDL_Swap32
directly using the SDL_PRIu32 macro in C90 mode:
testplatform.c:158:17: warning: format '%lX' expects argument of
type 'long unsigned int', but argument 3 has type 'unsigned int' [-Wformat=]
  158 |         SDL_Log("Value 32 = 0x%" SDL_PRIX32 ", swapped = 0x%" SDL_PRIX32,
      |
Comment thread test/CMakeLists.txt
Comment thread CMakeLists.txt
SDL_AddCommonCompilerFlags(SDL3_test)
target_compile_definitions(SDL3_test PRIVATE "$<$<CONFIG:Debug>:DEBUG>")
if("c_std_99" IN_LIST CMAKE_C_COMPILE_FEATURES)
target_compile_features(SDL3_test PRIVATE c_std_99)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest that you apply this already, w/o this P/R

@sezero
Copy link
Copy Markdown
Contributor

sezero commented Apr 26, 2026

Just tested draw.exe and platform.exe under dosbox 0.74: they run.

P.S.: Adapting the following to your python ld wrapper:

grep SDL_ ../src/dynapi/SDL_dynapi.sym | sed -e s/SDL_/_SDL_/g | sed -e s/\;//g > SDL3.exp

... and adding --exports /path/to/SDL3.exp will generate a smaller dxe.
(Related: #15460 )

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants