我正在为VxWorks编写一个交叉编译工具链文件。由于cmake是一个未知的系统,因此也有写平台文件(../Modules/Platform
中的那些文件)。
在我的工具链文件旁边,我已经编写了这些平台文件:
目前我的文件一切正常。
但是有些默认平台文件包含一个包含警卫/ include blocker ,就像这样:
if(__WINDOWS_GNU)
return()
endif()
set(__WINDOWS_GNU 1)
(来自:Modules/Platform/Windows-GNU.cmake
)
所以我想知道:我是否也必须插入这样的警卫?什么时候插入它们是个好主意?
答案 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()
停止进一步的内容处理。