python - Cython,CMake和setup.py,子目录中的python编译两次
问题描述
我正在尝试按照https://bloerg.net/2012/11/10/cmake-and-distutils.html的结构与 Cython 绑定一起构建 C++ 库。
问题是在 期间make install
,扩展将被编译两次。CMakeLists.txt
当主文件夹中只有一个主文件夹(调整了路径)时,不会发生这种双重编译。以下是详细信息:
我的项目结构是
.
├── CMakeLists.txt
├── python
│ ├── CMakeLists.txt
│ ├── a_py.pxd
│ ├── a_py.pyx
│ └── setup.py.in
└── src
├── A.cpp
└── A.h
顶层CMakeLists.txt
仅包含add_subdirectory(python)
.
python/CMakeLists.txt
是
IF(NOT ${PYTHON})
find_program(PYTHON "python")
ENDIF()
set(SETUP_PY_IN "${CMAKE_CURRENT_SOURCE_DIR}/setup.py.in")
set(SETUP_PY "${CMAKE_CURRENT_BINARY_DIR}/setup.py")
set(PY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/build/pytimestamp")
configure_file(
${SETUP_PY_IN}
${SETUP_PY}
)
add_custom_command(OUTPUT "${PY_OUTPUT}"
COMMAND ${PYTHON} ${SETUP_PY} build_ext
COMMAND ${CMAKE_COMMAND} -E touch ${PY_OUTPUT}
)
add_custom_target(a_py ALL DEPENDS ${PY_OUTPUT})
install(CODE "execute_process(COMMAND ${PYTHON} ${SETUP_PY} install)")
setup.py
是:
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
ext_modules = [
Extension(
name="a",
sources=["${CMAKE_CURRENT_SOURCE_DIR}/a_py.pyx", "${CMAKE_CURRENT_SOURCE_DIR}/../src/A.cpp"],
include_dirs = ['${CMAKE_CURRENT_SOURCE_DIR}/../src'],
language="c++",
),
]
setup(
name = 'a',
version='${PROJECT_VERSION}',
cmdclass = {'build_ext': build_ext},
ext_modules = ext_modules,
package_dir={ 'a': '${CMAKE_CURRENT_SOURCE_DIR}' },
)
在这两种情况下(CMakeFile.txt
在根目录或python
子文件夹中),首先build_ext
运行该步骤:
Scanning dependencies of target a_py [100%] Generating build/pytimestamp running build_ext
并编译生成的a_py.cpp
和A.cpp
链接库。在安装步骤中,只有CMakeFile.txt
在python
子文件夹中时才会再次运行编译。
这是安装过程中发生的情况:
running build_ext skipping '/Users/xxx/tmp/ctest/t08/python/a_py.cpp' Cython extension (up-to-date) building 'a' extension creating build
请注意,a_py.pyx
它不会再次被cythonized,但会重新创建构建目录(在构建和安装步骤之间是相同的)并且文件被编译(使用完全相同的编译器和链接器调用)。
一个完整的例子可以在这里找到:https ://github.com/zeeMonkeez/cmakeCythonTest
解决方案
我有同样的问题。显然,在我的情况下,在安装阶段setup.py
很难找到在构建阶段放置已编译扩展的目录,因此即使使用--skip-build
开关它也会重新编译它们。
我通过在构建和安装阶段分别使用--build-lib
和--build-dir
开关指定相同的目录路径来解决:
add_custom_command(OUTPUT ${PY_OUTPUT}
COMMAND ${PYTHON} ${SETUP_PY} build_ext --build-lib ${CMAKE_CURRENT_BINARY_DIR}/mysoext
COMMAND ${CMAKE_COMMAND} -E touch ${PY_OUTPUT}
DEPENDS ${DEPS}
)
...
set(MYINSTCMD "\
EXECUTE_PROCESS(COMMAND ${PYTHON} ${SETUP_PY} install_lib \
--skip-build \
--install-dir /my/install/dir \
--build-dir ${CMAKE_CURRENT_BINARY_DIR}/mysoext)")
install(CODE "${MYINSTCMD}")
推荐阅读
- localtime - 如何在 php/laravel/js 中获取计算机时间
- python - 在 geoTIFF 中获取所有唯一颜色时,如何知道 PIL 指的是什么颜色?
- function - 使用 FnMut 发送函数作为参数
- java - Java 执行 wscript - createobject(word.application 权限被拒绝
- dendrogram - 如何更改每个集群的树状图线的颜色?
- sql - 优化 Oracle SQL 查询以获得更快的结果
- python - scipy.optimize.minimize 在多变量优化中不收敛
- python - 使用 pytest 检查应用程序文件是否导入了模块?
- ruby-on-rails - Rails 条件验证:如果:不起作用
- r - Merlin R 包 - str2lang(x) 中的错误:
:1:30: 意外符号