Today I tried to use combination of "cmake + swig" to generate bindings for my code. Basically it works:
set(SWIG_EXECUTABLE "/usr/bin/swig")
find_package(SWIG REQUIRED)
include(${CMAKE_CURRENT_SOURCE_DIR}/UseSWIG.cmake)
set(CMAKE_SWIG_FLAGS -package example)
set(CMAKE_SWIG_OUTDIR "${CMAKE_CURRENT_SOURCE_DIR}/example")
set_source_files_properties(native.i PROPERTIES CPLUSPLUS ON)
SWIG_ADD_MODULE(core Java native.i lib.cpp)
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
with such native.i:
%module native
%include "lib.hpp"
%{
#include "lib.hpp"
%}
But if I change lib.hpp
build system cmake build
not call swig to regenerate code. So I have to touch native.i
to get it works, this is very annoying.
I found -M
option of swig
to generate dependencies,
Is any idea how use it to fix UseSWIG.cmake
?
UseSWIG.cmake
just uses add_custom_command
for generation,
so I need somehow add_custom_command
depend on dynamic set of files,
not static?
I believe that I have found a solution to your request.
I am currently using a solution, where all relevant dependencies are added such that SWIG
re-generates the interface, whenever any of the headers parsed are modified.
The idea is to make a custom target, which touch a dummy file in addition to deleting the generated interface file. I have put the solution below for a project named fnm
with a wrapper swig_fnm
.
# Method to make swig_fnm.i depend on input headers
execute_process(COMMAND swig -M -python -c++ -I${CMAKE_CURRENT_BINARY_DIR}/.. -I${CMAKE_CURRENT_SOURCE_DIR}/.. swig_fnm.i
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
OUTPUT_VARIABLE swig_deps
INPUT_FILE swig_fnm.i)
# Match all lines except the first one until " \"
string(REGEX MATCHALL "\n [^ ]+" temp ${swig_deps})
# Valid dependency extensions
set(valid_ext .h .hpp)
# Dependency list
set(swig_deps_actual)
foreach(t ${temp})
string(STRIP "${t}" t)
# Add to dependency list
if (EXISTS "${t}")
set(filter)
get_filename_component(filter "${t}" EXT)
if (";${valid_ext};" MATCHES ";${filter};")
set(swig_deps_actual ${swig_deps_actual} "${t}")
endif()
endif()
endforeach()
# This makes configure run again, but does not regenerate the SWIG interface.
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${swig_deps_actual})
# All headers except for the single .i file are ignored
swig_add_module(swig_fnm python swig_fnm.i ${swig_fnm_HEADERS} ${swig_deps_actual})
# Removes generated file (if any of the dependent files are changed)
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/swig.stamp
COMMAND ${CMAKE_COMMAND} -E remove ${swig_generated_file_fullname}
COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_CURRENT_BINARY_DIR}/swig.stamp
DEPENDS ${swig_deps_actual} # The dependent files
COMMENT "Removing old SWIG generated file" VERBATIM)
# Custom target for establishing dependency
add_custom_target(
swigtrick
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/swig.stamp)
# Dependency
add_dependencies(_swig_fnm swigtrick)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With