(交叉编译)平台文件是不是需要包含保护?

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 命令,让您不必手动编写包含防护。

以上是关于(交叉编译)平台文件是不是需要包含保护?的主要内容,如果未能解决你的问题,请参考以下文章

什么是交叉编译

交叉编译

玩转开发板之交叉编译器安装

交叉编译概述

交叉编译-如何编译Android平台的可执行程序

x86 平台代码移植到 嵌入式平台[交叉编译三方库]