# 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`的消息。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://chenxiaowei.gitbook.io/cmake-cookbook/7.0-chinese/7.6-chinese.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
