Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/cmake/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Recursion Cmake集变量是递归的吗?_Recursion_Cmake - Fatal编程技术网

Recursion Cmake集变量是递归的吗?

Recursion Cmake集变量是递归的吗?,recursion,cmake,Recursion,Cmake,我试图修改特定目录下所有目录的编译器标志(即,递归地修改当前所有目录子目录及其所有子目录的编译器标志)。所以我发现有两种方法: add_directory(dir1) # ... add_directory(dirN) add_compile_options(flag1 flag2 ...) # or for CMake versions < 3.0 to do something more like: set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} fl

我试图修改特定目录下所有目录的编译器标志(即,递归地修改当前所有目录子目录及其所有子目录的编译器标志)。所以我发现有两种方法:

add_directory(dir1)
# ...
add_directory(dirN)

add_compile_options(flag1 flag2 ...)
# or for CMake versions < 3.0 to do something more like:
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} flag1 flag2 ...")
add_目录(dir1)
# ...
添加目录(dirN)
添加编译选项(flag1 flag2…)
#或者对于<3.0的CMake版本,执行以下操作:
设置(CMAKE_CXX_标志“${CMAKE_CXX_标志}标志1标志2…”)
add\u compile\u options
的手册页非常清楚地说明了效果将是“当前目录和以下目录”(这是我想要的),但对于
set(CMAKE\u CXX\u标志…)
我不太确定


Cmake set variable recursive吗?

简单的回答是,在调用
add\u subdirectory()
时,每个子目录都有自己的变量范围,并使用当前变量值的副本初始化

有关详细答案,请参见

目录和目标属性vs(全局)变量

CMake处理和的方式存在差异:

  • 使用
    add\u compile\u options()
    指定的所有内容都将附加到目录属性。然后使用
    add\u library()
    add\u executable()
    “此属性用于在创建目标时初始化
    COMPILE\u选项
    target属性”

    当解析器进入
    add_subdirectory()
    调用时,目录属性的当前状态用于初始化子目录属性

  • 是一个全局缓存变量。您可以通过定义本地目录范围的变量(隐藏全局缓存的变量)来扩展/覆盖它

    这些变量的上下文被复制到
    add_subdirectory()
    (传播到子目录)上的子目录范围中

    CMake在每个
    CMakeLists.txt
    文件末尾查看其值,并将其应用于同一
    CMakeLists.txt
    中的所有目标(允许延迟声明,另请参见下面的完整公式和测试代码)

  • 因此,对于CMake版本<3.0,等效于添加编译选项()。功能仍然存在,但将定义与编译选项混合在一起很奇怪。于是
    add\u compile\u options()
    被发明出来

编译器标志的完整生成器公式

它在CMake的代码中(请参见和)

此示例显示了一个不带导出的
DEBUG
生成配置库,不考虑基于功能的标志或类似
CMAKE\u CXX\u USE\u RESPONSE\u FILE\u FOR\u INCLUDE
CMAKE\u QUOTE\u INCLUDE\u路径的内容:

  CMAKE_CXX_FLAGS       // as set at the end of target's CMakeLists.txt
+ CMAKE_CXX_FLAGS_DEBUG

+ Include Directories   // pefixed with CMAKE_INCLUDE_FLAG_CXX/CMAKE_INCLUDE_SYSTEM_FLAG_CXX

    (CMAKE_INCLUDE_CURRENT_DIR) ? 
        + CMAKE_CURRENT_SOURCE_DIR + CMAKE_CURRENT_BINARY_DIR
    + CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES
    + Target[INCLUDE_DIRECTORIES]
    + DependingTargets[INTERFACE_INCLUDE_DIRECTORIES] 

+ Define Flags         // compiler flags given with add_definitions()
+ Target[COMPILE_FLAGS] // deprecated
    - Filtered by CMAKE_CXX_FLAG_REGEX
+ Target[COMPILE_OPTIONS]
+ DependingTargets[INTERFACE_COMPILE_OPTIONS]
测试代码

为了更好地理解,以下是我的代码,用于测试编译器选项和得到的结果:

注意:通常我会使用
add_definitions()
target_compile_definitions()
而不是
add_compile_options()
target_compile_options()
来设置编译器定义,但为了演示编译器选项的传播,我(错误地)使用了
-D
标志

CMakeLists.txt

cmake_minimum_required(VERSION 3.0)

project(CxxFlagsTest)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DCXX_FLAG")
add_compile_options("-DCOMPILE_OPTION")

add_subdirectory(lib)

file(WRITE main.cpp "int main() { return 0; }")
add_executable(main main.cpp)
target_link_libraries(main lib)

target_compile_options(main PRIVATE "-DMAIN_COMPILE_OPTION")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DLATE_CXX_FLAG")

get_target_property(_main_compile_options main COMPILE_OPTIONS)
message(STATUS "main COMPILE_OPTIONS: ${_main_compile_options}")
get_directory_property(_root_compile_options COMPILE_OPTIONS)
message(STATUS "root COMPILE_OPTIONS: ${_root_compile_options}")
message(STATUS "root CMAKE_CXX_FLAGS: ${CMAKE_CXX_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSUB_CXX_FLAG")
add_compile_options("-DSUB_COMPILE_OPTION")

file(WRITE lib.cpp "")
add_library(lib lib.cpp)

target_compile_options(lib PUBLIC "-DLIB_COMPILE_OPTION")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DLATE_SUB_CXX_FLAG")

get_target_property(_lib_compile_options lib COMPILE_OPTIONS)
message(STATUS "lib COMPILE_OPTIONS: ${_lib_compile_options}")
get_directory_property(_sub_compile_options COMPILE_OPTIONS)
message(STATUS "sub COMPILE_OPTIONS: ${_sub_compile_options}")
message(STATUS "sub CMAKE_CXX_FLAGS: ${CMAKE_CXX_FLAGS}")
lib/CMakeLists.txt

cmake_minimum_required(VERSION 3.0)

project(CxxFlagsTest)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DCXX_FLAG")
add_compile_options("-DCOMPILE_OPTION")

add_subdirectory(lib)

file(WRITE main.cpp "int main() { return 0; }")
add_executable(main main.cpp)
target_link_libraries(main lib)

target_compile_options(main PRIVATE "-DMAIN_COMPILE_OPTION")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DLATE_CXX_FLAG")

get_target_property(_main_compile_options main COMPILE_OPTIONS)
message(STATUS "main COMPILE_OPTIONS: ${_main_compile_options}")
get_directory_property(_root_compile_options COMPILE_OPTIONS)
message(STATUS "root COMPILE_OPTIONS: ${_root_compile_options}")
message(STATUS "root CMAKE_CXX_FLAGS: ${CMAKE_CXX_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSUB_CXX_FLAG")
add_compile_options("-DSUB_COMPILE_OPTION")

file(WRITE lib.cpp "")
add_library(lib lib.cpp)

target_compile_options(lib PUBLIC "-DLIB_COMPILE_OPTION")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DLATE_SUB_CXX_FLAG")

get_target_property(_lib_compile_options lib COMPILE_OPTIONS)
message(STATUS "lib COMPILE_OPTIONS: ${_lib_compile_options}")
get_directory_property(_sub_compile_options COMPILE_OPTIONS)
message(STATUS "sub COMPILE_OPTIONS: ${_sub_compile_options}")
message(STATUS "sub CMAKE_CXX_FLAGS: ${CMAKE_CXX_FLAGS}")
将导致以下消息:

-- lib COMPILE_OPTIONS: -DCOMPILE_OPTION;-DSUB_COMPILE_OPTION;-DLIB_COMPILE_OPTION
-- sub COMPILE_OPTIONS: -DCOMPILE_OPTION;-DSUB_COMPILE_OPTION
-- sub CMAKE_CXX_FLAGS:  ... -DCXX_FLAG -DSUB_CXX_FLAG -DLATE_SUB_CXX_FLAG
-- main COMPILE_OPTIONS: -DCOMPILE_OPTION;-DMAIN_COMPILE_OPTION
-- root COMPILE_OPTIONS: -DCOMPILE_OPTION
-- root CMAKE_CXX_FLAGS:  ... -DCXX_FLAG -DLATE_CXX_FLAG
并设置以下预处理器定义:

lib

main

这里有趣的部分是
LATE
CXX标志和
LIB
compile选项传播到链接库

参考资料


递归是什么意思?变量将在
设置(..)
后在同一范围内定义。因此,如果您不是在宏或函数中定义它,并且您的add_子目录调用位于set(..)之后,那么该变量也会在子目录中定义。@TrevorBoydSmith在过去几个月里,我再次浏览了这个主题几次,并做了一些额外的测试,以查看编译标志在CMake中如何传播。我已经用测试结果更新了我的答案,并认为
add\u compile\u options()
优于
set(CMAKE\u CXX\u FLAGS…
,因为范围至少对我来说更容易理解。