【问题标题】:How to "install" Python code from CMake?如何从 CMake “安装” Python 代码?
【发布时间】:2017-01-19 03:06:55
【问题描述】:

我有一个主要使用 C++ 的项目,我使用 CMake 来管理它。在设置cmake_install_prefix 并进行配置后,它会生成makefile,然后可以使用这些makefile 以非常标准的方式构建和安装:

make
make install

此时,我的二进制文件最终位于cmake_install_prefix,无需额外工作即可执行它们。最近我在源代码树的一些地方添加了一些 Python 脚本,其中一些依赖于其他。我可以使用 CMake 将 Python 文件+目录结构复制到 cmake_install_prefix,但如果我进入该路径并尝试使用其中一个脚本,Python 找不到用作 imports 的其他脚本,因为 PYTHONPATH 确实不包含cmake_install_prefix。我知道您可以使用 CMake 设置环境变量,但它不会在 shell 中持续存在,因此对于用户而言,除了当前终端会话之外,它并不是真正的“设置”。

解决方案似乎是在您的软件构建说明中添加一个步骤,即“设置您的 PYTHONPATH”。有没有办法避免这种情况?这是将 Python 脚本作为更大项目的一部分“安装”的标准做法吗?为项目设置持续集成之类的事情似乎真的很复杂,因为像 Jenkins 这样的东西必须手动配置以注入环境变量,而它不需要什么特别的东西来构建和执行从 c++ 代码构建的可执行文件。

【问题讨论】:

    标签: python jenkins cmake


    【解决方案1】:

    Python 提供了sys.path 列表,用于搜索带有import 指令的模块。您可以在包含您的模块之前调整此列表:

    script1.py

    # Do some things useful for other scripts
    

    script2.py.in

    # Uses script1.py.
    ...
    sys.path.insert(1, "@SCRIPT1_INSTALL_PATH@")
    import script1
    ...
    

    CMakeLists.txt

    ...
    # Installation path for script1. Depends from CMAKE_INSTALL_PREFIX.
    set(SCRIPT1_INSTALL_PATH ${CMAKE_INSTALL_PREFIX}/<...>)
    
    install(FILES script1.py DESTINATION ${SCRIPT1_INSTALL_PATH}
    
    # Configure 'sys.path' in script2.py, so it may find script1.py.
    configure_file("script2.py.in" "script2.py" @ONLY)
    
    set(SCRIPT2_INSTALL_PATH ${CMAKE_INSTALL_PREFIX}/<...>)
    install(FILES script2.py DESTINATION ${SCRIPT2_INSTALL_PATH}
    ...
    

    如果您希望 script2.py 在构建树和安装树中都工作,您需要有 两个实例,一个在构建树中工作,一个在安装后工作.两个实例都可以从单个 .in 文件进行配置。


    对于已编译的可执行文件和库,类似的机制是使用帮助二进制文件在非标准位置查找库。它被称为 RPATH。

    因为 CMake

    • 知道创建的每个二进制文件(它跟踪 add_executableadd_library 调用),

    • 知道二进制文件之间的链接(target_link_libraries 调用也被跟踪),

    • 完全控制链接过程,

    CMake 能够在安装二进制文件时自动调整 RPATH。

    如果 Python 脚本 CMake 没有此类信息,则应手动调整链接路径

    【讨论】:

    • 看来这会产生一个工作的“安装”版本。此外,是否还有一种更直接/中间的方式来运行脚本以进行开发。也就是说,更改一个 .py 文件,运行整个 CMake 程序,然后尝试/测试它似乎有点笨拙。有没有办法让脚本也“就地”工作(例如,从源代码树)?
    • Is there anyway to make the scripts work "in-place" as well (from the source tree, for example)? 在脚本中你可以使用某种注解,比如sys.path.append(/path/to/scriptA) # $$scriptA$$。当要安装脚本时,首先找到其中的所有$$...$$ 行并用适当的表达式替换它们,然后安装结果文件。在任何情况下,已安装的脚本都应该与源代码树中的一个不同(除非您想调整环境或脚本的参数)。
    • 如果您希望脚本可执行,请使用 install(PROGRAMS script1.py...)PROGRAMS 这样做。
    猜你喜欢
    • 2020-04-21
    • 1970-01-01
    • 2014-03-30
    • 1970-01-01
    • 2021-08-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-04
    相关资源
    最近更新 更多