A correct way to add `_d` debug prefix for Debug Python extensions on Windows

On Windows when you run debug version of Python (python_d.exe) it only accepts extensions that were linked against python311_d.dll and also it requires them to have _d suffix.

For example:

# Let's say we've compiled '_example.pyd`.
# Then this will work fine in usual Python, 
# but in `python_d` it will result in "_example module is not found".

# If we've compiled `_example_d.pyd`
# then it will work fine in `python_d`, but won't work in usual Python.

import _example

The question is, how to ensure cmake will add _d suffix on Debug build automatically?
DEBUG_POSTFIX comes to mind, but it has a caveat.

cmake_minimum_required(VERSION 3.10)
project(HelloInstall)

find_package(SWIG REQUIRED)
include(UseSWIG)
find_package(Python REQUIRED COMPONENTS Interpreter Development)

set_source_files_properties(example.i PROPERTIES CPLUSPLUS ON)
swig_add_library(
    example
    TYPE MODULE
    LANGUAGE python
    SOURCES example.i example.cpp
)
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
swig_link_libraries(example PRIVATE Python::Python)
set_target_properties(
    ${SWIG_MODULE_example_REAL_NAME} PROPERTIES
    DEBUG_POSTFIX "_d"
)

The caveat is in example.py, the wrapper file that’s used to import underlying _example_d.pyd extension. Because cmake passed target name as -interface <target_name> to swig, example.py is now using import _example_d, which is incorrect and will always fail - it suppose to be import _example, even though underlying extension is indeed has _d suffix.

if __package__ or "." in __name__:
    from . import _example_d
else:
    import _example_d

From UseCmake.cmake code it seems the only way to avoid this is to override -interface yourself. So the workaround is to add set(SWIG_MODULE_example_EXTRA_FLAGS "-interface" "_example") before swig_add_library.

Is there some best practice for this case?
Could it also be considered a bug in cmake? In theory it should drop possible _d suffix when adding target_name in -interface in Debug config on Windows.
Also, maybe it would make sense for swig_add_library to set _d as DEBUG_POSTFIX on Windows as default in this case?

Unfortunately, currently there is no easy way to solve this problem because UseSWIG does not handle the debug version.

Can you create an issue for this problem? I have already some ideas to provide a better support of the debug environment of Python for SWIG.

1 Like

Thank you for looking into this, opened an issue - UseSWIG to handle Python Debug config extensions suffix on Windows (#27185) · Issue · cmake/cmake