使用 CMake,如何在头文件更改时重建 Swig 包装器

Using CMake, how to rebuild Swig wrapper when header file changes

我有一个 C++ 库(称为 myfibo),我想使用 CMake 和 Swig 制作一个 python 绑定模块(称为 myfibopy)。

第一个版本运行完美。但是,如果我重命名公开的 C++ 函数,python 模块将不再构建,因为 Swig 包装器 (PYTHON_wrap.cxx) 不会重新生成。

我已经按照 here 的说明尝试使用 SWIG_USE_LIBRARY_INCLUDE_DIRECTORIES,但没有成功。

我做错了什么?

这是重现错误的玩具示例:

目录树

.
├── CMakeLists.txt
├── myfibo
│   ├── CMakeLists.txt
│   ├── fibo.cpp
│   └── include
│       └── fibo.hpp
└── myfibopy
    ├── CMakeLists.txt
    └── fibo.i

fibo.hpp

#pragma once
void fib(int n);

fibo.cpp

#include "fibo.hpp"
#include <iostream>

void fib(int n)
{
  int a = 0;
  int b = 1;
  while (a < n)
  {
    std::cout << a << " ";
    a = b;
    b = a+b;
  }
  std::cout << std::endl;
}

fibo.i

%module myfibopy

%include fibo.hpp
%{
  #include "fibo.hpp"
%}

./CMakeLists.txt

project(myfibopy)      

cmake_minimum_required(VERSION 3.15) 

add_subdirectory(myfibo)
add_subdirectory(myfibopy)

myfibo/CMakeLists.txt

add_library(myfibo SHARED fibo.cpp)
target_include_directories(myfibo
  PUBLIC
    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
    $<INSTALL_INTERFACE:include>   # unused 
)

myfibopy/CMakeLists.txt

find_package(PythonLibs 3 REQUIRED)
include_directories(${PYTHON_INCLUDE_PATH})

find_package(SWIG 4.0 REQUIRED)
include(${SWIG_USE_FILE})

set(SRC fibo.i)

set_source_files_properties(${SRC} PROPERTIES CPLUSPLUS ON)

swig_add_library(myfibopy LANGUAGE python SOURCES ${SRC})

target_link_libraries(myfibopy PUBLIC myfibo)

# See https://gitlab.kitware.com/cmake/cmake/-/issues/18003
set_target_properties(myfibopy PROPERTIES SWIG_USE_TARGET_INCLUDE_DIRECTORIES TRUE)

第一次编译

> cmake -Bbuild -H.
   [...]
> cmake --build build
   [...]

完美。现在,build 目录存在,我可以使用 myfibopy 模块。

在fibo.hpp和fibo.cpp

中将fib重命名为fib2
> cmake --build build
Consolidate compiler generated dependencies of target myfibo
[ 20%] Building CXX object myfibo/CMakeFiles/myfibo.dir/fibo.cpp.o
[ 40%] Linking CXX shared library libmyfibo.so
[ 40%] Built target myfibo
[ 60%] Built target myfibopy_swig_compilation
Consolidate compiler generated dependencies of target myfibopy
[ 80%] Building CXX object myfibopy/CMakeFiles/myfibopy.dir/CMakeFiles/myfibopy.dir/fiboPYTHON_wrap.cxx.o
./build/myfibopy/CMakeFiles/myfibopy.dir/fiboPYTHON_wrap.cxx: In function ‘PyObject* _wrap_fib(PyObject*, PyObject*)’:
./build/myfibopy/CMakeFiles/myfibopy.dir/fiboPYTHON_wrap.cxx:2968:3: error: ‘fib’ was not declared in this scope
   fib(arg1);
   ^~~
./build/myfibopy/CMakeFiles/myfibopy.dir/fiboPYTHON_wrap.cxx:2968:3: note: suggested alternative: ‘fib2’
   fib(arg1);
   ^~~
   fib2
myfibopy/CMakeFiles/myfibopy.dir/build.make:75: recipe for target 'myfibopy/CMakeFiles/myfibopy.dir/CMakeFiles/myfibopy.dir/fiboPYTHON_wrap.cxx.o' failed
make[2]: *** [myfibopy/CMakeFiles/myfibopy.dir/CMakeFiles/myfibopy.dir/fiboPYTHON_wrap.cxx.o] Error 1
CMakeFiles/Makefile2:170: recipe for target 'myfibopy/CMakeFiles/myfibopy.dir/all' failed
make[1]: *** [myfibopy/CMakeFiles/myfibopy.dir/all] Error 2
Makefile:90: recipe for target 'all' failed
make: *** [all] Error 2

你试过了吗:

USE_SWIG_DEPENDENCIES
New in version 3.20.
If set to TRUE, implicit dependencies are generated by the swig tool itself. This property is only meaningful for Makefile, Ninja, Xcode, and Visual Studio (Visual Studio 11 2012 and above) generators. Default value is FALSE.
New in version 3.21: Added the support of Xcode generator.
New in version 3.22: Added the support of Visual Studio Generators.

USE_TARGET_INCLUDE_DIRECTORIES
New in version 3.13.
If set to TRUE, contents of target property INCLUDE_DIRECTORIES will be forwarded to SWIG compiler. If set to FALSE target property INCLUDE_DIRECTORIES will be ignored. If not set, target property SWIG_USE_TARGET_INCLUDE_DIRECTORIES will be considered.

来源:https://cmake.org/cmake/help/git-stage/module/UseSWIG.html