Is there a way for CMake to utilize dependencies generated by `swig -MM`?

2.3k views Asked by At

SWIG generates wrapper code from your C/C++ in a desired target language (Python, Java, C#, etc) using an interface (.i) file that specifies the input code to be wrapped as described in the SWIG tutorial. CMake can be used to call swig in order to generate target code from the .i interface, as described in the SWIG documentation.

However, using this method CMake only generates a dependency for the interface file itself, but not for the source files it includes. One can manually add dependencies, but SWIG can generate dependencies automatically with the -MM option, and I would like for these to be utilized by CMake.

There was a commit to CMake that utilized dependencies generated by swig -MM but it was later reverted due to a problem with generated sources that didn't exist at the time of the call to swig. At this time the problem seems to remain unsolved.

So I put the issue to the brilliant StackOverflow community: Is there a way with the current CMake to utilize dependencies generated by swig -MM when the interface file (a) does not include generated code (e.g. config.h), and (b) includes generated code?

Here is a small example that can be used for experimentation (download it here).

// swig_example.h
int foo(int n);
//*** comment this declaration after compiling once to witness dependency failure ***/
int another_function();
// swig_example.cpp
#include "swig_example.h"
int another_function() {return -1;}
int foo(int n) 
{
    if (n <= 1) return 1;
    else return another_function();
}
// swig_example: example.i
%module example
%{
#include "swig_example.h"
%}
%include "swig_example.h"
# swig_example: CMakeLists.txt
FIND_PACKAGE(SWIG REQUIRED)
INCLUDE(${SWIG_USE_FILE})
FIND_PACKAGE(PythonLibs)
INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_PATH})
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
SET(CMAKE_SWIG_FLAGS "")

SET_SOURCE_FILES_PROPERTIES(example.i PROPERTIES CPLUSPLUS ON)

#add manual dependencies (must be called before SWIG_ADD_MODULE)
#SET(SWIG_MODULE_example_EXTRA_DEPS ${CMAKE_SOURCE_DIR}/swig_example.h)

SWIG_ADD_MODULE(example python example.i swig_example.cpp)
SWIG_LINK_LIBRARIES(example ${PYTHON_LIBRARIES})

Compile it once, then comment the declaration of another_function and try to compile again. Because the swig interface is not regenerated an error occurs trying to compile examplePYTHON_wrap.cxx.

examplePYTHON_wrap.cxx:3220:17: error: use of undeclared identifier 'another_function'
  result = (int)another_function();

Uncomment the add manual dependencies line of the CMakeLists.txt and the interface will be properly regenerated. However, I want this to work using dependencies generated from swig -MM instead of needing to manually specify dependencies.

$ swig -python -MM -c++ ../example.i
../example_wrap.cxx: \
  ../example.i \
  ../swig_example.h \
1

There are 1 answers

0
Florian On BEST ANSWER

Turning my comments into an answer

I don't think - if you want to do this automatically and e.g. want to utilize swig -MM - that this can be done without changing the UseSWIG.cmake code.

When I look at why the previous attempt you have linked was reverted - namely the discussion of on "0012307: regression in 2.8.5 rc2: UseSWIG.cmake broken" - I don't believe that SWIG_GET_WRAPPER_DEPENDENCIES() was actually broken it just introduced a new restriction: "this simply require all headers for swig module to be present" before calling SWIG_ADD_MODULE().

So I suggested to add the -ignoremissing SWIG option, but this would need further testing.


Update (April 2017)

With CMake version 3.8.0 there came a fix "Automatically scan dependencies of SWIG files for Makefile generators" that works for makefile generators.


Reference

The general discussion of how to fix this (including my suggestion) is discussed at "Issue #4147: [MODULES][UseSWIG] Use swig to compute dependencies". The ticket is still open (was reopened), so please feel free to add your support, suggestions or test results there.