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

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

问题描述

我正在尝试将基于CMake的* nix项目移植到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 =nofollow noreferrer>动态链接库搜索顺序路径(说%WINDIR%\System32 TableGenerator 的构建输出目录),这是不可取的。



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

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






1。使用两个命令设置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的整个命令,并保留所有内容rsions同步

▪每个自定义命令必须明确更改






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



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


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


这是由于额外的临时文件和命令有点混乱:

 文件(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

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



缺点:

▪在CMake文件中非常嘈杂

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

▪必须明确更改每个自定义命令






3。使用未记录的变量 CMAKE_MSVCIDE_RUN_PATH



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

 设置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自定义命令设置运行时PATH的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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