CMake 有没有办法利用“swig -MM”生成的依赖项?

Posted

技术标签:

【中文标题】CMake 有没有办法利用“swig -MM”生成的依赖项?【英文标题】:Is there a way for CMake to utilize dependencies generated by `swig -MM`? 【发布时间】:2015-09-09 12:55:46 【问题描述】:

SWIG 使用接口 (.i) 文件以所需的目标语言(Python、Java、C# 等)从您的 C/C++ 生成包装器代码,该文件指定要包装的输入代码,如 SWIG tutorial 中所述。 CMake 可用于调用 swig,以便从 .i 接口生成目标代码,如SWIG documentation 中所述。

但是,使用这种方法,CMake 只会为接口文件本身生成依赖关系,而不会为其包含的源文件生成依赖关系。可以manually add dependencies,但 SWIG 可以使用 -MM 选项自动生成依赖项,我希望 CMake 使用这些。

有一个 commit to CMake 使用了由 swig -MM 但 it was later reverted 生成的依赖项,因为在调用 swig 时生成的源不存在的问题。目前,问题似乎仍未解决。

所以我把这个问题提交给了出色的 *** 社区:当前的 CMake 有没有办法在接口文件(a ) 不包括生成的代码(例如 config.h),而 (b) 包括生成的代码?

这是一个可用于实验的小示例 (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)

编译一次,然后注释another_function的声明,再次编译。因为没有重新生成 swig 接口,所以尝试编译 examplePYTHON_wrap.cxx 时发生错误。

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

取消注释 CMakeLists.txt 的 add manual dependencies 行,界面将正确重新生成。但是,我希望它使用从 swig -MM 生成的依赖项来工作,而不是需要手动指定依赖项。

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

【问题讨论】:

我想你正在搜索这个:CMake: adding automatic handling of dependencies for swig-generated modules。我不认为SWIG_GET_WRAPPER_DEPENDENCIES() 重新回到了官方分支,但是可以在here 找到源代码。 您是否因为在第一次尝试时收到“找不到文件”错误而对swig_example.h 进行评论?如果是,您可以通过告诉 CMake 将生成 swig_example.h 文件来保持 SET(SWIG_MODULE_example_EXTRA_DEPS ...) 行不注释。在您的SWIG_ADD_MODULE() 调用之后添加以下内容:set_source_files_properties($CMAKE_SOURCE_DIR/swig_example.h PROPERTIES GENERATED 1) @Florian 这些都是有用的注释。我已经在我的问题中提到了恢复的提交,它在技术上处理了上面的案例 a)。关于生成的属性,这是我不知道的,当然很有用。是否可以根据 CMake 生成的输入将现已失效的 SWIG_GET_WRAPPER_DEPENDENCIES 修改为自身? 当我查看0012307: regression in 2.8.5 rc2: UseSWIG.cmake broken 上的讨论时,我不相信SWIG_GET_WRAPPER_DEPENDENCIES() 实际上被破坏了,它只是引入了一个新限制:“这只是要求所有 swig 模块的标头都存在”在致电SWIG_ADD_MODULE() 之前。你可以试试SWIG_GET_WRAPPER_DEPENDENCIES() 代码吗?根据this 的补丁,你只需调用SWIG_ADD_MODULE(),它就会为你调用SWIG_GET_WRAPPER_DEPENDENCIES() 并且 - 补充我的最后一条评论并与我 2 天前的评论相矛盾 - 将 SWIG_MODULE_example_EXTRA_DEPS 中的所有文件设置为 GENERATED不是是一个好主意.因为如果缺少依赖项,您会收到“找不到文件”错误消息。 【参考方案1】:

把我的 cmets 变成答案

我不认为 - 如果您想自动执行此操作,例如想要使用swig -MM - 这可以在不更改UseSWIG.cmake 代码的情况下完成。

当我查看为什么您之前链接的尝试被恢复时 - 即在 "0012307: regression in 2.8.5 rc2: UseSWIG.cmake broken" 上的讨论 - 我不相信 SWIG_GET_WRAPPER_DEPENDENCIES() 实际上被打破了它只是引入了一个新的限制:“这只是要求所有在调用 SWIG_ADD_MODULE() 之前存在 swig 模块的标头。

所以我建议添加-ignoremissing SWIG 选项,但这需要进一步测试。


更新(2017 年 4 月)

在 CMake 版本 3.8.0 中,有一个适用于 makefile generators 的修复程序 "Automatically scan dependencies of SWIG files for Makefile generators"。


参考

关于如何解决这个问题的一般性讨论(包括我的建议)在"Issue #4147: [MODULES][UseSWIG] Use swig to compute dependencies" 进行了讨论。票仍然开放(已重新开放),因此请随时在此处添加您的支持、建议或测试结果。

【讨论】:

以上是关于CMake 有没有办法利用“swig -MM”生成的依赖项?的主要内容,如果未能解决你的问题,请参考以下文章

CMake、SWIG 和共享库

SWIG / C#:命名空间和模板

CMake 错误:找不到 SWIG(缺少:SWIG_DIR)

CMake - SWIG - 移植动态库

cmake利用toolchain.cmake生成makefile之后,make生成静态库失败问题

CMake Swig:如何在包含的 .i 文件上添加依赖项