1

我正在为 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:)

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

4

2 回答 2

1

CMake 模块可以相互包含,因此会导致菱形问题。如果你幸运的话,你有双重工作来设置一些变量,但如果你需要一些复杂的东西,事情可能会变得更糟。

例子:

FindB.cmake

find_package(A)

查找A.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)
于 2013-07-10T04:16:30.807 回答
0

可以使用包含防护,但有一些限制,如下所述

请注意,包含保护变量的类型不应该是 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 文件中,我在开始时使用以下代码段:

include(IncludeGuard)
cmake_include_guard()

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

于 2017-09-25T20:07:23.530 回答