Things are getting confused for me, so I hope to be clear.
I made a c++17 library (called here myLib
), and I bind it with python using swig. Everything is working when I compile by hand.
Now, I would like to automatize and clean my work using cmake: no problem for the library.
But things are getting more obscure to me when it comes to creating the binding with cmake.
I came with the following cmake sample:
include(FindSWIG)
find_program(SWIG_PATH swig)
find_package(SWIG 4.0 COMPONENTS python)
include(UseSWIG)
find_package(PythonLibs 3 REQUIRED)
find_package(PythonInterp ${PYTHONLIBS_VERSION_STRING} REQUIRED)
set(CMAKE_SWIG_FLAGS -py3)
message("PYTHONLIBS_VERSION_STRING: ${PYTHONLIBS_VERSION_STRING}")
message("CMAKE_SWIG_FLAGS: ${CMAKE_SWIG_FLAGS}")
add_custom_target(
binding_target
)
include_directories("${PROJECT_SOURCE_DIR}/external/include" "${PROJECT_SOURCE_DIR}/include" ${PYTHON_LIBRARIES})
# If I use the following line instead to the previous, I get an error of target type non-compilable
# target_include_directories(binding_target "${PROJECT_SOURCE_DIR}/external/include" "${PROJECT_SOURCE_DIR}/include" ${PYTHON_LIBRARIES})
set_source_files_properties(py_myLib.i PROPERTIES CPLUSPLUS ON)
# If I use the following line, I get an error of target type non-compilable.
# target_compile_features(binding_target SHARED cxx_std_17)
swig_add_library(binding_target
TYPE SHARED
LANGUAGE python
SOURCES py_myLib.i
)
swig_link_libraries(binding_target ${PYTHON_LIBRARIES} USE_TARGET_INCLUDE_DIRECTORIES)
With the previous code, the command cmake ..
is exiting without error, but the compilation with make
is returning errors as the compiler is not using the option -std=c++17
to compile.
(by the way, I am wondering why make
is compiling while make binding_target
does nothing, I would expect the opposite.)
I tried to add a C++17 feature to the compilation with the line target_compile_features
but then, I get an error from cmake ..
about a target_compile_features called with non-compilable target type
So my question is: how can I build properly (inside a target) the swig binding with cmake (precising the include directories and compilation option for this target) ?
I came up with this solution (do not hesitate to improve it):
include(FindSWIG)
find_program(SWIG_PATH swig)
find_package(SWIG 4.0 COMPONENTS python)
include(UseSWIG)
find_package(PythonLibs 3 REQUIRED)
find_package(PythonInterp ${PYTHONLIBS_VERSION_STRING} REQUIRED)
set(CMAKE_SWIG_FLAGS -py3)
message("PYTHONLIBS_VERSION_STRING: ${PYTHONLIBS_VERSION_STRING}")
message("CMAKE_SWIG_FLAGS: ${CMAKE_SWIG_FLAGS}")
#
set_source_files_properties(py_myLib.i PROPERTIES CPLUSPLUS ON)
set_property(SOURCE py_myLib.i PROPERTY SWIG_MODULE_NAME py_myLib)
set (UseSWIG_TARGET_NAME_PREFERENCE STANDARD)
swig_add_library(py_myLib
TYPE SHARED
LANGUAGE python
SOURCES py_myLib.i
)
# For Swig wrapping
set_property(TARGET py_myLib PROPERTY SWIG_INCLUDE_DIRECTORIES
"${PROJECT_SOURCE_DIR}/external/include"
"${PROJECT_SOURCE_DIR}/include"
)
# For Cxx compilation
set_property(TARGET py_myLib PROPERTY INCLUDE_DIRECTORIES
"${PROJECT_SOURCE_DIR}/external/include"
"${PROJECT_SOURCE_DIR}/include"
${PYTHON_INCLUDE_PATH}
)
set_property(TARGET py_myLib PROPERTY COMPILE_OPTIONS -shared -std=c++17 ) #
# swig_link_libraries(
target_link_libraries( py_myLib
${PYTHON_LIBRARIES}
)
#
target_include_directories(py_myLib
PRIVATE
# where the library itself will look for its internal headers
${CMAKE_SOURCE_DIR}/include #
${CMAKE_SOURCE_DIR}/external/include
PUBLIC
# where top-level project will look for the library's public headers
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/include>
)