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

时间:2013-05-29 20:49:03

标签: cmake cross-compiling toolchain include-guards

我正在为VxWorks编写一个交叉编译工具链文件。由于cmake是一个未知的系统,因此也有写平台文件(../Modules/Platform中的那些文件)。

在我的工具链文件旁边,我已经编写了这些平台文件:

  • VxWorks.cmake (VxWorks操作系统设置)
  • VxWorks-gcc.cmake (WindRiver(Gnu)编译器设置)
  • VxWorks-gcc- [CPU] .cmake (CPU特定设置,是工具链文件中指定的处理器)

目前我的文件一切正常。

但是有些默认平台文件包含一个包含警卫/ include blocker ,就像这样:

if(__WINDOWS_GNU)
  return()
endif()
set(__WINDOWS_GNU 1)

(来自:Modules/Platform/Windows-GNU.cmake

所以我想知道:我是否也必须插入这样的警卫?什么时候插入它们是个好主意?

2 个答案:

答案 0 :(得分:1)

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)

答案 1 :(得分:0)

可以使用包含保护,但有一些限制,如here所述:

  

请注意,include guard变量的类型永远不应该是CACHE变量,因为这会导致变量在多个CMake配置运行中持续存在,从而导致阻止任何后续运行的错误在模块文件中读取#39的内容。然而,非CACHE变量也不完全合适,因为外来作用域(尚未采用该变量定义)将导致(有些不必要且可能存在问题)重新读取文件的内容。因此,最好的选择是通过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文件中,我在beggining:

使用以下代码段
include(IncludeGuard)
cmake_include_guard()

cmake_include_guard使用return()停止进一步的内容处理。