Swig defines SWIG_init with a hyphen in debug mode on windows, resulting in autogenerated C++ code that is invalid

Question:

On Windows, I am using cmake, swig, and visual studio to build a python wrapper for my library. In Release mode everything works fine. In Debug, the generated code contains this line:

#define SWIG_init PyInit__myproject-gd

So Debug appends the -gd which is not there in Release. The build goes on to use that symbol as a function name, which is not valid C++ because a hyphen is not allowed in an identifier. And so this line…

SWIG_init(void) {

…causes the build to fail with this error message:

C:xxxmyprojectPYTHON_wrap.cxx(807935,1): error C2143: syntax error: missing ';' before '-'
C:xxxmyprojectPYTHON_wrap.cxx(807935,1): error C2059: syntax error: '-'
C:xxxmyprojectPYTHON_wrap.cxx(807935,17): error C2143: syntax error: missing ';' before '{'
C:xxxmyprojectPYTHON_wrap.cxx(807935,17): error C2447: '{': missing function header (old-style formal list?)

How do I fix this?

Edit:

In release, the swig command emitted by cmake includes:

-interface _myproject

For debug it says:

-interface _myproject-gd

So in the c++ code autogenerated by swig I get a function called _myproject in release but _myproject-gd in debug.

In this file:

C:Program FilesCMakesharecmake-3.26ModulesUseSWIG.cmake

I see:

# This makes sure that the name used in the proxy code
# matches the library name created by CMake
list (APPEND SWIG_MODULE_${name}_EXTRA_FLAGS "-interface" "$<TARGET_FILE_PREFIX:${target_name}>$<TARGET_FILE_BASE_NAME:${target_name}>")

I have debugged that cmake generator expression and of course it evaluates to _myproject in release and _myproject-gd in debug.

In this file:

C:reposmyprojectcmakecommonSettings.cmake

I see:

    if("${MSVC_RUNTIME}" STREQUAL "static")
        set(CMAKE_DEBUG_POSTFIX "gd")
    else()
        set(CMAKE_DEBUG_POSTFIX "-gd")
    endif()

Removing that hyphen fixes the compile error but breaks other things. I’m not certain, but it seems to me that the cmake configuration for swig is misappropriating a cmake variable that is intended to be used in a file (lib) name and is instead incorporating it into the name of a C++ function. So you add a hyphen to that cmake variable, thinking that your lib name will contain a hyphen, and then your autogenerated swig code breaks. I might be wrong, I am still digging.

Edit #2:

I notice that UseSWIG.cmake only sets the -interface flag if it has not already been set. So, before calling swig_add_library, if I do something like this…

list (APPEND SWIG_MODULE_myproject_EXTRA_FLAGS "-interface" _myproject)

…it appears to fix the problem. I can’t yet be sure because my build still fails later with what appears to be a separate, unrelated problem.

Asked By: erik

||

Answers:

Our site sometimes populates CMAKE_DEBUG_POSTFIX with a value containing a hyphen e.g. "-gd". Function swig_add_library() (defined in module UseSWIG.cmake) misappropriates this variable in two ways:

  1. It uses the variable as part of the name of a function in the autogenerated C source code. The hyphen results in invalid C.
  2. It uses the variable as part of the package name and a hyphen results in the package not getting loaded at runtime.

The workaround for us was to unset CMAKE_DEBUG_POSTFIX before calling swig_add_library() and restore CMAKE_DEBUG_POSTFIX after (because it is required by subsequent calls to target_link_libraries):

set(TEMP_CMAKE_DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX})
unset(CMAKE_DEBUG_POSTFIX)
swig_add_library(myproject TYPE MODULE LANGUAGE python SOURCES myproject.i)
set(CMAKE_DEBUG_POSTFIX ${TEMP_CMAKE_DEBUG_POSTFIX})
Answered By: erik
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.