Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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 \
like image 423
taranaki Avatar asked Jun 23 '15 15:06

taranaki


People also ask

How to manage dependencies with CMake?

There are a lot of ways of managing dependencies with CMake, so let’s to a quick overview of possible ways. The simplest way of doing dependency management is to simply copy source code of your dependencies into your project source directory.

How do I use externalproject with CMake?

The ExternalProject module can be used alongside find_package to automatically download and build any dependencies that cannot be found locally on the system. Dependencies in cmake can be found using the find_package command in your CMakeLists.txt files.

How does CMake work with imgui?

Basically, CMake will take build artifacts of ImGui-SFML, sfml-graphics, sfml-window and sfml-system targets (DLLs) and copy them to the directory where executable example_exe will be built. Note that this is only done when you’re building your project, not installing it (when you run cmake --build . --target install ).

Why decompose CMake build files into smaller files?

It's better to decompose CMake build files into smaller files so that you don't get one huge `CMakeLists.txt` which builds everything, but is several thousands lines long and hard to maintain.


1 Answers

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.

like image 73
Florian Avatar answered Nov 06 '22 04:11

Florian