如何在 Windows 上为 CMake 自定义命令设置运行时 PATH [英] How to set runtime PATH for CMake custom command on Windows

查看:187
本文介绍了如何在 Windows 上为 CMake 自定义命令设置运行时 PATH的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将基于 CMake 的 *nix 项目移植到 Windows.主库需要的一个头文件是由自定义程序生成的,所以CMakeLists.txt文件包含如下内容:

I'm trying to port a *nix, CMake-based project to Windows. One header file needed by the main library is generated by a custom program, so the CMakeLists.txt file contains something like this:

add_executable(TableGenerator "TableGenerator.cpp")
target_link_libraries(TableGenerator ${LibFoo_LIBRARY})

add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/Table.h"
                   COMMAND TableGenerator "${CMAKE_CURRENT_BINARY_DIR}/Table.h"
                   DEPENDS TableGenerator)

一个重要的细节是TableGenerator 使用外部共享库LibFoo.例如在 Linux 下,一切正常,因为 libfoo.so 安装在系统库目录之一中,例如 /usr/local/lib,或者 CMake 甚至设置了 rpath可执行文件中的属性,说明在哪里可以找到库.

An important detail is that TableGenerator uses the external shared library LibFoo. For example under Linux, everything works fine, because libfoo.so is installed in one of the system library directories like /usr/local/lib, or CMake even sets the rpath attribute in the executable, saying where exactly to find the library.

然而,在 Windows 上,这些库通常不会安装到系统中,而只是被提取或编译到构建树中或附近的某个任意目录中.为了让 TableGenerator 运行,foo.dll 需要在 Dynamic-Link Library Search Order 路径(比如 %WINDIR%System32 或构建TableGenerator 的输出目录),这是不可取的.

On Windows, however, these kind of libraries are usually not installed into the system but are rather just extracted or compiled into some arbitrary directory in or near the build tree. In order for TableGenerator to run, the foo.dll would need to be available in or copied to one of the Dynamic-Link Library Search Order paths (say %WINDIR%System32 or the build output directory for TableGenerator), which is not desirable.

如何为自定义命令设置 PATH 环境变量,即不使用 在 CMake 运行期间 但在实际的自定义构建步骤运行时期间?

How can I set the PATH environment variable for the custom command, i.e. to be used not during the CMake run but during the actual custom build step runtime?

推荐答案

虽然我仍在研究以正确提出问题,但我已经找到了三个解决方案.考虑到找到这些信息有多么困难,我还是决定在这里发布问题和答案.

While still doing my research in order to ask the question properly, I have found three solutions. Considering how hard it was to find this information, I decided to post the question and answer here anyway.

有一个专门用于解决这个确切问题的特殊变量——CMAKE_MSVCIDE_RUN_PATH.如果设置,则会将这样的行添加到自定义构建步骤脚本中:

There is a special variable dedicated to solving this exact problem – CMAKE_MSVCIDE_RUN_PATH. If set, it results in a line like this being added to the custom build step script:

set PATH=<CMAKE_MSVCIDE_RUN_PATH>;%PATH%

那么,所需要的就是在一个好地方这样的东西:

So all that's needed then is something like this at a good place:

set(CMAKE_MSVCIDE_RUN_PATH ${LibFoo_RUNTIME_LIBRARY_DIRS})

我最初只在 CMake 源代码中注意到这个变量,因为它在 CMake 3.10 之前一直没有记录.因此,您可能无法在旧版 CMake 的文档中找到它,但别担心,它是 自 2006 年起支持.

I have originally noticed this variable only in CMake sources, because it used to be undocumented until CMake 3.10. So you might not be able to find it in documentation for older versions of CMake, but don't worry, it's been supported since 2006.

优点:
▪ 可以在一个中心位置启用
▪ 无需对其他地方的任何 add_custom_command() 命令进行任何更改
▪ 只设置路径本身,无需显式编写批处理命令
▪ 明确的名称和意图的明显选择

Advantages:
▪ Can be enabled at one central place
▪ No change at all in any of the add_custom_command() commands elsewhere is needed
▪ Only the path itself is set, no batch commands need to be written explicitly
▪ The obvious choice with clear name and intent

缺点:
▪ 全局用于整个 CMake 项目和所有自定义命令
▪ 仅适用于Visual Studio 9 2008"及更高版本的生成器

Disadvantages:
▪ Global for the whole CMake project and all custom commands
▪ Works with the "Visual Studio 9 2008" and above generators only

为 Visual Studio 中的自定义构建步骤生成的脚本包含一些序言,然后是命令本身,然后是一些尾声.难道不能通过另一个 COMMAND 参数在真正的命令之前简单地添加 set PATH=... 吗?

The script being generated for the custom build step in Visual Studio contains some prologue, then the commands themselves and then some epilogue. Wouldn't it be possible to simply add set PATH=... before the real command through another COMMAND parameter?

add_custom_command() 的文档说:

命令
指定要在构建时执行的命令行.如果指定了多个 COMMAND,它们将按顺序执行,但不一定必须组合成有状态的 shell 或批处理脚本.

COMMAND
Specify the command-line(s) to execute at build time. If more than one COMMAND is specified they will be executed in order, but not necessarily composed into a stateful shell or batch script.

所以不,这不能保证是可能的.但 Visual Studio 项目生成器实际上 这样做,即单个命令只是一个接一个地附加,所以以下工作:

So no, that's not guaranteed to be possible. But the Visual Studio project generator actually does it like this, i.e. the individual commands are just appended one after another, so the following does the job:

add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/Table.h"
                   COMMAND set "PATH=${LibFoo_RUNTIME_LIBRARY_DIRS};%PATH%"
                   COMMAND TableGenerator "${CMAKE_CURRENT_BINARY_DIR}/Table.h"
                   DEPENDS TableGenerator)

优点:
▪ 可以为每个自定义命令显式更改 PATH

Advantages:
▪ The PATH can be changed for each custom command explicitly

缺点:
▪ 依赖于未记录在案的生成器行为
▪ 有必要为 Windows 重写整个命令并使两个版本保持同步
▪ 每个自定义命令都必须明确更改

Disadvantages:
▪ Relies on an undocumented behavior of the generator
▪ It's necessary to rewrite the whole command for Windows and keep both versions in sync
▪ Each custom command must be changed explicitly

以上引用的 add_custom_command() 文档继续:

要运行完整脚本,请使用 configure_file() 命令或 file(GENERATE) 命令创建它,然后指定一个 COMMAND 启动它.

To run a full script, use the configure_file() command or the file(GENERATE) command to create it, and then specify a COMMAND to launch it.

这有点乱,因为额外的临时文件和命令:

This is a bit messy because of the additional temporary files and commands:

file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/RunTableGenerator.cmd"
              CONTENT "set PATH=${LibFoo_RUNTIME_LIBRARY_DIRS};%PATH%
                       %1 ${CMAKE_CURRENT_BINARY_DIR}/Table.h")
add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/Table.h"
                   COMMAND "${CMAKE_CURRENT_BINARY_DIR}/RunTableGenerator.cmd" "$<TARGET_FILE:TableGenerator>"
                   DEPENDS TableGenerator)

注意将可执行文件的路径作为参数发送的尴尬方式.这是必要的,因为脚本编写一次,但 TableGenerator 可能位于不同的位置以用于不同的配置(调试和发布).如果直接在内容中使用生成器表达式,则会打印 CMake 错误,并且除了一种配置外,项目将无法正确构建.

Notice the awkward way of sending the path to the executable as an argument. This is necessary because the script is writen once, but TableGenerator might be in different locations for different configurations (debug and release). If the generator expression was used directly in the content, a CMake error would be printed and the project would not build correctly for all but one configuration.

优点:
▪ 可以为每个自定义命令显式更改 PATH
▪ 完整记录和推荐的解决方案

Advantages:
▪ The PATH can be changed for each custom command explicitly
▪ A fully documented and recommended solution

缺点:
▪ CMakefiles 中非常嘈杂
▪ 有必要为 Windows 重写整个命令并使两个版本保持同步
▪ 每个自定义命令都必须明确更改

Disadvantages:
▪ Very noisy in the CMakefiles
▪ It's necessary to rewrite the whole command for Windows and keep both versions in sync
▪ Each custom command must be changed explicitly

请参阅下面由 Dvir Yitzchaki 提供的其他答案.

See the other answer below contributed by Dvir Yitzchaki.

我个人选择了解决方案 #1,因为它干净简单,甚至在它在 3.10 版中得到 CMake 正确记录和支持之前也是如此.这对您来说也应该是最好的前进方式,除非您需要做一些更特别的事情.

I had personally settled on the solution #1 because it was clean and simple, even before it got properly documented and supported by CMake in version 3.10. It should be the best way forward for you as well, unless you need to do something even more special.

这篇关于如何在 Windows 上为 CMake 自定义命令设置运行时 PATH的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆