I want to make a Python Package for win_amd64 (Windows x64) of cpp files. I have used Swig to wrap them into python and then used setuptools to build it. I have made CMakeLists.txt files to do all this actions. Note: I am using x86_64-w64-mingw32 cross-compiler to build this in linux machine
Tools Used & its Version:
- Swig Version: 4.1.1
- CMake Version: 3.27
- Python Version: 3.9.18 (linux) - to run setuptools
- Cross Compiler Toolchain: x86_64-w64-mingw32
- Linux Distro & Version: Ubuntu 20.04
- Python 3.9 Windows AMD64 - dev.msi pkg (wget'ed the dev.msi and msiextracted it to local folder)
Note: I can build the python pkg for linux-x86_64 (linux 64) for all of Python3.6 and above, but for windows I can only build for Python3.6 (By using the library libpython36.a) but with later version for win_amd64 I had to use the libpython39.lib (Lib based libraries)
What happens now:
I can build the whl file for win_amd64 successfully. CMake can make the .dll and setuptools wrapped it well
On installing this on windows Python3.9 x64, it installs without any warning
But when I try to import the main module, it throws
import sample # name of the module # Error below Traceback: from . import _sample_swig ImportError: DLL load failed: The specified module could not be found.ImportError: DLL load failed: The specified module could not be found.`
Project Setup:
Swig File
FIND_PACKAGE(SWIG REQUIRED) INCLUDE(${SWIG_USE_FILE}) CMAKE_MINIMUM_REQUIRED(VERSION 3.16) SET(PYTHON_MODULE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/sample) set(PYTHON_EXECUTABLE python${PYTHON_BUILD_VERSION}) if (${BUILD_PLATFORM} MATCHES "Windows") set(CMAKE_SYSTEM_NAME Windows) set(CMAKE_C_COMPILER /usr/bin/x86_64-w64-mingw32-gcc) set(CMAKE_CXX_COMPILER /usr/bin/x86_64-w64-mingw32-g++) set(PYTHON_LIBRARY /home/developer/workspace/69/py39/libs/python.lib) set(PYTHON_INCLUDE_DIR /home/developer/workspace/69/py39/include) set(TARGET_EXTENSION "pyd") set(CMAKE_FIND_ROOT_PATH /opt/win_cross_compile_libs) ELSE() set(CMAKE_C_COMPILER /usr/bin/gcc) set(CMAKE_CXX_COMPILER /usr/bin/g++) set(TARGET_EXTENSION "so") set(PythonLibs_DIR /usr/lib/x86_64-linux-gnu/) set(CMAKE_FIND_ROOT_PATH /usr/lib/x86_64-linux-gnu/) ENDIF() project(sample LANGUAGES CXX) set(CMAKE_LANGUAGE_COMPILER ${CMAKE_CXX_COMPILER}) FIND_PACKAGE(Python3 COMPONENTS Interpreter Development) FIND_PACKAGE(PythonLibs) INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/include) message(STATUS "Py Libs: ${PYTHON_LIBRARIES}") message(STATUS "Add. Linking Flags: ${ADD_LINK_FLAGS}") message(STATUS "Python Incl Dir: ${PYTHON_INCLUDE_DIR}") message(STATUS "Python Module: ${PYTHON_MODULE_DIR}") message(STATUS "Machine: ${CMAKE_SYSTEM_NAME}") set(PythonLibs_DIR "/usr/lib/x86_64-linux-gnu/") set_property(SOURCE include/sample.i PROPERTY CPLUSPLUS ON) file(GLOB SRC_FILES ${PROJECT_SOURCE_DIR}/src/*.cpp) swig_add_library(sample_swig TYPE SHARED LANGUAGE python OUTPUT_DIR ${PYTHON_MODULE_DIR} OUTFILE_DIR src SOURCES include/sample.i ${SRC_FILES} ) SWIG_LINK_LIBRARIES(sample_swig ${PYTHON_LIBRARIES}) add_custom_command( TARGET _sample_swig POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy _sample_swig.${TARGET_EXTENSION} ${PYTHON_MODULE_DIR}/_sample_swig.${TARGET_EXTENSION} ) INSTALL(TARGETS _sample_swig LIBRARY DESTINATION sample)Interface file used for swig:
%module arithmetic_operator %{ #include "addition.h" %} %include "addition.h" %include "stdint.i"`Header file:
# include <iostream> using namespace std; int addition_fn(int a, int b) { return (a+b);` }CPP File:
# include <iostream> using namespace std; const int MAX_ADDABLE = 50; int main() { cout<<"Hello World\n"; }Setup.py:
from skbuild import setup setup( name='sample', version='0.1.0', description='Sample', cmake_with_sdist=True, packages=['sample'], python_requires=">=3.6", include_package_data=True, zip_safe=False )
Using os.add_dll_directory(<dll folder location (site-packages/sample)>) as the Python3.8 and above only loads from trusted sources even though overwritten by PYTHONPATH - Doesn't work
Wasn't able to figure it out for a month.
I finally fixed this by moving my x86_64-w64-mingw32-g++ which was on 9.0.x on Ubuntu 20.04 to compiler x86_64-w64-mingw32-g++-posix with GCC version 10-posix 20220113 (GCC) on Ubuntu-22.04
Seems like the latest GCC will seemingly handle Windows Python 3.8+ DLL based handles when using Shared Libraries