tools: fail a .c that uses strlcpy without including compat/strl.h

modeline_edid.c called strlcpy with no <compat/strl.h> and reached
master: glibc 2.38 declares strlcpy and strlcat itself, so it built
clean here and passed both syntax-check passes, while MXE, clang and
the webOS toolchain - which have only libretro-common's declaration -
did not. Neither pass could have caught it, since both ask the host's
headers what exists.

A grep can, and does not care what the host provides: a .c that uses
strlcpy, strlcat, strlcpy_lit, strlcat_lit or strcasestr must include
the compat header itself rather than lean on whatever a project
header dragged in, which is the standing rule anyway. It runs as pass
0 of tools/mingw_syntax_check.sh, so it fires on the files being
checked before delivery and costs nothing.

Fourteen files were leaning on the transitive declaration and now
include it directly: the font driver and its freetype renderer, the
widgets, vulkan_common, the GX2, PS2 and OGA drivers, the Android
display server, the screensaver and cancel callbacks, the audio
driver, the test input and joypad drivers, and the webOS Wayland
helper. No behaviour changes; the ones this host can build were
checked, and the failures that remain there are the ones master
already had.
This commit is contained in:
LibretroAdmin authored and libretroadmin committed 2026-09-11 08:30:20 +02:00
1 parent e8fbf2beb8
commit df29e6046f
15 files changed
+59 -1

No files matched your search

+2
View File
@@ -59,6 +59,8 @@
#include <lists/string_list.h>
#include <lists/dir_list.h>
#include <compat/strl.h>
#ifdef HAVE_THREADS
#include "audio_thread_wrapper.h"
#endif
+2
View File
@@ -48,6 +48,8 @@
#ifdef _WIN32
#include <windows.h>
#include <compat/strl.h>
#endif
#define VENDOR_ID_AMD 0x1002
+2
View File
@@ -20,6 +20,8 @@
#include <stdlib.h>
#include <android/native_window.h>
#include <compat/strl.h>
#include "../../verbosity.h"
#include "../video_display_server.h"
#include "../../frontend/drivers/platform_unix.h"
+2
View File
@@ -27,6 +27,8 @@
#include <file/file_path.h>
#include <string/stdstring.h>
#include <compat/strl.h>
#include "../../driver.h"
#include "../../configuration.h"
#include "../../verbosity.h"
+2
View File
@@ -30,6 +30,8 @@
#include <libretro.h>
#include <compat/strl.h>
#ifdef HAVE_CONFIG_H
#include "../../config.h"
#endif
+2
View File
@@ -28,6 +28,8 @@
#include <libretro_gskit_ps2.h>
#include <boolean.h>
#include <compat/strl.h>
#include "../video_defines.h"
#include "../../driver.h"
#include "../../retroarch.h"
+2
View File
@@ -56,6 +56,8 @@ static FcConfig *fc_config = NULL;
#ifdef WIIU
#include <wiiu/os.h>
#include <compat/strl.h>
#endif
#include FT_FREETYPE_H
+2
View File
@@ -31,6 +31,8 @@
#include "video_thread_wrapper.h"
#include <retro_atomic.h>
#include <compat/strl.h>
/* ------------------------------------------------------------------
* Shared font file bytes.
*
+2
View File
@@ -29,6 +29,8 @@
#include <retro_math.h>
#include <features/features_cpu.h>
#include <compat/strl.h>
#include "gfx_display.h"
#include "gfx_widgets.h"
#include "font_driver.h"
+2
View File
@@ -43,6 +43,8 @@
#ifdef HAVE_USERLAND
#include <webos-helpers/libhelpers.h>
#include <compat/strl.h>
#include "formats/rjson.h"
HContext *g_register_ctx = NULL;
HContext *g_screensaver_ctx = NULL;
+2
View File
@@ -26,6 +26,8 @@
#include <formats/rjson.h>
#include <formats/rjson_stream.h>
#include <compat/strl.h>
#include "../input_driver.h"
#include "../input_keymaps.h"
#include "../../verbosity.h"
+2
View File
@@ -32,6 +32,8 @@
#include <formats/rjson.h>
#include <formats/rjson_stream.h>
#include <compat/strl.h>
#include "../../config.def.h"
#include "../../verbosity.h"
#include "../input_driver.h"
+2
View File
@@ -16,6 +16,8 @@
#include <file/file_path.h>
#include <string/stdstring.h>
#include <compat/strl.h>
#include "../menu_driver.h"
#include "../menu_cbs.h"
#include "../../audio/audio_driver.h"
+2
View File
@@ -22,6 +22,8 @@
#include <file/file_path.h>
#include <retro_inline.h>
#include <compat/strl.h>
#include "../verbosity.h"
#if defined(HAVE_CONFIG_H)
+31 -1
View File
@@ -78,9 +78,39 @@ C89FLAGS="-fsyntax-only -std=c89 -ansi -pedantic -Werror=pedantic \
C89CC_WIN32="${C89CC_WIN32:-i686-w64-mingw32-gcc}"
command -v "$C89CC_WIN32" >/dev/null 2>&1 || C89CC_WIN32=""
# Pass 0: the declaration a compiler here cannot miss.
#
# glibc 2.38 declares strlcpy and strlcat itself, so a .c that uses
# them without including <compat/strl.h> compiles clean on this box
# and on both passes below, then fails on MXE, clang and the webOS
# toolchain, where the only declaration is libretro-common's. That is
# how it reached master in modeline_edid.c. A grep is the only check
# that does not depend on what the host's headers happen to provide:
# a file that uses one of these must include the compat header
# itself, not lean on whatever a project header dragged in.
check_compat_include()
{
f="$1"
miss=""
if grep -qE '\b(strlcpy|strlcat|strlcpy_lit|strlcat_lit)[[:space:]]*\(' "$f" \
&& ! grep -q 'compat/strl\.h' "$f"; then
miss="compat/strl.h"
fi
if grep -qE '\bstrcasestr[[:space:]]*\(' "$f" \
&& ! grep -q 'compat/strcasestr\.h' "$f"; then
miss="$miss compat/strcasestr.h"
fi
[ -z "$miss" ] && return 0
echo "FAIL [decl] $f"
echo " uses a libretro-common string helper without including:$miss" \
| sed 's/^/ /'
return 1
}
fail=0; n=0
for f in $FILES; do
n=$((n+1))
check_compat_include "$f" || fail=1
# Only real errors, not warnings. A missing header named without a
# path (d3dkmthk.h: an optional platform header this box lacks) is
# forgiven; a missing header with a path component (../companion/x.h:
@@ -121,5 +151,5 @@ for f in $FILES; do
echo "FAIL [c89] $f"; echo "$err" | sed 's/^/ /'; fail=1
fi
done
[ $fail = 0 ] && echo "ok: $n translation units clean (win32 gnu99 + linux c89 pedantic)"
[ $fail = 0 ] && echo "ok: $n translation units clean (compat decls + win32 gnu99 + linux c89 pedantic)"
exit $fail