【问题标题】: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

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

【问题讨论】:

    标签: cmake cross-compiling toolchain include-guards


    【解决方案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 命令,让您不必手动编写包含防护。
      猜你喜欢
      • 1970-01-01
      • 2019-07-22
      • 2019-09-27
      • 2011-08-24
      • 1970-01-01
      • 2021-08-26
      • 2016-04-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多