使用 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
我有一个 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 version3.20
.
If set toTRUE
, 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 isFALSE
.
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 toTRUE
, contents of target property INCLUDE_DIRECTORIES will be forwarded to SWIG compiler. If set toFALSE
target property INCLUDE_DIRECTORIES will be ignored. If not set, target propertySWIG_USE_TARGET_INCLUDE_DIRECTORIES
will be considered.
来源:https://cmake.org/cmake/help/git-stage/module/UseSWIG.html