26

我使用 cmake 进行交叉编译。在我的工具链文件中有一行

SET(CMAKE_C_FLAGS "-std=gnu99")

此变量未在 CMakeLists.txt 中再次设置。

当我运行cmake -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake ..此标志时,将被忽略。

更详细地说: 的行flags.cmake显示一个空C_FLAGS =行。但在CMakeOutput.log我可以找到一条线Build flags: -std=gnu99

我发现第二次运行cmake ..(无论是否指定工具链文件都相同)解决了这个问题。

但是为什么我第一次运行 cmake 时没有设置它?

编辑:添加了 MNWE

CMakeLists.txt:

cmake_minimum_required(VERSION 2.6)
project(myproject)

SET(files src/main.c)

add_executable(myexec ${files})

avr.cmake:

SET(CMAKE_SYSTEM_NAME Generic)

SET(CMAKE_C_COMPILER avr-gcc)

SET(CMAKE_C_FLAGS "-std=gnu99")
4

2 回答 2

24

我通过更换线路找到了一个临时解决方案

SET(CMAKE_C_FLAGS "-std=gnu99")

经过

SET(CMAKE_C_FLAGS "-std=gnu99" CACHE STRING "" FORCE)
于 2012-07-18T07:49:46.507 回答
17

我只是想添加一些背景信息(例如在这里讨论如何为每个工具链设置 cmake_c/xx_flags?)。

简而言之,这些CMAKE_<LANG>_FLAGS变量被设计缓存在CMake<Lang>Information.cmake脚本中(这意味着您可以在配置步骤之后在 CMake 的 GUI 应用程序中更改它们)。

所以你必须 - 如果将它们设置在工具链文件中 - 首先将它们放入缓存中。CMake 自己的脚本(在 Toolchain 文件之后执行)没有附带FORCE,因此不会再次覆盖它。

查看 CMakeCInformation.cmake(来自 share\cmake-2.8\Modules):

set(CMAKE_C_FLAGS_INIT "$ENV{CFLAGS} ${CMAKE_C_FLAGS_INIT}")
# avoid just having a space as the initial value for the cache
if(CMAKE_C_FLAGS_INIT STREQUAL " ")
  set(CMAKE_C_FLAGS_INIT)
endif()
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS_INIT}" CACHE STRING
     "Flags used by the compiler during all build types.")

正如你所看到的,官方的做法是使用CMAKE_C_FLAGS_INIT注入额外的标志。存在的问题是,工具链文件中的后续更改将无法识别(缓存不会被覆盖,见上文)。

考虑到所有这些,您的临时解决方案是正确的选择。可以肯定的是——因为工具链文件在配置/生成过程中被解析了两次——你甚至可以在你的工具链文件中UNSET设置之前添加一个调用:CMAKE_C_FLAGS

UNSET(CMAKE_C_FLAGS CACHE)
SET(CMAKE_C_FLAGS "-std=gnu99" CACHE STRING "" FORCE)

另一个经常找到的解决方案是使用类似的东西:

add_definitions(" -std=gnu99")

注入编译标志(但这不是构建配置感知的,因为变量定义是)。另请参阅CMake clang 和 c++0x

使用 CMake 2.8.12 引入了新命令,因此您可以这样做(未经测试,只是为了展示可能性):

add_compile_options("$<$<CONFIG:RELASE>:-std=gnu99>")
add_compile_options("$<$<CONFIG:DEBUG>:-std=gnu99 -g3>")

请参阅在 CMake 中设置通用编译标志的现代方法是什么?CMake 生成器表达式,区分 C/C++ 代码以获取更多信息。

于 2015-05-13T13:58:00.797 回答