如何在编译时在 CMake 生成的 Makefile 中运行命令? [英] How to run a command at compile time within Makefile generated by CMake?

查看:88
本文介绍了如何在编译时在 CMake 生成的 Makefile 中运行命令?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想将一些选项传递给编译器.该选项必须在编译时计算 - 每次调用 'make' 时,而不是调用 'cmake' 时,因此 execute_process 命令不会剪切它.(是吗?)

I would like to pass some options to a compiler. The option would have to be calculated at compile time - everytime when 'make' is invoked, not when 'cmake', so execute_process command does not cut it. (does it?)

例如将日期传递给这样的 g++ 编译器:

For instance passing a date to a g++ compiler like that:

g++ prog.cpp -o prog -DDATETIME="17:09:2009,14:25"

但在编译时计算 DATETIME.

But with DATETIME calculated at compile time.

知道如何在 CMake 中做到这一点吗?

Any idea how to do it in CMake?

赏金

将接受最少黑客的解决方案.

A least hackish solution will be accepted.

请注意,我希望能够在编译时执行任意命令,而不仅仅是日期".

Please note that I want to be able to exectue an arbitrary command at compile time, not only 'date'.

编辑 2:

它必须适用于 Linux、Windows (VS)、Mingw、Cygwin 和 OS X.您不能假设 Ruby、Perl 或 Python,因为它们在 Windows 上是非标准的.你可以假设 BOOST,但我想它没有用.

It have to work on Linux, Windows (VS), Mingw, Cygwin and OS X. You can't assume Ruby, Perl or Python as they are non standard on Windows. You can assume BOOST, but I guess it's no use.

目标是强制 cmake 生成 Makefile(在 Linux 的情况下),当执行 make 时,它​​将完成工作.

The goal is to force cmake to generate Makefile (in case of Linux) that when make is executed, will do the job.

创建自定义 *.h 文件是可以的,但它必须由 make 的 Makefile(或其他操作系统上的等效文件)启动.*.h 的创建不必(也不应该)使用 cmake.

Creating custom *.h file is ok, but it has to be initiated by a Makefile (or equivalent on other OS) by make. The creation of *.h doesn't have to (and shouldn't have to) use cmake.

推荐答案

您遗漏了一些信息,例如您需要哪些平台运行它,如果有任何其他工具可以使用.如果你可以使用Ruby、Perl、Python,事情变得简单多了.患病的假设您想在 Unix 和 Windows pqlatform 上运行,并且没有额外的工具可用.

You're leaving out some information, such as which platforms you need to run this on and if there are any additional tools you can use. If you can use Ruby, Perl, of Python, things become much simpler. I'll assume that you want to run on both Unix and Windows pqlatform and that there are no extra tools available.

如果你想在预处理器符号中输出命令,最简单的方法是生成一个头文件而不是摆弄带命令行参数.请记住,CMake 具有脚本模式(-P) 它只处理文件中的脚本命令,所以你可以做这样的事情:

If you want the output from the command in a preprocessor symbol, the easiest way is to generate a header file instead of fiddling around with command line parameters. Remember that CMake has a script-mode (-P) where it only processes script commands in the file, so you can do something like this:

CMakeLists.txt:

CMakeLists.txt:

project(foo)  
cmake_minimum_required(VERSION 2.6)
add_executable(foo main.c custom.h)
include_directories(${CMAKE_CURRENT_BINARY_DIR})  
add_custom_command(OUTPUT custom.h 
    COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_SOURCE_DIR}/custom.cmake)

文件custom.h"是在编译时通过命令cmake"生成的-P custom.cmake".custom.cmake 看起来像这样:

The file "custom.h" is generated at compile time by the command "cmake -P custom.cmake". custom.cmake looks like this:

execute_process(COMMAND uname -a 
    OUTPUT_VARIABLE _output OUTPUT_STRIP_TRAILING_WHITESPACE)
file(WRITE custom.h "#define COMPILE_TIME_VALUE "${_output}"")

它执行命令(在本例中为uname -a",您将替换它使用您希望的任何命令),并将输出放入变量中_output,然后将其写入 custom.h.请注意,这只会如果命令输出单行,则工作.(如果你需要多行输出,你必须写一个更复杂的custom.cmake,取决于您希望如何将多行数据放入您的程序中.)

It executes the command (in this case "uname -a", you'll replace it with whatever command you wish), and puts the output in the variable _output, which it then writes to custom.h. Note that this will only work if the command outputs a single line. (If you need multiline output, you'll have to write a more complex custom.cmake, depending on how you want the multiline data into your program.)

主程序如下所示:

#include <stdio.h>
#include "custom.h"
int main()
{
  printf("COMPILE_TIME_VALUE: %s
", COMPILE_TIME_VALUE);
  return 0;
}

如果你真的想在编译时计算编译器选项,事情变得更加棘手.对于 Bourne-shell 生成器,您可以在反引号内插入命令.如果你在想办法的时候生气引用,将命令的所有逻辑移动到 shell 脚本中,以便你只需要把 mycommand.sh 放在你的 add_definitions() 中:

If you actually want to to calculate compiler options at compile time, things become much trickier. For Bourne-shell generators you can just insert the command inside backticks. If you get mad while figuring out quoting, move all the logic of your command inside a shell-script so you only need to put mycommand.sh in your add_definitions():

if(UNIX)
  add_definitions(`${CMAKE_CURRENT_SOURCE_DIR}/custom-options.sh`)
endif()

对于基于 Windows 批处理文件的生成器,事情要复杂得多,我没有很好的解决办法.问题在于 PRE_BUILD 命令不作为与实际编译器相同的批处理文件的一部分执行调用(研究 BuildLog.htm 以获取详细信息),所以我最初的想法不起作用(在 PRE_BUILD 步骤中生成 custom.bat 然后执行在它上面调用 custom.bat"以获得一个变量集,以后可以在编译器命令行中引用).如果有一个等价物批处理文件中的反引号,这将解决问题.

For Windows batch file based generators things are much tricker, and I don't have a good solution. The problem is that the PRE_BUILD commands are not executed as part of the same batch file as the actual compiler invocation (study the BuildLog.htm for details), so my initial idea did not work (generating a custom.bat in a PRE_BUILD step and then do "call custom.bat" on it to get a variable set which can later be referenced in the compiler command line). If there is an equivalent of backticks in batch files, that would solve the problem.

希望这能提供一些想法和起点.

Hope this gives some ideas and starting points.

(现在到不可避免的反问:你到底是什么想做什么?)

(Now to the inevitable counter-question: what are you really trying to do?)

我不确定您为什么不想让 CMake 用于生成头文件.使用 ${CMAKE_COMMAND} 将扩展到用于生成 Makefiles/.vcproj-files 的 CMake,并且由于 CMake 并不真正支持便携式 Makefiles/.vcproj-files,因此您需要在目标机器上重新运行 CMake.

I'm not sure why you don't want to let CMake be used to generate the header-file. Using ${CMAKE_COMMAND} will expand to the CMake used to generate the Makefiles/.vcproj-files, and since CMake doesn't really support portable Makefiles/.vcproj-files you will need to rerun CMake on the target machines.

出于这个明确的原因,CMake 也有一堆实用程序命令(运行cmake -E"获取列表).例如你可以做

CMake also has a bunch of utility commands (Run "cmake -E" for a list) for this explicit reason. You can for example do

add_custom_command(OUTPUT custom.h COMMAND ${CMAKE_COMMAND} -E copy file1.h file2.h)

将file1.h复制到file2.h.

to copy file1.h to file2.h.

无论如何,如果您不想使用 CMake 生成头文件,您将需要调用单独的 .bat/.sh 脚本来生成头文件,或者使用 echo 来生成:

Anyway, if you don't want to generate the header-files using CMake, you will either need to invoke separate .bat/.sh scripts to generate the header file, or do it using echo:

add_custom_command(OUTPUT custom.h COMMAND echo #define SOMETHING 1 > custom.h)

根据需要调整引用.

这篇关于如何在编译时在 CMake 生成的 Makefile 中运行命令?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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