11

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 \
Flexo
  • 87,323
  • 22
  • 191
  • 272
taranaki
  • 803
  • 9
  • 15
  • 1
    I think you are searching for this: [CMake: adding automatic handling of dependencies for swig-generated modules](http://www.cmake.org/pipermail/cmake/2013-January/053345.html). I don't think that the `SWIG_GET_WRAPPER_DEPENDENCIES()` found its way back into the official branch, but the source code can be found [here](http://www.cmake.org/gitweb?p=cmake.git;a=commitdiff;h=fc045318). – Florian Jun 24 '15 at 10:33
  • 2
    Do you do the commenting of `swig_example.h` because you get a "file not found" error on your first try? If yes, you can keep the `SET(SWIG_MODULE_example_EXTRA_DEPS ...)` line uncommented by telling CMake that `swig_example.h` file is going to be generated. Add the following after your `SWIG_ADD_MODULE()` call: `set_source_files_properties(${CMAKE_SOURCE_DIR}/swig_example.h PROPERTIES GENERATED 1)` – Florian Jun 24 '15 at 10:40
  • 1
    @Florian those are both useful notes. I already mentioned the reverted commit in my question, which technically handles case a) above. Regarding PROPERTIES GENERATED, this was something I wasn't aware of, and is certainly useful. Is it possible to modify the now defunct SWIG_GET_WRAPPER_DEPENDENCIES to itself depend on CMake generated inputs? – taranaki Jun 24 '15 at 23:55
  • 1
    When I look at the discussion on [0012307: regression in 2.8.5 rc2: UseSWIG.cmake broken](http://public.kitware.com/Bug/view.php?id=12307) 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()`. Can you give the `SWIG_GET_WRAPPER_DEPENDENCIES()` code a try? According to [this](http://public.kitware.com/Bug/view.php?id=4147) with the patch you just call `SWIG_ADD_MODULE()` and it calls `SWIG_GET_WRAPPER_DEPENDENCIES()` for you. – Florian Jun 26 '15 at 14:02
  • 1
    And - supplementing my last comment and in contradiction to my comment 2 days ago - it will _not_ be a good idea to set all files in `SWIG_MODULE_example_EXTRA_DEPS` to `GENERATED`. Because it's a feature that you get an "file not found" error message if a dependency is missing. – Florian Jun 26 '15 at 14:08
  • 1
    I suggested a fix at [0004147: MODULES UseSWIG: Use swig to compute dependencies](http://public.kitware.com/Bug/view.php?id=4147). The CMake team is searching someone interested in working on the feature. Would you like to take the ticket and do the testing? – Florian Jun 30 '15 at 17:46
  • Hmm, the way I usually handle dependencies is to let the swig wrapper depend through linking to a static library. If I change any headers of the dependent library, SWIG is regenerating the code. – Jens Munk Jul 18 '15 at 18:24

1 Answers1

2

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.

Florian
  • 39,996
  • 9
  • 133
  • 149