From 3b8aa0487e55c51502cdb56dfdb0a1ff5d045797 Mon Sep 17 00:00:00 2001 From: Peter Knowles Date: Sat, 31 Oct 2026 14:57:33 +0000 Subject: [PATCH] CMake: check that the POSIX regex functions link, not just regex.h Finding regex.h was taken to mean that regcomp() etc. are available. On some systems the header belongs to a separate library that is not linked by default: on MSYS2 (MinGW-w64) regex.h comes from libsystre (TRE), whose regex.h defines regcomp etc. as macros for tre_regcomp etc., so GKlib compiles but fails to link (undefined tre_regcomp). Now compile and link a small program that calls regcomp(), regexec(), regerror() and regfree(). If that fails with the C library alone, try systre, tre, gnurx and regex, and add the first that works to GKlib's public link interface (as for libexecinfo). If none works, fall back to GKlib's own implementation (gkregex) instead of building a library that cannot be linked. check_symbol_exists() is not used, because it accepts a macro and so cannot detect the TRE case. The GKREGEX option (make config gkregex=set) was declared but had no effect; it now selects gkregex unconditionally. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01HhHuoyV4eedKKTaFRt9Wfi --- CMakeLists.txt | 47 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cc386c1..ed8deb1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -141,8 +141,50 @@ if(PCRE) message(WARNING "PCRE was requested, but is not available") endif() endif() +# regcomp() and friends are in libc on glibc, macOS and the BSDs, but on some +# systems regex.h belongs to a separate library that is not linked by default +# (e.g. libsystre/libtre on MSYS2, libgnurx on MinGW). The header alone is not +# enough to link, so confirm the functions are linkable and record the extra +# library when one is required; otherwise fall back to GKlib's own regex +# implementation (gkregex), which is also used when GKREGEX is set. The test +# calls the functions rather than using check_symbol_exists(), which accepts a +# macro, and TRE's regex.h defines regcomp etc. as macros for tre_regcomp etc. +set(REGEX_LIBRARY "") +set(GKLIB_REGEX_TEST_SOURCE " +#include +#include +int main(void) { + regex_t re; regmatch_t m[1]; char buf[8]; int rc; + rc = regcomp(&re, \"a\", REG_EXTENDED); + if (rc != 0) return (int)regerror(rc, &re, buf, sizeof(buf)); + rc = regexec(&re, \"a\", 1, m, 0); + regfree(&re); + return rc; +}") if(NOT HAVE_PCREPOSIX_H) - check_include_file(regex.h HAVE_REGEX_H) + if(GKREGEX) + set(HAVE_REGEX_H FALSE) + else() + check_include_file(regex.h HAVE_REGEX_H) + endif() + if(HAVE_REGEX_H) + check_c_source_compiles("${GKLIB_REGEX_TEST_SOURCE}" GKLIB_REGEX_IN_LIBC) + if(NOT GKLIB_REGEX_IN_LIBC) + foreach(lib systre tre gnurx regex) + set(CMAKE_REQUIRED_LIBRARIES ${lib}) + check_c_source_compiles("${GKLIB_REGEX_TEST_SOURCE}" + GKLIB_REGEX_IN_LIB${lib}) + unset(CMAKE_REQUIRED_LIBRARIES) + if(GKLIB_REGEX_IN_LIB${lib}) + set(REGEX_LIBRARY ${lib}) + break() + endif() + endforeach() + if(NOT REGEX_LIBRARY) + set(HAVE_REGEX_H FALSE) + endif() + endif() + endif() if(NOT HAVE_REGEX_H) set(USE_GKREGEX ON) endif() @@ -207,7 +249,8 @@ target_compile_options(${PROJECT_NAME} target_link_libraries(${PROJECT_NAME} PUBLIC $<$:OpenMP::OpenMP_C> - ${EXECINFO_LIBRARY}) + ${EXECINFO_LIBRARY} + ${REGEX_LIBRARY}) #------------------------------------------------------------------------------- # APPS configuration