Skip to content
This repository has been archived by the owner on Jan 29, 2021. It is now read-only.

Commit

Permalink
update chapter 5
Browse files Browse the repository at this point in the history
  • Loading branch information
xiaoweiChen committed Oct 4, 2019
1 parent c08c94e commit d92d9ae
Show file tree
Hide file tree
Showing 8 changed files with 44 additions and 42 deletions.
8 changes: 4 additions & 4 deletions content/chapter5/5.0-chinese.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# 第5章 配置时和构建时的操作

本章中,我们将介绍以下内容
本章的主要内容有

* 使用平台无关的文件操作
* 配置时运行自定义命令
Expand Down Expand Up @@ -29,6 +29,6 @@

本章会介绍在配置和构建时的自定义行为,我们将学习如何使用这些命令:

* execute_process,从CMake中执行任意进程,并检索它们的输出。
* add_custom_target,创建执行自定义命令的目标。
* add_custom_command,指定必须执行的命令,以生成文件或在其他目标的特定生成事件中生成。
* **execute_process**,从CMake中执行任意进程,并检索它们的输出。
* **add_custom_target**,创建执行自定义命令的目标。
* **add_custom_command**,指定必须执行的命令,以生成文件或在其他目标的特定生成事件中生成。
8 changes: 4 additions & 4 deletions content/chapter5/5.1-chinese.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,13 @@
)
```

3. 我们为源文件添加了一个可执行目标:
3. 为源文件添加了一个可执行目标:

```cmake
add_executable(linear-algebra linear-algebra.cpp)
```

4. 由于源文件的编译依赖于Eigen头文件,我们需要显式地指定可执行目标对自定义目标的依赖关系:
4. 由于源文件的编译依赖于Eigen头文件,需要显式地指定可执行目标对自定义目标的依赖关系:

```cmake
add_dependencies(linear-algebra unpack-eigen)
Expand All @@ -63,7 +63,7 @@

## 工作原理

让我们细看` add_custom_target `这个命令:
细看` add_custom_target `这个命令:

```cmake
add_custom_target(unpack-eigen
Expand All @@ -87,7 +87,7 @@ add_custom_target(unpack-eigen
2. ${CMAKE_COMMAND} -E rename eigen-eigen-5a0156e40feb eigen-3.3.4
```

注意,使用`-E`标志调用CMake命令本身来执行实际的工作。对于许多常见操作,CMake实现了一个对所有操作系统都通用的接口,这使得构建系统独立于特定的平台。`add_custom_target`命令中的下一个参数是工作目录。我们的示例中,它对应于构建目录:`CMAKE_CURRENT_BINARY_DIR`。最后一个参数`COMMENT`,用于指定CMake在执行自定义目标时输出什么样的消息。
注意,使用`-E`标志调用CMake命令本身来执行实际的工作。对于许多常见操作,CMake实现了一个对所有操作系统都通用的接口,这使得构建系统独立于特定的平台。`add_custom_target`命令中的下一个参数是工作目录。我们的示例中,它对应于构建目录`CMAKE_CURRENT_BINARY_DIR`。最后一个参数`COMMENT`,用于指定CMake在执行自定义目标时输出什么样的消息。

## 更多信息

Expand Down
14 changes: 7 additions & 7 deletions content/chapter5/5.3-chinese.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@

## 具体实施

CMakeLists.txt必须包含一个自定义命令,来提取线性代数包装器库的源代码:
`CMakeLists.txt`必须包含一个自定义命令,来提取线性代数包装器库的源代码:

1. 从的最低CMake版本、项目名称和支持语言的定义开始:
1. 从CMake最低版本、项目名称和支持语言的定义开始:

```cmake
cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
Expand All @@ -42,7 +42,7 @@ CMakeLists.txt必须包含一个自定义命令,来提取线性代数包装器
find_package(LAPACK REQUIRED)
```

4. 我们声明一个变量`wrap_BLAS_LAPACK_sources`来保存`wrap_BLAS_LAPACK.tar.gz`压缩包文件的名称:
4. 声明一个变量`wrap_BLAS_LAPACK_sources`来保存`wrap_BLAS_LAPACK.tar.gz`压缩包文件的名称:

```cmake
set(wrap_BLAS_LAPACK_sources
Expand All @@ -53,7 +53,7 @@ CMakeLists.txt必须包含一个自定义命令,来提取线性代数包装器
)
```

5. 我们声明自定义命令来提取`wrap_BLAS_LAPACK.tar.gz`压缩包,并更新提取文件的时间戳。注意这个`wrap_BLAS_LAPACK_sources`变量的预期输出:
5. 声明自定义命令来提取`wrap_BLAS_LAPACK.tar.gz`压缩包,并更新提取文件的时间戳。注意这个`wrap_BLAS_LAPACK_sources`变量的预期输出:

```cmake
add_custom_command(
Expand Down Expand Up @@ -146,9 +146,9 @@ add_custom_command(
)
```

`add_custom_command`向目标添加规则,并通过执行命令生成输出。`add_custom_command`中声明的任何目标,即在相同的CMakeLists.txt中声明的任何目标,使用输出的任何文件作为源文件的目标,在构建时会有规则生成这些文件。因此,源文件生成在构建时,目标和自定义命令在构建系统生成时,将自动处理依赖关系。
`add_custom_command`向目标添加规则,并通过执行命令生成输出。`add_custom_command`中声明的任何目标,即在相同的`CMakeLists.txt`中声明的任何目标,使用输出的任何文件作为源文件的目标,在构建时会有规则生成这些文件。因此,源文件生成在构建时,目标和自定义命令在构建系统生成时,将自动处理依赖关系。

我们的例子中,输出是压缩tar包,其中包含有源文件。要检测和使用这些文件,必须在构建时提取打包文件。通过使用带有`-E`标志的CMake命令,以实现平台独立性。下一个命令会更新提取文件的时间戳。这样做是为了确保没有处理陈旧文件。`WORKING_DIRECTORY`可以指定在何处执行命令。示例中,`CMAKE_CURRENT_BINARY_DIR`是当前正在处理的构建目录。`DEPENDS`参数列出了自定义命令的依赖项。例子中,压缩的tar是一个依赖项。CMake使用`COMMENT`字段在构建时打印状态消息。最后,`VERBATIM`告诉CMake为生成器和平台生成正确的命令,从而确保完全独立。
我们的例子中,输出是压缩`tar`,其中包含有源文件。要检测和使用这些文件,必须在构建时提取打包文件。通过使用带有`-E`标志的CMake命令,以实现平台独立性。下一个命令会更新提取文件的时间戳。这样做是为了确保没有处理陈旧文件。`WORKING_DIRECTORY`可以指定在何处执行命令。示例中,`CMAKE_CURRENT_BINARY_DIR`是当前正在处理的构建目录。`DEPENDS`参数列出了自定义命令的依赖项。例子中,压缩的`tar`是一个依赖项。CMake使用`COMMENT`字段在构建时打印状态消息。最后,`VERBATIM`告诉CMake为生成器和平台生成正确的命令,从而确保完全独立。

我们来仔细看看这用使用方式和打包库的创建:

Expand Down Expand Up @@ -179,7 +179,7 @@ target_link_libraries(math

`add_custom_command`有两个限制:

* 只有在相同的CMakeLists.txt中,指定了所有依赖于其输出的目标时才有效。
* 只有在相同的`CMakeLists.txt`,指定了所有依赖于其输出的目标时才有效。
* 对于不同的独立目标,使用`add_custom_command`的输出可以重新执行定制命令。这可能会导致冲突,应该避免这种情况的发生。

第二个限制,可以使用`add_dependencies`来避免。不过,规避这两个限制的正确方法是使用`add_custom_target`命令,我们将在下一节的示例中详细介绍。
20 changes: 11 additions & 9 deletions content/chapter5/5.4-chinese.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,36 +6,38 @@

## 准备工作

我们将重用前一节示例,对源码进行简单的修改。特别是,将把压缩后的tar打包文件放在名为deps的子目录中,而不是存储在顶级目录中。这个子目录包含它自己的CMakeLists.txt,它将由主CMakeLists.txt所调用
我们将重用前一节示例,对源码进行简单的修改。特别是,将把压缩后的`tar`打包文件放在名为`deps`的子目录中,而不是存储在主目录中。这个子目录包含它自己的`CMakeLists.txt`,将由主`CMakeLists.txt`调用

## 具体实施

我们将从主CMakeLists.txt开始,然讨论到deps/CMakeLists.txt:
我们将从主`CMakeLists.txt`开始,然后讨论`deps/CMakeLists.txt`:

1. 声明启用C++11:

```cmake
cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
project(recipe-04 LANGUAGES CXX Fortran)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
```

2. 现在,继续讨论deps/CMakeLists.txt。这通过`add_subdirectory`命令实现:
2. 现在,继续讨论`deps/CMakeLists.txt`。这通过`add_subdirectory`命令实现:

```cmake
add_subdirectory(deps)
```

3. deps/CMakeLists.txt中,我们首先定位必要的库(BLAS和LAPACK):
3. `deps/CMakeLists.txt`,我们首先定位必要的库(BLAS和LAPACK):

```cmake
find_package(BLAS REQUIRED)
find_package(LAPACK REQUIRED)
```

4. 然后,我们将tar包的内容汇集到一个变量`MATH_SRCS`中:
4. 然后,我们将`tar`包的内容汇集到一个变量`MATH_SRCS`中:

```cmake
set(MATH_SRCS
Expand All @@ -46,7 +48,7 @@
)
```

5. 列出要打包的源之后,我们定义一个目标和一个命令。这个组合用于提取`${CMAKE_CURRENT_BINARY_DIR}`中的包。但是,这里我们在一个不同的范围内,引用deps/CMakeLists.txt,因此tar包将存放在到主项目构建目录下的`deps`子目录中:
5. 列出要打包的源之后,定义一个目标和一个命令。这个组合用于提取`${CMAKE_CURRENT_BINARY_DIR}`中的包。但是,这里我们在一个不同的范围内,引用`deps/CMakeLists.txt`,因此`tar`包将存放在到主项目构建目录下的`deps`子目录中:

```cmake
add_custom_target(BLAS_LAPACK_wrappers
Expand Down Expand Up @@ -95,7 +97,7 @@
)
```

7. 执行完deps/CMakeLists.txt中的命令,返回到父范围,定义可执行目标,并将其链接到另一个目录的数学库:
7. 执行完`deps/CMakeLists.txt`中的命令,返回到父范围,定义可执行目标,并将其链接到另一个目录的数学库:

```cmake
add_executable(linear-algebra linear-algebra.cpp)
Expand All @@ -108,9 +110,9 @@

## 工作原理

用户可以使用`add_custom_target`,在目标中执行定制命令。这与我们前面讨论的`add_custom_command`略有不同。`add_custom_target`添加的目标没有输出,因此总会执行。因此,可以在子目录中引入自定义目标,并且仍然能够在顶级CMakeLists.txt中引用它
用户可以使用`add_custom_target`,在目标中执行定制命令。这与我们前面讨论的`add_custom_command`略有不同。`add_custom_target`添加的目标没有输出,因此总会执行。因此,可以在子目录中引入自定义目标,并且仍然能够在主`CMakeLists.txt`中引用它

本例中,使用`add_custom_target``add_custom_command`提取了源文件的包。这些源文件稍后用于编译另一个库,我们设法在另一个(父)目录范围内链接这个库。构建CMakeLists.txt文件的过程中,我们简要地说明了tar包是在deps下提取的,deps是项目构建目录下的一个子目录。这是因为在CMake中,构建树的结构与源树的层次结构相同。
本例中,使用`add_custom_target``add_custom_command`提取了源文件的包。这些源文件稍后用于编译另一个库,我们设法在另一个(父)目录范围内链接这个库。构建`CMakeLists.txt`文件的过程中,我们简要地说明了`tar`包是在`deps`下提取的,deps是项目构建目录下的一个子目录。这是因为在CMake中,构建树的结构与源树的层次结构相同。

这个示例中有一个值得注意的细节,我们应该讨论一下,那就是我们把数学库的源标记为`PRIVATE`:

Expand Down
14 changes: 7 additions & 7 deletions content/chapter5/5.5-chinese.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

## 准备工作

本示例中,我们将使用Fortran代码(example.f90):
本示例中,我们将使用Fortran代码(`example.f90`):

```fortran
program example
Expand Down Expand Up @@ -72,7 +72,7 @@ except FileNotFoundError:

## 具体实施

来看看CMakeLists.txt:
来看看`CMakeLists.txt`

1. 首先声明一个Fortran项目:

Expand Down Expand Up @@ -106,7 +106,7 @@ except FileNotFoundError:
)
```

5. 然后,定义一个自定义命令,在example目标在已链接之前,打印链接行:
5. 然后,定义一个自定义命令,`example`目标在已链接之前,打印链接行:

```cmake
add_custom_command(
Expand Down Expand Up @@ -143,11 +143,11 @@ except FileNotFoundError:

## 工作原理

一旦声明了库或可执行目标,就可以使用`add_custom_command`将其他命令锁定到目标上。这些命令将在特定的时间执行,与它们所附加的目标的执行相关联。CMake通过以下选项,定制命令执行顺序:
当声明了库或可执行目标,就可以使用`add_custom_command`将其他命令锁定到目标上。这些命令将在特定的时间执行,与它们所附加的目标的执行相关联。CMake通过以下选项,定制命令执行顺序:

* PRE_BUILD:在执行与目标相关的任何其他规则之前执行的命令。但能在Visual Studio 7或更高版本进行。
* PRE_LINK:使用此选项,命令在编译目标之后,调用链接器或归档器之前执行。Visual Studio 7或更高版本之外的生成器中使用`PRE_BUILD`将被解释为`PRE_LINK`
* POST_BUILD:如前所述,这些命令将在执行给定目标的所有规则之后运行。
* **PRE_BUILD**:在执行与目标相关的任何其他规则之前执行的命令。但能在Visual Studio 7或更高版本进行。
* **PRE_LINK**:使用此选项,命令在编译目标之后,调用链接器或归档器之前执行。Visual Studio 7或更高版本之外的生成器中使用`PRE_BUILD`将被解释为`PRE_LINK`
* **POST_BUILD**:如前所述,这些命令将在执行给定目标的所有规则之后运行。

本例中,将两个自定义命令绑定到可执行目标。`PRE_LINK`命令将`${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/example.dir/link.txt`的内容打印到屏幕上。文件包含链接命令,在我们的例子中,链接行是这样的:

Expand Down
12 changes: 6 additions & 6 deletions content/chapter5/5.6-chinese.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@

## 工作原理

`try_compile``check_cxx_source_compiles`都将编译源文件,并将其链接到可执行文件中。如果这些操作成功,那么输出变量`omp_task_loop_test_1`(前者)和`omp_task_loop_test_2`(后者)将被设置为`TRUE`。然而,这两个命令实现的方式略有不同。`check_<lang>_source_compiles`命令是`try_compile`命令的简化包装。因此,它提供了一个最小接口:
`try_compile``check_cxx_source_compiles`都将编译源文件,并将其链接到可执行文件中。如果这些操作成功,那么输出变量`omp_task_loop_test_1`(前者)和`omp_task_loop_test_2`(后者)将被设置为`TRUE`。然而,这两个命令实现的方式略有不同。`check_<lang>_source_compiles`命令是`try_compile`命令的简化包装。因此,它提供了一个接口:

1. 要编译的代码片段必须作为CMake变量传入。大多数情况下,这意味着必须使用`file(READ ...)`来读取文件。然后,代码片段被保存到构建目录的`CMakeFiles/CMakeTmp`子目录中。
2. 微调编译和链接,必须通过设置以下CMake变量进行:
Expand All @@ -129,22 +129,22 @@

**TIPS**:*Fortran下,CMake代码的格式通常是固定的,但也有意外情况。为了处理这些意外,需要为`check_fortran_source_compiles`设置`-ffree-form`编译标志。可以通过`set(CMAKE_REQUIRED_FLAGS “-ffree-form")`实现。*

这个最小接口反映了:测试编译是通过,在CMake调用中直接生成和执行构建和连接命令来执行的。
这个接口反映了:测试编译是通过,在CMake调用中直接生成和执行构建和连接命令来执行的。

命令`try_compile`提供了更完整的接口和两种不同的操作模式:

1. 以一个完整的CMake项目作为输入,并基于它的CMakeLists.txt配置、构建和链接。这种操作模式提供了更好的灵活性,因为要编译项目的复杂度是可以选择的。
1. 以一个完整的CMake项目作为输入,并基于它的`CMakeLists.txt`配置、构建和链接。这种操作模式提供了更好的灵活性,因为要编译项目的复杂度是可以选择的。
2. 提供了源文件,和用于包含目录、链接库和编译器标志的配置选项。

因此,`try_compile`基于在项目上调用CMake,其中CMakeLists.txt已经存在(在第一种操作模式中),或者基于传递给`try_compile`的参数动态生成文件。
因此,`try_compile`基于在项目上调用CMake,其中`CMakeLists.txt`已经存在(在第一种操作模式中),或者基于传递给`try_compile`的参数动态生成文件。

## 更多信息

本示例中概述的类型检查并不总是万无一失的,并且可能产生假阳性和假阴性。作为一个例子,您可以尝试注释掉包含`CMAKE_REQUIRED_LIBRARIES`的行。运行这个例子仍然会报告“成功”,这是因为编译器将忽略OpenMP的`pragma`字段。
本示例中概述的类型检查并不总是万无一失的,并且可能产生假阳性和假阴性。作为一个例子,可以尝试注释掉包含`CMAKE_REQUIRED_LIBRARIES`的行。运行这个例子仍然会报告“成功”,这是因为编译器将忽略OpenMP的`pragma`字段。

当返回了错误的结果时,应该怎么做?构建目录的`CMakeFiles`子目录中的`CMakeOutput.log``CMakeError.log`文件会提供一些线索。它们记录了CMake运行的操作的标准输出和标准错误。如果怀疑有假阳性,应该通过搜索保存编译检查结果的变量集来检查前者。如果你怀疑是假阴性,你应该检查后者。

调试`try_compile`需要一些注意事项。即使检查不成功,CMake也会删除由该命令生成的所有文件。幸运的是,`debug-trycompile`将阻止CMake进行删除。如果你的代码中有多个`try_compile`调用,你一次只能调试一个:
调试`try_compile`需要一些注意事项。即使检查不成功,CMake也会删除由该命令生成的所有文件。幸运的是,`debug-trycompile`将阻止CMake进行删除。如果你的代码中有多个`try_compile`调用,一次只能调试一个:

1. 运行CMake,不使用`--debug-trycompile`,将运行所有`try_compile`命令,并清理它们的执行目录和文件。

Expand Down
2 changes: 1 addition & 1 deletion content/chapter5/5.8-chinese.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

本示例的代码示例是复用第3章第9节的配置,并进行微小的改动。之前,我们展示了如何在您的系统上找到ZeroMQ库并将其链接到一个C程序中。本示例中,在生成实际的C++程序之前,我们将检查一个使用GNU/Linux上的系统UUID库的小型C程序是否能够实际运行。

## 如何实施
## 具体实施

开始构建C++项目之前,我们希望检查GNU/Linux上的UUID系统库是否可以被链接。这可以通过以下一系列步骤来实现:

Expand Down

0 comments on commit d92d9ae

Please sign in to comment.