CMake: USES_TERMINAL argument in add_custom_command(TARGET) does not use console pool with Ninja

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

CMake: USES_TERMINAL argument in add_custom_command(TARGET) does not use console pool with Ninja

问题

在CMake中,如果我在使用add_custom_command时使用USES_TERMINAL,以便在使用sudo运行命令时获得用户密码的提示,如下面的CMakeLists.txt片段所示:

add_executable(my-app main.c)

add_custom_command(
    TARGET my-app
    POST_BUILD
    COMMAND sudo setcap cap_net_admin+eip $<TARGET_FILE:my-app>
    USES_TERMINAL
)

然后使用Ninja配置和构建:

$ cmake -G Ninja -B build
$ cmake --build build

用户密码的提示不会出现,并且构建会挂起。查看生成的build.ninja文件,我期望在构建my-app时应该有一个pool = console的设置,但它并不存在:

build my-app: C_EXECUTABLE_LINKER__my-app_ CMakeFiles/my-app.dir/main.c.o
  OBJECT_DIR = CMakeFiles/my-app.dir
  POST_BUILD = cd /home/bob/test_cmake_uses_terminal/build && sudo setcap cap_net_admin+eip /home/bob/test_cmake_uses_terminal/build/my-app
  PRE_LINK = :
  TARGET_COMPILE_PDB = CMakeFiles/my-app.dir/
  TARGET_FILE = my-app
  TARGET_PDB = my-app.pdb

如果我手动将pool = console添加到列表中,它将正确提示用户输入密码。

我已经通过使用add_custom_target以更不优雅的方式使其工作,但我想知道为什么USES_TERMINAL不像我所理解的那样工作,根据文档来看。

我使用的是CMake版本3.24.1,运行在Ubuntu 22.04上,如果有帮助的话。

更新:

关于此问题已提交错误报告:https://gitlab.kitware.com/cmake/cmake/-/issues/25040

英文:

In CMake, if I use add_custom_command with USES_TERMINAL in order to get a prompt for a user's password when running a command using sudo, as seen in the following CMakeLists.txt snippet:

add_executable(my-app main.c)

add_custom_command(
    TARGET my-app
    POST_BUILD
    COMMAND sudo setcap cap_net_admin+eip $&lt;TARGET_FILE:my-app&gt;
    USES_TERMINAL
)

And then configure and build using Ninja:

$ cmake -G Ninja -B build
$ cmake --build build

The prompt for the user's password does not appear, and the build hangs. Looking at the resulting build.ninja file, I would expect there to be a pool = console setting for building my-app, but it's not present:

build my-app: C_EXECUTABLE_LINKER__my-app_ CMakeFiles/my-app.dir/main.c.o
  OBJECT_DIR = CMakeFiles/my-app.dir
  POST_BUILD = cd /home/bob/test_cmake_uses_terminal/build &amp;&amp; sudo setcap cap_net_admin+eip /home/bob/test_cmake_uses_terminal/build/my-app
  PRE_LINK = :
  TARGET_COMPILE_PDB = CMakeFiles/my-app.dir/
  TARGET_FILE = my-app
  TARGET_PDB = my-app.pdb

If I manually add pool = console to that list, it properly prompts for the user's password when runnning the command.

I was able to get this to work in a more kludgey way using add_custom_target, but I'd like to know why USES_TERMINAL is not working as I interpret the documentation.

I'm using cmake version 3.24.1 and running on Ubuntu 22.04, if that helps.


Update:

Bug report submitted regarding this issue: https://gitlab.kitware.com/cmake/cmake/-/issues/25040

答案1

得分: 1

原来 USES_TERMINAL 从未打算在调用带有 TARGET 参数的 add_custom_command 时使用。

使自定义命令可用于终端的最佳方法是在添加自定义命令的目标上设置属性 JOB_POOL_LINKconsole

set_property(TARGET my-app PROPERTY JOB_POOL_LINK console)
add_custom_command(
    TARGET my-app
    POST_BUILD
    COMMAND sudo setcap cap_net_admin+eip $<TARGET_FILE:my-app>)

另一个潜在的解决方法是使用带有 USES_TERMINAL 参数的 add_custom_target,但这会导致命令在每次构建时执行,这可能是不希望的:

add_custom_target(
    run_sudo_setcap
    ALL
    COMMAND sudo setcap cap_net_admin+eip $<TARGET_FILE:my-app>
    DEPENDS my-app
    USES_TERMINAL)

Solution 取自与此问题相关的错误报告中发布的建议:https://gitlab.kitware.com/cmake/cmake/-/issues/25040#note_1381770

请注意,CMake 的最新文档将不再显示 USES_TERMINAL 作为 add_custom_command(TARGET) 命令的支持参数:

https://gitlab.kitware.com/cmake/cmake/-/merge_requests/8602

https://cmake.org/cmake/help/git-master/command/add_custom_command.html#build-events

英文:

It turns out that USES_TERMINAL was never intended to be used when calling add_custom_command with TARGET in its signature.

The best way to have the terminal available to the custom command is to set the property JOB_POOL_LINK to console on the target on which the custom command is being added:

set_property(TARGET my-app PROPERTY JOB_POOL_LINK console)
add_custom_command(
    TARGET my-app
    POST_BUILD
    COMMAND sudo setcap cap_net_admin+eip $&lt;TARGET_FILE:my-app&gt;)

One other potential workaround would be to use add_custom_target with the USES_TERMINAL parameter, but this results in undesirable behavior of the command being executed on every build:

add_custom_target(
    run_sudo_setcap
    ALL
    COMMAND sudo setcap cap_net_admin+eip $&lt;TARGET_FILE:my-app&gt;
    DEPENDS my-app
    USES_TERMINAL)

Solution taken from the recommendation posted on the bug report related to this issue: https://gitlab.kitware.com/cmake/cmake/-/issues/25040#note_1381770

And note that the newest docs for CMake will no longer show USES_TERMINAL as a supported parameter to the add_custom_command(TARGET) command:

https://gitlab.kitware.com/cmake/cmake/-/merge_requests/8602

https://cmake.org/cmake/help/git-master/command/add_custom_command.html#build-events

huangapple
  • 本文由 发表于 2023年6月29日 04:08:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/76576407.html
匿名

发表评论

匿名网友

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

确定