(交叉编译)平台文件是不是需要包含保护?
Posted
技术标签:
【中文标题】(交叉编译)平台文件是不是需要包含保护?【英文标题】:Do (Cross-compile) platform files require an include guard?(交叉编译)平台文件是否需要包含保护? 【发布时间】:2013-05-25 06:47:06 【问题描述】:我正在为 VxWorks 编写一个交叉编译工具链文件。由于 cmake 是一个未知系统,因此也有写入平台文件(../Modules/Platform
中的那些)。
到目前为止,除了我的 工具链 文件之外,我还编写了以下平台文件:
VxWorks.cmake(VxWorks 操作系统设置) VxWorks-gcc.cmake(WindRiver (Gnu) 编译器设置) VxWorks-gcc-[CPU].cmake(CPU 特定设置,是工具链文件中指定的处理器)目前我的文件一切正常。
但一些默认平台文件包含一个包含保护/包含阻止程序,如下所示:
if(__WINDOWS_GNU)
return()
endif()
set(__WINDOWS_GNU 1)
(来自:Modules/Platform/Windows-GNU.cmake
)
所以我想知道:我是否也必须插入这样的警卫?什么时候插入它们是个好主意?
【问题讨论】:
【参考方案1】:可以使用包含守卫,但有一些限制,如 here 所述:
请注意,include 保护变量的类型不应该是 CACHE 变量,因为这会导致变量在多个 CMake 配置运行中持续存在,从而导致阻止任何后续运行读取模块文件内容的错误。然而,非缓存变量也不完全合适,因为外部范围(尚未采用该变量定义)将导致(有些不必要且可能有问题)重新读取文件内容。因此,最好的选择是通过 GLOBAL 属性设置来实现此检查,因为此类设置具有所有所需的特征:它们都是全局有效的并且仅适用于单会话。
其次,请注意,只有支持这种结构的模块文件(即,仅声明函数或将其所有设置定义为 CACHE 变量的文件)才能毫无问题地使用包含保护(非 CACHE 变量,虽然可能是在这些函数中引用,可能会突然超出范围,但该函数仍可访问)。
就我而言,我有 IncludeGuard.cmake
文件,其内容如下:
# Include this file and invoke cmake_include_guard to prevent the CMake script
# parse invoker file multiple times.
macro(cmake_include_guard)
get_property(INCLUDE_GUARD GLOBAL PROPERTY "INCLUDE_GUARD_$CMAKE_CURRENT_LIST_FILE")
if(INCLUDE_GUARD)
return()
endif()
set_property(GLOBAL PROPERTY "INCLUDE_GUARD_$CMAKE_CURRENT_LIST_FILE" TRUE)
endmacro()
在常见的 cmake 文件中,我在开始时使用以下 sn-p:
include(IncludeGuard)
cmake_include_guard()
宏 cmake_include_guard
使用 return()
停止进一步的内容处理。
【讨论】:
【参考方案2】:CMake 模块可以相互包含,因此可以导致diamond problem。 如果你幸运的话,你有双重工作来设置一些变量,但如果 你需要一些复杂的东西,事情可能会变得更糟。
例子:
FindB.cmake
find_package(A)
FindA.cmake
find_package(B)
CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
list(APPEND CMAKE_MODULE_PATH $CMAKE_CURRENT_LIST_DIR)
find_package(A) # include FindA.cmake, which include FindB.cmake
# which include FindA.cmake ....
现在运行 cmake 。
-- The C compiler identification is Clang 4.2.0
-- The CXX compiler identification is Clang 4.2.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
Segmentation fault: 11
只需在模块开头使用守卫(让变量描述路径以防止冲突)
FindB.cmake
if(FIND_B_CMAKE)
return()
endif()
set(FIND_B_CMAKE 1)
find_package(A)
【讨论】:
目前我没有任何钻石问题;我的平台文件中的大部分代码都是设置变量等。但也许一旦这会变得相关,所以我最好包括那些警卫。感谢您的回答! 请注意,CMake 3.10 引入了一个include_guard
命令,让您不必手动编写包含防护。以上是关于(交叉编译)平台文件是不是需要包含保护?的主要内容,如果未能解决你的问题,请参考以下文章