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:\xxx\myprojectPYTHON_wrap.cxx(807935,1): error C2143: syntax error: missing ';' before '-'
C:\xxx\myprojectPYTHON_wrap.cxx(807935,1): error C2059: syntax error: '-'
C:\xxx\myprojectPYTHON_wrap.cxx(807935,17): error C2143: syntax error: missing ';' before '{'
C:\xxx\myprojectPYTHON_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 Files\CMake\share\cmake-3.26\Modules\UseSWIG.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:\repos\myproject\cmake\commonSettings.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.
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:
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})