From 7152d92ea2fa251d6732f5401ddd37276f6e12b6 Mon Sep 17 00:00:00 2001 From: xiaowei Date: Sat, 19 Oct 2019 20:21:33 +0800 Subject: [PATCH] update chapter 7 --- SUMMARY.md | 2 +- content/chapter7/7.0-chinese.md | 2 +- content/chapter7/7.1-chinese.md | 22 +++++----- content/chapter7/7.2-chinese.md | 14 +++---- content/chapter7/7.3-chinese.md | 6 +-- content/chapter7/7.4-chinese.md | 28 ++++++------- content/chapter7/7.5-chinese.md | 10 ++--- content/chapter7/7.6-chinese.md | 12 +++--- content/chapter7/7.7-chinese.md | 72 ++++++++++++++++----------------- content/chapter7/7.8-chinese.md | 12 +++--- content/chapter7/7.9-chinese.md | 64 ++++++++++++++--------------- 11 files changed, 119 insertions(+), 125 deletions(-) diff --git a/SUMMARY.md b/SUMMARY.md index b11f524..17c4da9 100644 --- a/SUMMARY.md +++ b/SUMMARY.md @@ -72,7 +72,7 @@ * [7.3 编写函数来测试和设置编译器标志](content/chapter7/7.3-chinese.md) * [7.4 用指定参数定义函数或宏](content/chapter7/7.4-chinese.md) * [7.5 重新定义函数和宏](content/chapter7/7.5-chinese.md) - * [7.6 废弃使用函数、宏和变量](content/chapter7/7.6-chinese.md) + * [7.6 使用废弃函数、宏和变量](content/chapter7/7.6-chinese.md) * [7.7 add_subdirectory的限定范围](content/chapter7/7.7-chinese.md) * [7.8 使用target_sources避免全局变量](content/chapter7/7.8-chinese.md) * [7.9 组织Fortran项目](content/chapter7/7.9-chinese.md) diff --git a/content/chapter7/7.0-chinese.md b/content/chapter7/7.0-chinese.md index f3155a5..8d1e707 100644 --- a/content/chapter7/7.0-chinese.md +++ b/content/chapter7/7.0-chinese.md @@ -7,7 +7,7 @@ * 编写函数来测试和设置编译器标志 * 用指定参数定义函数或宏 * 重新定义函数和宏 -* 废弃使用函数、宏和变量 +* 使用废弃函数、宏和变量 * add_subdirectory的限定范围 * 使用target_sources避免全局变量 * 组织Fortran项目 diff --git a/content/chapter7/7.1-chinese.md b/content/chapter7/7.1-chinese.md index 2bc99f9..d238224 100644 --- a/content/chapter7/7.1-chinese.md +++ b/content/chapter7/7.1-chinese.md @@ -12,10 +12,10 @@ . ├── CMakeLists.txt ├── src -│ ├── CMakeLists.txt -│ ├── main.cpp -│ ├── sum_integers.cpp -│ └── sum_integers.hpp +│ ├── CMakeLists.txt +│ ├── main.cpp +│ ├── sum_integers.cpp +│ └── sum_integers.hpp └── tests ├── catch.hpp ├── CMakeLists.txt @@ -24,7 +24,7 @@ ## 具体实施 -1. 定义了最低CMake版本、项目名称和支持的语言,并要求支持C++11标准: +1. 定义了CMake最低版本、项目名称和支持的语言,并要求支持C++11标准: ```cmake cmake_minimum_required(VERSION 3.5 FATAL_ERROR) @@ -34,7 +34,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) ``` -2. 根据GNU标准定义binary和library路径: +2. 根据GNU标准定义`binary`和`library`路径: ```cmake include(GNUInstallDirs) @@ -71,7 +71,7 @@ target_link_libraries(cpp_test sum_integers) ``` -6. 然后,定义一个新宏`add_catch_test`,我们将在稍后讨论: +6. 定义一个新宏`add_catch_test`: ```cmake macro(add_catch_test _name _cost) @@ -102,7 +102,7 @@ endmacro() ``` -7. 最后,我们使用`add_catch_test`定义了两个测试。此外,还设置和打印了一个变量的值: +7. 最后,使用`add_catch_test`定义了两个测试。此外,还设置和打印了变量的值: ```cmake set(num_macro_calls 0) @@ -111,7 +111,7 @@ message(STATUS "in total there were ${num_macro_calls} calls to add_catch_test") ``` -8. 现在,进行测试。我们首先配置项目(输出行如下所示): +8. 现在,进行测试。配置项目(输出行如下所示): ```cmake $ mkdir -p build @@ -126,7 +126,7 @@ -- ... ``` -9. 最后,我们构建并运行测试: +9. 最后,构建并运行测试: ```shell $ cmake --build . @@ -217,4 +217,4 @@ math(EXPR num_macro_calls "${num_macro_calls} + 1") set(CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE ON) ``` -这个命令会将当前目录,添加到CMakeLists.txt中定义的所有目标的`interface_include_directory`属性中。换句话说,我们不需要使用`target_include_directory`来添加`cpp_test`所需头文件的位置。 \ No newline at end of file +这个命令会将当前目录,添加到`CMakeLists.txt`中定义的所有目标的`interface_include_directory`属性中。换句话说,我们不需要使用`target_include_directory`来添加`cpp_test`所需头文件的位置。 \ No newline at end of file diff --git a/content/chapter7/7.2-chinese.md b/content/chapter7/7.2-chinese.md index e5e0de4..b9e5fae 100644 --- a/content/chapter7/7.2-chinese.md +++ b/content/chapter7/7.2-chinese.md @@ -2,9 +2,9 @@ **NOTE**:*此示例代码可以在 https://github.com/dev-cafe/cmake-cookbook/tree/v1.0/chapter-7/recipe-02 中找到。该示例在CMake 3.5版(或更高版本)中是有效的,并且已经在GNU/Linux、macOS和Windows上进行过测试。* -项目通常从单个CMakeLists.txt文件开始,随着时间的推移,这个文件会逐渐增长。在本示例中,我们将演示一种将CMakeLists.txt分割成更小单元的机制。将CMakeLists.txt拆分为模块有几个动机,这些模块可以包含在主CMakeLists.txt或其他模块中: +项目通常从单个`CMakeLists.txt`文件开始,随着时间的推移,这个文件会逐渐增长。本示例中,我们将演示一种将`CMakeLists.txt`分割成更小单元的机制。将`CMakeLists.txt`拆分为模块有几个动机,这些模块可以包含在主`CMakeLists.txt`或其他模块中: -* 主CMakeLists.txt更易于阅读。 +* 主`CMakeLists.txt`更易于阅读。 * CMake模块可以在其他项目中重用。 * 与函数相结合,模块可以帮助我们限制变量的作用范围。 @@ -12,12 +12,12 @@ ## 准备工作 -本例中,我们将使用两个文件,主CMakeLists.txt和`cmake/colors.cmake`: +本例中,我们将使用两个文件,主`CMakeLists.txt`和`cmake/colors.cmake`: ```shell . ├── cmake -│ └── colors.cmake +│ └── colors.cmake └── CMakeLists.txt ``` @@ -102,7 +102,7 @@ endmacro() message(STATUS "${BoldMagenta}This is bold${ColourReset}") ``` -5. 测试一下(如果使用macOS或Linux,以下的输出应该出现屏幕上): +5. 测试一下(如果使用macOS或Linux,以下的输出应该出现屏幕上): ## 工作原理 @@ -127,7 +127,7 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") `include(colors)`命令指示CMake搜索`${CMAKE_MODULE_PATH}`,查找名称为`colors.cmake`的模块。 -例子中,我们没有以下的方式进行: +例子中,我们没有按以下的方式进行: ```cmake list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") @@ -142,4 +142,4 @@ include(cmake/colors.cmake) ## 更多信息 -推荐的做法是在模块中定义宏或函数,然后调用宏或函数。将包含模块用作函数调用不是很好的方式。除了定义函数和宏以及查找程序、库和路径之外,包含模块不应该做更多的事情。实际的`include`命令不应该定义或修改变量,其原因是重复的`include`(可能是偶然的)不应该引入任何不想要的副作用。在第5节中,我们将创建一个防止意外包含的保护机制。 \ No newline at end of file +推荐的做法是在模块中定义宏或函数,然后调用宏或函数。将包含模块用作函数调用不是很好的方式。除了定义函数和宏以及查找程序、库和路径之外,包含模块不应该做更多的事情。实际的`include`命令不应该定义或修改变量,其原因是重复的`include`(可能是偶然的)不应该引入任何不想要的副作用。在第5节中,我们将创建一个防止多次包含的保护机制。 \ No newline at end of file diff --git a/content/chapter7/7.3-chinese.md b/content/chapter7/7.3-chinese.md index f8cb673..1327099 100644 --- a/content/chapter7/7.3-chinese.md +++ b/content/chapter7/7.3-chinese.md @@ -68,13 +68,13 @@ endfunction() project(recipe-03 LANGUAGES C CXX) ``` -2. 然后,显示包含`set_compiler_flag.cmake`: +2. 显示包含`set_compiler_flag.cmake`: ```cmake include(set_compiler_flag.cmake) ``` -3. 然后,测试C标志列表: +3. 测试C标志列表: ```cmake set_compiler_flag( @@ -137,7 +137,7 @@ endfunction() 2. 包含模块 3. 调用函数或宏 -从输出中,可以看到代码检查列表中的每个标志,一旦检查成功,它就打印成功的编译标志。看看`set_compiler_flag.cmake`模块的内部,这个模块又包含三个模块: +从输出中,可以看到代码检查列表中的每个标志。一旦检查成功,它就打印成功的编译标志。看看`set_compiler_flag.cmake`模块的内部,这个模块又包含三个模块: ```cmake include(CheckCCompilerFlag) diff --git a/content/chapter7/7.4-chinese.md b/content/chapter7/7.4-chinese.md index 65aacdb..9b44139 100644 --- a/content/chapter7/7.4-chinese.md +++ b/content/chapter7/7.4-chinese.md @@ -2,7 +2,7 @@ **NOTE**:*此示例代码可以在 https://github.com/dev-cafe/cmake-cookbook/tree/v1.0/chapter-7/recipe-04 中找到,其中包含一个C++示例。该示例在CMake 3.5版(或更高版本)中是有效的,并且已经在GNU/Linux、macOS和Windows上进行过测试。* -前面的示例中,我们研究了函数和宏,并使用了位置参数。这个示例中,我们将定义一个带有命名参数的函数。我们将复用第1节中的示例,使用函数和宏重用代码,而不是使用以下代码定义测试:`add_catch_test`(short 1.5)。 +前面的示例中,我们研究了函数和宏,并使用了位置参数。这个示例中,我们将定义一个带有命名参数的函数。我们将复用第1节中的示例,使用函数和宏重用代码,而不是使用以下代码定义测试:`add_catch_test(short 1.5)`。 我们将这样调用函数: @@ -25,24 +25,24 @@ add_catch_test( ```shell . ├── cmake -│ └── testing.cmake +│ └── testing.cmake ├── CMakeLists.txt ├── src -│ ├── CMakeLists.txt -│ ├── main.cpp -│ ├── sum_integers.cpp -│ └── sum_integers.hpp +│ ├── CMakeLists.txt +│ ├── main.cpp +│ ├── sum_integers.cpp +│ └── sum_integers.hpp └── tests -├── catch.hpp -├── CMakeLists.txt -└── test.cpp + ├── catch.hpp + ├── CMakeLists.txt + └── test.cpp ``` ## 具体实施 我们对CMake代码进行一些修改,如下所示: -1. CMakeLists.txt顶部中只增加了一行,因为我们将包括位于`cmake`下面的模块: +1. `CMakeLists.txt`顶部中只增加了一行,因为我们将包括位于`cmake`下面的模块: ```cmake list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") @@ -50,7 +50,7 @@ add_catch_test( 2. 保持`src/CMakeLists.txt`。 -3. 在`tests/CMakeLists.txt`中,我们将`add_catch_test`函数定义移动到`cmake/testing.cmake`,并且定义两个测试: +3. `tests/CMakeLists.txt`中,将`add_catch_test`函数定义移动到`cmake/testing.cmake`,并且定义两个测试: ```cmake add_executable(cpp_test test.cpp) @@ -79,7 +79,7 @@ add_catch_test( ) ``` -4. `add_catch_test`函数在`cmake/testing.cmake`中定义: +4. `add_catch_test`在`cmake/testing.cmake`中定义: ```cmake function(add_catch_test) @@ -169,7 +169,7 @@ add_catch_test( ## 工作原理 -示例的特点是其命名参数,因此我们可以将重点放在`cmake/testing.cmake`模块上。CMake提供`cmake_parse_arguments`命令,我们使用函数名(`add_catch_test`)选项(我们的例子中是none)、单值参数(`NAME`和`COST`)和多值参数(`LABELS`、`DEPENDS`和`REFERENCE_FILES`)调用该命令: +示例的特点是其命名参数,因此我们可以将重点放在`cmake/testing.cmake`模块上。CMake提供`cmake_parse_arguments`命令,我们使用函数名(`add_catch_test`)选项(我们的例子中是`none`)、单值参数(`NAME`和`COST`)和多值参数(`LABELS`、`DEPENDS`和`REFERENCE_FILES`)调用该命令: ```cmake function(add_catch_test) @@ -194,7 +194,7 @@ endfunction() * add_catch_test_DEPENDS * add_catch_test_REFERENCE_FILES -我们可以查询,并在函数中使用这些变量。这种方法使我们有机会用更健壮的接口和更具有可读的函数/宏调用,来实现函数和宏。 +可以查询,并在函数中使用这些变量。这种方法使我们有机会用更健壮的接口和更具有可读的函数/宏调用,来实现函数和宏。 ## 更多信息 diff --git a/content/chapter7/7.5-chinese.md b/content/chapter7/7.5-chinese.md index f36a0a6..a574964 100644 --- a/content/chapter7/7.5-chinese.md +++ b/content/chapter7/7.5-chinese.md @@ -11,8 +11,8 @@ ```shell . ├── cmake -│ ├── custom.cmake -│ └── include_guard.cmake +│ ├── custom.cmake +│ └── include_guard.cmake └── CMakeLists.txt ``` @@ -29,14 +29,14 @@ message(STATUS "custom.cmake is included and processed") 我们对三个CMake文件的逐步分解: -1. 在这个示例中,我们不会编译任何代码,因此我们的语言要求是`NONE`: +1. 示例中,我们不会编译任何代码,因此我们的语言要求是`NONE`: ```cmake cmake_minimum_required(VERSION 3.5 FATAL_ERROR) project(recipe-05 LANGUAGES NONE) ``` -2. 然后,我们定义一个`include_guard`宏,将其放在一个单独的模块中: +2. 定义一个`include_guard`宏,将其放在一个单独的模块中: ```cmake # (re)defines include_guard @@ -143,7 +143,7 @@ endif() list(APPEND included_modules ${CMAKE_CURRENT_LIST_FILE}) ``` -如果第一次调用宏,则`included_modules`变量没有定义,因此我们将其设置为空列表。然后检查`${CMAKE_CURRENT_LIST_FILE}`是否是`included_modules`列表中的元素。如果是,则会发出警告。如果没有,我们将`${CMAKE_CURRENT_LIST_FILE}`追加到这个列表。CMake输出中,我们可以验证自定义模块的第二个包含确实会导致警告。 +如果第一次调用宏,则`included_modules`变量没有定义,因此我们将其设置为空列表。然后检查`${CMAKE_CURRENT_LIST_FILE}`是否是`included_modules`列表中的元素。如果是,则会发出警告;如果没有,我们将`${CMAKE_CURRENT_LIST_FILE}`追加到这个列表。CMake输出中,我们可以验证自定义模块的第二个包含确实会导致警告。 CMake 3.10及更高版本的情况有所不同;在这种情况下,存在一个内置的`include_guard`,我们用自己的宏接收到参数并调用它: diff --git a/content/chapter7/7.6-chinese.md b/content/chapter7/7.6-chinese.md index e449bb2..074d046 100644 --- a/content/chapter7/7.6-chinese.md +++ b/content/chapter7/7.6-chinese.md @@ -1,8 +1,8 @@ -# 7.6 废弃使用函数、宏和变量 +# 7.6 使用废弃函数、宏和变量 **NOTE**:*此示例代码可以在 https://github.com/dev-cafe/cmake-cookbook/tree/v1.0/chapter-7/recipe-06 中找到。该示例在CMake 3.5版(或更高版本)中是有效的,并且已经在GNU/Linux、macOS和Windows上进行过测试。* -弃用是在不断发展的项目开发过程中一种重要机制,它向开发人员发出信号,表明将来某个函数、宏或变量将被删除或替换。在一段时间内,函数、宏或变量将继续可访问,但会发出警告,最终可能会上升为错误。 +“废弃”是在不断发展的项目开发过程中一种重要机制,它向开发人员发出信号,表明将来某个函数、宏或变量将被删除或替换。在一段时间内,函数、宏或变量将继续可访问,但会发出警告,最终可能会上升为错误。 ## 准备工作 @@ -30,11 +30,11 @@ 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`,使代码停止配置,并迫使开发人员对代码进行修改,切换到内置命令。 +这段代码定义了一个自定义的"包含保护"机制,包括一个自定义模块(与前一个示例中的模块相同),并打印所有包含模块的列表。对于CMake 3.10或更高版本有内置的`include_guard`。但是,不能简单地删除`custom_include_guard`和`${included_modules}`,而是使用一个“废弃”警告来弃用宏和变量。某个时候,可以将该警告转换为`FATAL_ERROR`,使代码停止配置,并迫使开发人员对代码进行修改,切换到内置命令。 ## 具体实施 -弃用函数、宏和变量的方法如下: +“废弃”函数、宏和变量的方法如下: 1. 首先,定义一个函数,我们将使用它来弃用一个变量: @@ -72,7 +72,7 @@ message(STATUS "list of all included modules: ${included_modules}") -- list of all included modules: /home/user/example/cmake/custom.cmake ``` -4. CMake 3.10及以上将产生预期的弃用警告: +4. CMake 3.10及以上将产生预期的“废弃”警告: ```cmake CMake Deprecation Warning at CMakeLists.txt:26 (message): @@ -110,7 +110,7 @@ function(deprecate_variable _variable _access) endfunction() ``` -然后,这个函数被添加到将要废弃的变量上: +然后,这个函数被添加到将要“废弃”的变量上: ```cmake variable_watch(somevariable deprecate_variable) diff --git a/content/chapter7/7.7-chinese.md b/content/chapter7/7.7-chinese.md index bc16e29..bc21824 100644 --- a/content/chapter7/7.7-chinese.md +++ b/content/chapter7/7.7-chinese.md @@ -6,7 +6,7 @@ ## 准备工作 -由于我们希望展示和讨论如何构造一个复杂的项目,所以我们需要一个比“hello world”项目更复杂的例子: +由于我们希望展示和讨论如何构造一个复杂的项目,所以需要一个比“hello world”项目更复杂的例子: * https://en.wikipedia.org/wiki/Cellular_automaton#Elementary_cellular_automata * http://mathworld.wolfram.com/ElementaryCellularAutomaton.html @@ -21,33 +21,33 @@ . ├── CMakeLists.txt ├── external -│ ├── CMakeLists.txt -│ ├── conversion.cpp -│ ├── conversion.hpp -│ └── README.md +│ ├── CMakeLists.txt +│ ├── conversion.cpp +│ ├── conversion.hpp +│ └── README.md ├── src -│ ├── CMakeLists.txt -│ ├── evolution -│ │ ├── CMakeLists.txt -│ │ ├── evolution.cpp -│ │ └── evolution.hpp -│ ├── initial -│ │ ├── CMakeLists.txt -│ │ ├── initial.cpp -│ │ └── initial.hpp -│ ├── io -│ │ ├── CMakeLists.txt -│ │ ├── io.cpp -│ │ └── io.hpp -│ ├── main.cpp -│ └── parser -│ ├── CMakeLists.txt -│ ├── parser.cpp -│ └── parser.hpp +│ ├── CMakeLists.txt +│ ├── evolution +│ │ ├── CMakeLists.txt +│ │ ├── evolution.cpp +│ │ └── evolution.hpp +│ ├── initial +│ │ ├── CMakeLists.txt +│ │ ├── initial.cpp +│ │ └── initial.hpp +│ ├── io +│ │ ├── CMakeLists.txt +│ │ ├── io.cpp +│ │ └── io.hpp +│ ├── main.cpp +│ └── parser +│ ├── CMakeLists.txt +│ ├── parser.cpp +│ └── parser.hpp └── tests - ├── catch.hpp - ├── CMakeLists.txt - └── test.cpp + ├── catch.hpp + ├── CMakeLists.txt + └── test.cpp ``` 我们将代码分成许多库来模拟真实的大中型项目,可以将源代码组织到库中,然后将库链接到可执行文件中。 @@ -209,13 +209,13 @@ TEST_CASE("Apply rule 222", "[rule-222]") { } ``` -相应的头文件包含函数声明。有人可能会说,对于这个小代码示例,项目包含了太多子目录,但请注意,这只是一个项目的简化示例,通常包含每个库的许多源文件,理想情况下,这些文件被放在到单独的目录中。 +相应的头文件包含函数声明。有人可能会说,对于这个小代码示例,项目包含了太多子目录。请注意,这只是一个项目的简化示例,通常包含每个库的许多源文件,理想情况下,这些文件被放在到单独的目录中。 ## 具体实施 让我们来详细解释一下CMake所需的功能: -1. CMakeLists.txt顶部非常类似于第1节,代码重用与函数和宏: +1. `CMakeLists.txt`顶部非常类似于第1节,代码重用与函数和宏: ```cmake cmake_minimum_required(VERSION 3.5 FATAL_ERROR) @@ -283,7 +283,7 @@ TEST_CASE("Apply rule 222", "[rule-222]") { ) ``` -4. `src/CMakeLists.txt`文件添加了更多的子目录,这些子目录又包含CMakeLists.txt文件。`src/evolution/CMakeLists.txt`包含以下内容: +4. `src/CMakeLists.txt`文件添加了更多的子目录,这些子目录又包含`CMakeLists.txt`文件。`src/evolution/CMakeLists.txt`包含以下内容: ```cmake add_library(evolution "") @@ -367,7 +367,7 @@ TEST_CASE("Apply rule 222", "[rule-222]") { ## 工作原理 -我们可以将所有代码放到一个源文件中。不过,这不切实际,因为每次编辑都需要重新编译。将源文件分割成更小、更易于管理的单元是有意义的。我们可以将所有源代码都编译成一个库或可执行文件。实际上,项目更喜欢将源代码编译分成更小的、定义良好的库。这样做既是为了本地化和简化依赖项,也是为了简化代码维护。这意味着如在这里所做的那样,由许多库构建一个项目是一种常见的情况。 +我们可以将所有代码放到一个源文件中。不过,每次编辑都需要重新编译。将源文件分割成更小、更易于管理的单元是有意义的。可以将所有源代码都编译成一个库或可执行文件。实际上,项目更喜欢将源代码编译分成更小的、定义良好的库。这样做既是为了本地化和简化依赖项,也是为了简化代码维护。这意味着如在这里所做的那样,由许多库构建一个项目是一种常见的情况。 为了讨论CMake结构,我们可以从定义每个库的单个CMakeLists.txt文件开始,自底向上进行,例如`src/evolution/CMakeLists.txt`: @@ -387,7 +387,7 @@ target_include_directories(evolution ) ``` -这些单独的CMakeLists.txt文件定义了库。本例中,我们首先使用`add_library`定义库名,然后定义它的源和包含目录,以及它们的目标可见性:实现文件(`evolution.cpp`:`PRIVATE`),而接口头文件是` evolution.hpp `被定义为`PUBLIC`,因为我们将在`main.cpp`和`test.cpp`中访问它。定义尽可能接近代码目标的好处是,对于该库的修改,只需要变更该目录中的文件即可;换句话说,也就是库依赖项被封装。 +这些单独的`CMakeLists.txt`文件定义了库。本例中,我们首先使用`add_library`定义库名,然后定义它的源和包含目录,以及它们的目标可见性:实现文件(`evolution.cpp`:`PRIVATE`),而接口头文件` evolution.hpp `定义为`PUBLIC`,因为我们将在`main.cpp`和`test.cpp`中访问它。定义尽可能接近代码目标的好处是,对于该库的修改,只需要变更该目录中的文件即可;换句话说,也就是库依赖项被封装。 向上移动一层,库在`src/CMakeLists.txt`中封装: @@ -409,11 +409,11 @@ target_link_libraries(automata ) ``` -文件在主CMakeLists.txt中被引用。这意味着我们已经使用CMakeLists.txt文件树,从构建了我们的项目。这种方法对于许多项目来说是可用的,并且它可以扩展到更大型的项目,而不需要在目录间的全局变量中包含源文件列表。`add_subdirectory`方法的另一个好处是它隔离了作用范围,因为子目录中定义的变量在父范围中不能访问。 +文件在主`CMakeLists.txt`中被引用。这意味着使用`CMakeLists.txt`文件,构建我们的项目。这种方法对于许多项目来说是可用的,并且它可以扩展到更大型的项目,而不需要在目录间的全局变量中包含源文件列表。`add_subdirectory`方法的另一个好处是它隔离了作用范围,因为子目录中定义的变量在父范围中不能访问。 ## 更多信息 -使用`add_subdirectory`调用树构建项目的一个限制是,CMake不允许将`target_link_libraries`与定义在当前目录范围之外的目标一起使用。对于本示例来说,这不是问题。在下一个示例中,我们将演示另一种方法,我们不使用`add_subdirectory`,而是使用`module include`来组装不同的CMakeLists.txt文件,它允许我们链接到当前目录之外定义的目标。 +使用`add_subdirectory`调用树构建项目的一个限制是,CMake不允许将`target_link_libraries`与定义在当前目录范围之外的目标一起使用。对于本示例来说,这不是问题。在下一个示例中,我们将演示另一种方法,我们不使用`add_subdirectory`,而是使用`module include`来组装不同的`CMakeLists.txt`文件,它允许我们链接到当前目录之外定义的目标。 CMake可以使用Graphviz图形可视化软件(http://www.graphviz.org )生成项目的依赖关系图: @@ -435,7 +435,7 @@ if(${PROJECT_SOURCE_DIR} STREQUAL ${PROJECT_BINARY_DIR}) endif() ``` -认识到构建树的结构模仿源树的结构是很有用的。示例中,将`message`打印输出插入到src/CMakeLists.txt中: +认识到构建结构与源结构类似很有用。示例中,将`message`打印输出插入到`src/CMakeLists.txt`中: ```cmake message("current binary dir is ${CMAKE_CURRENT_BINARY_DIR}") @@ -443,7 +443,7 @@ message("current binary dir is ${CMAKE_CURRENT_BINARY_DIR}") 在`build`下构建项目时,我们将看到`build/src`的打印输出。 -在CMake的3.12版本中,`OBJECT`库是组织大型项目的另一种可行方法。对我们的示例的惟一修改是在库的CMakeLists.txt中。源文件将被编译成目标文件:既不存档到静态库中,也不链接到动态库中。例如: +在CMake的3.12版本中,`OBJECT`库是组织大型项目的另一种可行方法。对我们的示例的惟一修改是在库的`CMakeLists.tx`t中。源文件将被编译成目标文件:既不存档到静态库中,也不链接到动态库中。例如: ```cmake add_library(io OBJECT "") @@ -461,4 +461,4 @@ target_include_directories(io ) ``` -主CMakeLists.txt保持不变:`automata`可执行目标将这些目标文件链接到最终的可执行文件。使用也有要求需求,例如:在对象库上设置的目录、编译标志和链接库,将被正确地继承。有关CMake 3.12中引入的对象库新特性的更多细节,请参考官方文档: https://cmake.org/cmake/help/v3.12/manual/cmake-buildsystem.7.html#object-libraries \ No newline at end of file +主`CMakeLists.txt`保持不变:`automata`可执行目标将这些目标文件链接到最终的可执行文件。使用也有要求需求,例如:在对象库上设置的目录、编译标志和链接库,将被正确地继承。有关CMake 3.12中引入的对象库新特性的更多细节,请参考官方文档: https://cmake.org/cmake/help/v3.12/manual/cmake-buildsystem.7.html#object-libraries \ No newline at end of file diff --git a/content/chapter7/7.8-chinese.md b/content/chapter7/7.8-chinese.md index 16f9757..d7a7b00 100644 --- a/content/chapter7/7.8-chinese.md +++ b/content/chapter7/7.8-chinese.md @@ -6,13 +6,11 @@ ## 准备工作 -将使用与前一个示例相同的源代码。惟一的更改将出现在CMakeLists.txt文件中,我们将在下面的部分中讨论这些更改。 +将使用与前一个示例相同的源代码。惟一的更改将出现在`CMakeLists.txt`文件中,我们将在下面的部分中讨论这些更改。 ## 具体实施 -让我们详细看看CMake需要的各种文件: - -1. 主CMakeLists.txt包含以下内容: +1. 主`CMakeLists.txt`包含以下内容: ```cmake cmake_minimum_required(VERSION 3.5 FATAL_ERROR) @@ -94,7 +92,7 @@ ) ``` -5. 其余CMakeLists.txt文件和`src/initial/CMakeLists.txt`相同: +5. 其余`CMakeLists.txt`文件和`src/initial/CMakeLists.txt`相同: ```cmake target_sources(automaton @@ -133,14 +131,14 @@ * automaton(包含除转换之外的所有源) * evolution(在`src/evolution`中定义,并通过`cpp_test`链接) -本例中,通过使用`include()`引用CMakeLists.txt文件,我们在父范围内,仍然能保持所有目标可用: +本例中,通过使用`include()`引用`CMakeLists.txt`文件,我们在父范围内,仍然能保持所有目标可用: ```cmake include(src/CMakeLists.txt) include(external/CMakeLists.txt) ``` -我们可以构建一个包含树,记住当进入子目录(src/CMakeLists.txt)时,我们需要使用相对于父范围的路径: +我们可以构建一个包含树,记住当进入子目录(`src/CMakeLists.txt`)时,我们需要使用相对于父范围的路径: ```cmake include(${CMAKE_CURRENT_LIST_DIR}/evolution/CMakeLists.txt) diff --git a/content/chapter7/7.9-chinese.md b/content/chapter7/7.9-chinese.md index ae4d9b3..d1c301d 100644 --- a/content/chapter7/7.9-chinese.md +++ b/content/chapter7/7.9-chinese.md @@ -17,29 +17,29 @@ . ├── CMakeLists.txt ├── external -│ ├── CMakeLists.txt -│ ├── conversion.f90 -│ └── README.md +│ ├── CMakeLists.txt +│ ├── conversion.f90 +│ └── README.md ├── src -│ ├── CMakeLists.txt -│ ├── evolution -│ │ ├── ancestors.f90 -│ │ ├── CMakeLists.txt -│ │ ├── empty.f90 -│ │ └── evolution.f90 -│ ├── initial -│ │ ├── CMakeLists.txt -│ │ └── initial.f90 -│ ├── io -│ │ ├── CMakeLists.txt -│ │ └── io.f90 -│ ├── main.f90 -│ └── parser -│ ├── CMakeLists.txt -│ └── parser.f90 +│ ├── CMakeLists.txt +│ ├── evolution +│ │ ├── ancestors.f90 +│ │ ├── CMakeLists.txt +│ │ ├── empty.f90 +│ │ └── evolution.f90 +│ ├── initial +│ │ ├── CMakeLists.txt +│ │ └── initial.f90 +│ ├── io +│ │ ├── CMakeLists.txt +│ │ └── io.f90 +│ ├── main.f90 +│ └── parser +│ ├── CMakeLists.txt +│ └── parser.f90 └── tests - ├── CMakeLists.txt - └── test.f90 + ├── CMakeLists.txt + └── test.f90 ``` 主程序在` src/main.f90`中: @@ -122,7 +122,7 @@ contains end module ``` -实现时间步长的evolution库被人为地分成三个文件。大部分在`src/evolution/evolution.f90`中: +evolution库分成三个文件,大部分在`src/evolution/evolution.f90`中: ```fortran module evolution @@ -190,7 +190,7 @@ module ancestors end module ``` -我们还有一个“空”模块在` src/evolution/empty.f90 `中: +还有一个“空”模块在` src/evolution/empty.f90 `中: ```fortran module empty @@ -213,8 +213,6 @@ empty_subroutine_no_interface() end subroutine ``` -我们将在下一节中解释这些选择。 - 启动条件的代码位于`src/initial/initial.f90`: ```fortran @@ -287,7 +285,7 @@ module parser end module ``` -最后,我们使用`tests/test.f90`对上面的实现进行测试: +最后,使用`tests/test.f90`对上面的实现进行测试: ```fortran program test @@ -329,9 +327,7 @@ end program ## 具体实施 -下面我们将讨论相应的CMake结构: - -1. 主CMakeLists.txt类似于第7节,我们只是将CXX换成Fortran,去掉C++11的要求: +1. 主`CMakeLists.txt`类似于第7节,我们只是将CXX换成Fortran,去掉C++11的要求: ```cmake cmake_minimum_required(VERSION 3.5 FATAL_ERROR) @@ -388,7 +384,7 @@ end program ) ``` -4. `src/CMakeLists.txt`文件添加了更多的子目录,这些子目录又包含CMakeLists.txt文件。它们在结构上都是相似的,例如:`src/initial/CMakeLists.txt`包含以下内容: +4. `src/CMakeLists.txt`文件添加了更多的子目录,这些子目录又包含`CMakeLists.txt`文件。它们在结构上都是相似的,例如:`src/initial/CMakeLists.txt`包含以下内容: ```cmake add_library(initial "") @@ -413,7 +409,7 @@ end program ) ``` -6. 单元测试在tests/CMakeLists.txt中注册: +6. 单元测试在`tests/CMakeLists.txt`中注册: ```cmake add_executable(fortran_test test.f90) @@ -488,7 +484,7 @@ end program ## 工作原理 -第7节中使用`add_subdirectory`限制范围,将从下往上讨论CMake结构,从定义每个库的单个CMakeLists.txt文件开始,比如`src/evolution/CMakeLists.txt`: +第7节中使用`add_subdirectory`限制范围,将从下往上讨论CMake结构,从定义每个库的单个`CMakeLists.txt`文件开始,比如`src/evolution/CMakeLists.txt`: ```cmake add_library(evolution "") @@ -501,7 +497,7 @@ target_sources(evolution ) ``` -这些独立的CMakeLists.txt文件定义了源文件的库,遵循与前两个示例相同的方式:开发或维护人员可以对其中文件分而治之。 +这些独立的`CMakeLists.txt`文件定义了源文件的库,遵循与前两个示例相同的方式:开发或维护人员可以对其中文件分而治之。 首先用`add_library`定义库名,然后定义它的源和包含目录,以及它们的目标可见性。这种情况下,因为它们的模块接口是在库之外访问,所以`ancestors.f90`和` evolution.f90`都是`PUBLIC`,而模块接口` empty.f90 `不能在文件之外访问,因此将其标记为`PRIVATE`。 @@ -525,7 +521,7 @@ target_link_libraries(automata ) ``` -这个文件在主CMakeLists.txt中被引用。这意味着我们使用CMakeLists.txt文件树(使用`add_subdirectory`添加)从库树构建项目。正如第7节中讨论的,使用`add_subdirectory`限制范围,这种方法可以扩展到更大型的项目,而不需要在多个目录之间的全局变量中携带源文件列表,还可以隔离范围和名称空间。 +这个文件在主`CMakeLists.txt`中被引用。这意味着我们使用`CMakeLists.txt`文件(使用`add_subdirectory`添加)构建项目。正如第7节中讨论的,使用`add_subdirectory`限制范围,这种方法可以扩展到更大型的项目,而不需要在多个目录之间的全局变量中携带源文件列表,还可以隔离范围和名称空间。 将这个Fortran示例与C++版本(第7节)进行比较,我们可以注意到,在Fortran的情况下,相对的CMake工作量比较小;我们不需要使用`target_include_directory`,因为没有头文件,接口是通过生成的Fortran模块文件进行通信。另外,我们既不需要担心`target_sources`中列出的源文件的顺序,也不需要在库之间强制执行任何显式依赖关系。CMake能够从源文件依赖项推断Fortran模块依赖项。使用`target_sources`与`PRIVATE`和`PUBLIC`资源结合使用,以紧凑和健壮的方式表示接口。