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

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

问题描述

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

  add_executable(TableGeneratorTableGenerator.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属性,说明在哪里可以找到库。



但在Windows上,通常不会安装到系统中,而只是提取或编译到构建树中或附近的某个任意目录。为了运行 TableGenerator foo.dll 需要可用或复制到< a href =https://msdn.microsoft.com/en-us/library/windows/desktop/ms682586.aspx>动态链接库搜索订单路径(例如%WINDIR %\System32 TableGenerator 的生成输出目录),这是不可取的。



如何为自定义命令设置 PATH 环境变量,即不要使用

在进行我的研究以正确地提出问题时,我发现了三个解决方案。考虑到查找这些信息有多难,我决定在这里发布问题和答案。






1。使用两个 COMMAND 参数显式设置PATH



为Visual Studio中的自定义构建步骤生成的脚本包含一些序言,然后命令本身,然后一些结语。不可能简单地添加在真实命令之前通过另一个 COMMAND 参数设置PATH = ...



add_custom_command() 说明:


COMMAND

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


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

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

优点:

可以为每个自定义命令显式更改PATH。



缺点:

▪依赖于生成器的未记录行为

▪必须重写Windows的整个命令,并保持两个版本同步

▪必须显式更改每个自定义命令






2。使用文件(GENERATE ...)创建自定义脚本



add_custom_command() 的rel =nofollow>文档继续:


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


由于附加的临时文件和命令,有点乱。

  file(GENERATE OUTPUT$ { CMAKE_CURRENT_BINARY_DIR} /RunTableGenerator.cmd
CONTENTset 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)
/ pre>

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





▪可以为每个自定义命令明确更改PATH

▪完整记录并推荐的解决方案



缺点:

▪CMakefiles很嘈杂

▪有必要重写Windows的整个命令,并保持两个版本同步

▪必须显式更改每个自定义命令






3。使用未记录的变量 CMAKE_MSVCIDE_RUN_PATH



在查看CMake源时,我注意到有一个未记录的变量 CMAKE_MSVCIDE_RUN_PATH ,如果设置,则将这样的行添加到自定义构建步骤脚本中:

  set PATH =< CMAKE_MSVCIDE_RUN_PATH> ;%PATH%

那么所需要的就是这样的地方:

  set(CMAKE_MSVCIDE_RUN_PATH $ {LibFoo_RUNTIME_LIBRARY_DIRS})

优点:

▪可在一个中心位置启用

▪无变化所有在任何 add_custom_command()命令在其他地方

▪只有路径本身设置,没有批处理命令需要明确写入

缺点:

▪整个CMake项目和所有自定义命令的全局

▪变量






我已经亲自解决了解决方案#3,因为它是干净的,简单,希望它会留下来。毕竟,已经有 9年


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)

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.

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.

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.


1. Setting the PATH explicitly using two COMMAND parameters

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?

The documentation for add_custom_command() says:

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.

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)

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

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


2. Using file(GENERATE ...) to create a custom script

The documentation for add_custom_command() quoted above continues:

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)

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.

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

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


3. Using undocumented variable CMAKE_MSVCIDE_RUN_PATH

While looking at the CMake sources, I noticed there was an undocumented variable CMAKE_MSVCIDE_RUN_PATH which, if set, resulted 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})

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

Disadvantages:
▪ Global for the whole CMake project and all custom commands
▪ The variable is undocumented (therefore can get removed etc.)


I have personally settled on the solution #3 because it is clean and simple, hoping that it will stay. After all, it's been there for 9 years already.

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

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