> For the complete documentation index, see [llms.txt](https://chenxiaowei.gitbook.io/cmake-cookbook/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://chenxiaowei.gitbook.io/cmake-cookbook/7.0-chinese/7.6-chinese.md).

# 7.6 使用废弃函数、宏和变量

**NOTE**:*此示例代码可以在* <https://github.com/dev-cafe/cmake-cookbook/tree/v1.0/chapter-7/recipe-06> *中找到。该示例在CMake 3.5版(或更高版本)中是有效的，并且已经在GNU/Linux、macOS和Windows上进行过测试。*

“废弃”是在不断发展的项目开发过程中一种重要机制，它向开发人员发出信号，表明将来某个函数、宏或变量将被删除或替换。在一段时间内，函数、宏或变量将继续可访问，但会发出警告，最终可能会上升为错误。

## 准备工作

我们将从以下CMake项目开始:

```
cmake_minimum_required(VERSION 3.5 FATAL_ERROR)

project(recipe-06 LANGUAGES NONE)

macro(custom_include_guard)
  if(NOT DEFINED included_modules)
      set(included_modules)
  endif()

  if ("${CMAKE_CURRENT_LIST_FILE}" IN_LIST included_modules)
      message(WARNING "module ${CMAKE_CURRENT_LIST_FILE} processed more than once")
  endif()

  list(APPEND included_modules ${CMAKE_CURRENT_LIST_FILE})
endmacro()

include(cmake/custom.cmake)

message(STATUS "list of all included modules: ${included_modules}")
```

这段代码定义了一个自定义的"包含保护"机制，包括一个自定义模块(与前一个示例中的模块相同)，并打印所有包含模块的列表。对于CMake 3.10或更高版本有内置的`include_guard`。但是，不能简单地删除`custom_include_guard`和`${included_modules}`，而是使用一个“废弃”警告来弃用宏和变量。某个时候，可以将该警告转换为`FATAL_ERROR`，使代码停止配置，并迫使开发人员对代码进行修改，切换到内置命令。

## 具体实施

“废弃”函数、宏和变量的方法如下:

1. 首先，定义一个函数，我们将使用它来弃用一个变量:

   ```
   function(deprecate_variable _variable _access)
     if(_access STREQUAL "READ_ACCESS")
         message(DEPRECATION "variable ${_variable} is deprecated")
     endif()
   endfunction()
   ```
2. 然后，如果CMake的版本大于3.9，我们重新定义`custom_include_guard`并将`variable_watch`附加到`included_modules`中:

   ```
   if (CMAKE_VERSION VERSION_GREATER "3.9")
     # deprecate custom_include_guard
     macro(custom_include_guard)
       message(DEPRECATION "custom_include_guard is deprecated - use built-in include_guard instead")
       _custom_include_guard(${ARGV})
     endmacro()

     # deprecate variable included_modules
     variable_watch(included_modules deprecate_variable)
   endif()
   ```
3. CMake3.10以下版本的项目会产生以下结果:

   ```
   $ mkdir -p build
   $ cd build
   $ cmake ..

   -- custom.cmake is included and processed
   -- list of all included modules: /home/user/example/cmake/custom.cmake
   ```
4. CMake 3.10及以上将产生预期的“废弃”警告:

   ```
   CMake Deprecation Warning at CMakeLists.txt:26 (message):
   custom_include_guard is deprecated - use built-in include_guard instead
   Call Stack (most recent call first):
   cmake/custom.cmake:1 (custom_include_guard)
   CMakeLists.txt:34 (include)
   -- custom.cmake is included and processed
   CMake Deprecation Warning at CMakeLists.txt:19 (message):
   variable included_modules is deprecated
   Call Stack (most recent call first):
   CMakeLists.txt:9999 (deprecate_variable)
   CMakeLists.txt:36 (message)
   -- list of all included modules: /home/user/example/cmake/custom.cmake
   ```

## 工作原理

弃用函数或宏相当于重新定义它，如前面的示例所示，并使用`DEPRECATION`打印消息:

```
macro(somemacro)
  message(DEPRECATION "somemacro is deprecated")
  _somemacro(${ARGV})
endmacro()
```

可以通过定义以下变量来实现对变量的弃用:

```
function(deprecate_variable _variable _access)
  if(_access STREQUAL "READ_ACCESS")
      message(DEPRECATION "variable ${_variable} is deprecated")
  endif()
endfunction()
```

然后，这个函数被添加到将要“废弃”的变量上:

```
variable_watch(somevariable deprecate_variable)
```

如果在本例中`${included_modules}`是读取 (`READ_ACCESS`)，那么`deprecate_variable`函数将发出带有`DEPRECATION`的消息。
