如何在CMake安装中创建一个Python 3虚拟环境?

huangapple go评论67阅读模式
英文:

How can I create a python3 venv in cmake install?

问题

以下是您要翻译的代码部分:

find_package(Python3 REQUIRED COMPONENTS Interpreter)
set(VENV "${CMAKE_INSTALL_PREFIX}/venv")
set(REQUIREMENTS "${CMAKE_SOURCE_DIR}/tools/testing/scripts/requirements.txt")
set(BIN_DIR "${VENV}/bin")
install(CODE "
      MESSAGE(\"Creating VENV from ${Python3_EXECUTABLE} to ${VENV}\")
      execute_process(COMMAND_ECHO STDOUT COMMAND ${Python3_EXECUTABLE} -m venv ${VENV} )
      execute_process(COMMAND_ECHO STDOUT COMMAND ${BIN_DIR}/pip install -U pip wheel )
      execute_process(COMMAND_ECHO STDOUT COMMAND ${BIN_DIR}/pip install -r ${REQUIREMENTS} )
")

希望这有所帮助。如果您有任何其他问题,请随时提出。

英文:

I have a medium sized project composed by many parts, mostly in C++, but testing and configuration relies on Python3 scripts.

The project buildsystem is generated using CMake and installed (by CMake rules) in a "deploy" directory.

I would like to create a Python venv to segregate changes.
I have the following CMake fragment:

set(VENV ${CMAKE_INSTALL_PREFIX}/venv)
set(REQUIREMENTS ${CMAKE_SOURCE_DIR}/tools/testing/scripts/requirements.txt)
set(BIN_DIR ${VENV}/bin)
set(PYTHON ${BIN_DIR}/python)
set(OUTPUT_FILE ${VENV}/environment.txt)
add_custom_command(
    OUTPUT ${OUTPUT_FILE}
    COMMAND ${Python3_EXECUTABLE} -m venv ${VENV}
    COMMAND ${BIN_DIR}/pip install -U pip wheel
    COMMAND ${BIN_DIR}/pip install -r ${REQUIREMENTS}
    COMMAND ${BIN_DIR}/pip freeze > ${VENV}/environment.txt
    DEPENDS ${REQUIREMENTS}
)
add_custom_target(venv DEPENDS ${PYTHON})

... but I don't know how to trigger the venv target while doing installation.

I am unsure if this is the right approach (comments welcome, of course), but need should be quite clear: I need to be able to run my scripts from the "deploy" directory using something like:

venv/bin/python test-script.py

or use a custom: #!venv/bin/python line (I am working under Linux).

UPDATE:

My somewhat working code, based on @user Answer, is as follows:

find_package(Python3 REQUIRED COMPONENTS Interpreter)
set(VENV "${CMAKE_INSTALL_PREFIX}/venv")
set(REQUIREMENTS "${CMAKE_SOURCE_DIR}/tools/testing/scripts/requirements.txt")
set(BIN_DIR "${VENV}/bin")
install(CODE "
      MESSAGE(\"Creating VENV from ${Python3_EXECUTABLE} to ${VENV}\")
      execute_process(COMMAND_ECHO STDOUT COMMAND ${Python3_EXECUTABLE} -m venv ${VENV} )
      execute_process(COMMAND_ECHO STDOUT COMMAND ${BIN_DIR}/pip install -U pip wheel )
      execute_process(COMMAND_ECHO STDOUT COMMAND ${BIN_DIR}/pip install -r ${REQUIREMENTS} )
")

Equivalent code with set(... and find_package(... inside install(CODE... did not work; also quoting seems wrong.

I will accept this answer, but I would like to clarify the above.

答案1

得分: 0

你可以使用install(SCRIPT)install(CODE)来实现这个功能:

SCRIPT形式会在安装过程中调用给定的CMake脚本文件。如果脚本文件名是相对路径,它将相对于当前源目录进行解释。CODE形式会在安装过程中调用给定的CMake代码。代码被指定为双引号内的单个参数。

我认为可以这样做(在这里使用CODE形式使得变量替换和使用一些在配置阶段上下文之外不可用的变量更容易,即使你使用SCRIPT模式,也需要明确传递它们):

install(CODE "
    set(VENV \"${CMAKE_INSTALL_PREFIX}/venv\")
    set(REQUIREMENTS \"${CMAKE_SOURCE_DIR}/tools/testing/scripts/requirements.txt\")
    set(BIN_DIR \"${VENV}/bin\")
    set(OUTPUT_FILE \"${VENV}/environment.txt\")
    execute_process(COMMAND \"${Python3_EXECUTABLE}\" -m venv \"${VENV}\")
    execute_process(COMMAND \"${BIN_DIR}/pip\" install -U pip wheel)
    execute_process(COMMAND \"${BIN_DIR}/pip\" install -r \"${REQUIREMENTS}\")
    execute_process(COMMAND \"${BIN_DIR}/pip\" freeze > \"${VENV}/environment.txt\")
    execute_process(COMMAND \"${REQUIREMENTS}\")
")

另请参阅关于execute_process的文档,如果你想处理命令失败等情况。

英文:

You should be able to do this using install(SCRIPT) or install(CODE):

> The SCRIPT form will invoke the given CMake script files during installation. If the script file name is a relative path it will be interpreted with respect to the current source directory. The CODE form will invoke the given CMake code during installation. Code is specified as a single argument inside a double-quoted string.

I believe it would be done something like this (using the CODE form here to make it easier to do variable substitution and use some of the variables that wouldn't be available outside the context of the configuration phase (i.e. if you were to use the SCRIPT mode) without explicitly passing them):

install(CODE "
    set(VENV \"${CMAKE_INSTALL_PREFIX}/venv\")
    set(REQUIREMENTS \"${CMAKE_SOURCE_DIR}/tools/testing/scripts/requirements.txt\")
    set(BIN_DIR \"${VENV}/bin\")
    set(OUTPUT_FILE \"${VENV}/environment.txt\")
    execute_process(COMMAND \"${Python3_EXECUTABLE}\" -m venv \"${VENV}\")
    execute_process(COMMAND \"${BIN_DIR}/pip\" install -U pip wheel)
    execute_process(COMMAND \"${BIN_DIR}/pip\" install -r \"${REQUIREMENTS}\")
    execute_process(COMMAND \"${BIN_DIR}/pip\" freeze > \"${VENV}/environment.txt\")
    execute_process(COMMAND \"${REQUIREMENTS}\")
")

See also the docs for execute_process if you want to do things like handle command failures, etc.

huangapple
  • 本文由 发表于 2023年2月24日 06:59:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/75551166.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定