Fix build with SWIG 4.4

SWIG 4.4 has dropped the usage of SWIG_NULLPTR again, which means we can't
rely on its presence to identify SWIG >= 4.2.0

Generate a swig_version.h by parsing the output of `swig -version` and
writing this in a hex representation

Fixes #1979
This commit is contained in:
Dominique Leuenberger
2025-12-02 11:10:27 +01:00
committed by Alexey Sokolov
parent 18416d7df6
commit 49af1c8d53
3 changed files with 71 additions and 8 deletions

View File

@@ -29,6 +29,17 @@ if(APPLE)
endif()
if(SWIG_FOUND)
set(SWIG_VERSION_HEADER "${CMAKE_CURRENT_BINARY_DIR}/swig_version.h")
add_custom_command(
OUTPUT "${SWIG_VERSION_HEADER}"
COMMAND ${CMAKE_COMMAND}
-DSWIG_EXECUTABLE=${SWIG_EXECUTABLE}
-DSWIG_VERSION_HEADER=${SWIG_VERSION_HEADER}
-P "${CMAKE_CURRENT_SOURCE_DIR}/generate_swig_version.cmake"
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/generate_swig_version.cmake"
)
add_custom_command(
OUTPUT "pyfunctions.cpp"
COMMAND "${PERL_EXECUTABLE}"
@@ -36,7 +47,7 @@ if(SWIG_FOUND)
"${CMAKE_CURRENT_SOURCE_DIR}/functions.in"
"pyfunctions.cpp"
VERBATIM
DEPENDS codegen.pl functions.in)
DEPENDS codegen.pl functions.in "${SWIG_VERSION_HEADER}")
add_custom_command(
OUTPUT "swigpyrun.h"
@@ -98,7 +109,7 @@ endfunction()
add_custom_target(modpython_dist
COMMAND "${CMAKE_COMMAND}" -E tar cz
"${CMAKE_CURRENT_SOURCE_DIR}/generated.tar.gz"
"swigpyrun.h" "znc_core.py" "modpython_biglib.cpp" "pyfunctions.cpp"
DEPENDS swigpyrun.h znc_core.py modpython_biglib.cpp pyfunctions.cpp
"swigpyrun.h" "znc_core.py" "modpython_biglib.cpp" "pyfunctions.cpp" "${SWIG_VERSION_HEADER}"
DEPENDS swigpyrun.h znc_core.py modpython_biglib.cpp pyfunctions.cpp "${SWIG_VERSION_HEADER}"
VERBATIM)
add_dependencies(modpython_dist copy_csocket_h)

View File

@@ -49,6 +49,8 @@ print $out <<'EOF';
* Don't change it manually. *
***************************************************************************/
#include "swig_version.h"
namespace {
inline swig_type_info* ZNC_SWIG_pchar_descriptor(void) {
static int init = 0;
@@ -60,11 +62,8 @@ namespace {
return info;
}
// SWIG 4.2.0 replaced SWIG_Python_str_AsChar with SWIG_PyUnicode_AsUTF8AndSize.
// SWIG doesn't provide any good way to detect SWIG version (other than parsing
// `swig -version`), but it also introduced SWIG_NULLPTR in 4.2.0.
// So let's abuse that define to do different code for new SWIG.
#ifdef SWIG_NULLPTR
// SWIG_VERSION is defined as 0x040200 for 4.2.0.
#if defined(SWIG_VERSION) && SWIG_VERSION >= 0x040200
// This is copied/adapted from SWIG 4.2.0 from pystrings.swg
inline int ZNC_SWIG_AsCharPtrAndSize(PyObject *obj, char** cptr, size_t* psize, int *alloc) {
#if PY_VERSION_HEX>=0x03000000

View File

@@ -0,0 +1,53 @@
# generate_swig_version.cmake
execute_process(
COMMAND ${SWIG_EXECUTABLE} -version
OUTPUT_VARIABLE SWIG_OUTPUT
ERROR_VARIABLE SWIG_ERROR
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_STRIP_TRAILING_WHITESPACE
)
set(FULL_OUTPUT "${SWIG_OUTPUT}\n${SWIG_ERROR}")
string(REGEX MATCH "SWIG Version ([0-9]+)\\.([0-9]+)\\.([0-9]+)" MATCH_FOUND "${FULL_OUTPUT}")
if(MATCH_FOUND)
# Extract capture groups
set(SWIG_VERSION_MAJOR ${CMAKE_MATCH_1})
set(SWIG_VERSION_MINOR ${CMAKE_MATCH_2})
set(SWIG_VERSION_PATCH ${CMAKE_MATCH_3})
message(STATUS "Found SWIG Version: ${SWIG_VERSION_MAJOR}.${SWIG_VERSION_MINOR}.${SWIG_VERSION_PATCH}")
# Format: 0x<MAJ><MIN><PATCH> (assuming 8 bits per component)
# Calculation: (Major << 16) | (Minor << 8) | Patch
math(EXPR VERSION_NUM
"(${SWIG_VERSION_MAJOR} << 16) + (${SWIG_VERSION_MINOR} << 8) + ${SWIG_VERSION_PATCH}"
OUTPUT_FORMAT HEXADECIMAL
)
set(HEADER_FILE "swig_version.h")
file(WRITE ${SWIG_VERSION_HEADER}
"// Auto-generated by CMake
#ifndef SWIG_VERSION_META_H
#define SWIG_VERSION_META_H
#define SWIG_VERSION_MAJOR ${SWIG_VERSION_MAJOR}
#define SWIG_VERSION_MINOR ${SWIG_VERSION_MINOR}
#define SWIG_VERSION_PATCH ${SWIG_VERSION_PATCH}
// Hex format 0xMAJMINPAT (e.g. 4.1.0 -> 0x40100)
#define SWIG_VERSION ${VERSION_NUM}
#endif // SWIG_VERSION_META_H
"
)
message(STATUS "Generated ${HEADER_FILE} with version ${VERSION_NUM}")
else()
message(WARNING "Could not parse SWIG version from output:\n${FULL_OUTPUT}")
endif()