From 9c1526f71963f14d065803cf00feb7af39e7022c Mon Sep 17 00:00:00 2001 From: xiaoweic Date: Wed, 16 Nov 2022 10:33:54 +0800 Subject: [PATCH] update --- content/3/chapter12/0.tex | 8 ++--- content/3/chapter12/2.tex | 62 +++++++++++++++++++-------------------- content/3/chapter12/3.tex | 16 +++++----- content/3/chapter12/4.tex | 32 ++++++++++---------- content/3/chapter12/5.tex | 48 +++++++++++++++--------------- content/3/chapter12/6.tex | 16 +++++----- content/3/chapter12/7.tex | 20 ++++++------- content/3/chapter12/8.tex | 8 ++--- content/Appendix/0.tex | 2 +- content/Appendix/1.tex | 14 ++++----- content/Appendix/2.tex | 2 +- content/Appendix/3.tex | 10 +++---- content/Appendix/4.tex | 6 ++-- 13 files changed, 122 insertions(+), 122 deletions(-) diff --git a/content/3/chapter12/0.tex b/content/3/chapter12/0.tex index c7f6ee2..8a3dce2 100644 --- a/content/3/chapter12/0.tex +++ b/content/3/chapter12/0.tex @@ -1,11 +1,11 @@ -我们收集了建造专业项目所需的所有知识,学习了结构化、构建、依赖管理、测试、分析、安装和打包。是时候通过创建一个连贯、专业的项目来将这些获得的技能付诸实践了。 +我们收集了建造专业项目所需的所有知识,了解了结构化、构建、依赖管理、测试、分析、安装和打包。是时候通过创建一个连贯、专业的项目来将这些获得的技能付诸实践了。 -重要的是要理解,即使是微不足道的程序也将受益于自动化的质量检查和简化的端到端流程,将原始代码转化为完整的解决方案。的确,这通常是一项相当大的投资,因为需要采取许多步骤来正确地准备一切——若试图将这些机制添加到已经存在的代码库中(通常,已经非常庞大和复杂),则需要采取更多步骤。 +重要的是要理解,即使是微不足道的程序也可受益于自动化的质量检查和简化的端到端流程,将原始代码转化为完整的解决方案。这通常是一项相当大的投资,需要许多步骤来准备这一切——若试图将这些机制添加到现存在的代码库中(通常,已经非常庞大和复杂),则需要采取更多步骤。 -这就是从一开始就使用CMake并将所有管道设置在前面的原因,不仅将更容易配置,更重要的是,也更有效地尽早进行,因为所有的质量控制和构建自动化无论如何都必须添加到长期项目中。 +这就是从一开始就使用CMake并在前面对所有流水进行设置的原因,不仅更容易配置,也能更有效地尽早进行测试,因为所有的质量控制和自动化构建都必须添加到长期项目中。 -这正是在本章要做的——将编写一个尽可能小而简单的新解决方案。只执行一个(几乎)功能——两个数字相加,限制业务代码的功能将让我们专注于项目的其他方面。 +这正是在本章要做的——编写一个尽可能小而简单的新解决方案。只执行一个(几乎)功能——两个数字相加,限制业务代码的功能可以让我们更专注于项目的其他方面。 为了解决一个更复杂的问题,这个项目将构建一个库和一个可执行文件。该库将提供内部业务逻辑,也可以供其他项目作为CMake包使用。可执行文件将只针对最终用户,并将实现一个显示底层库功能的用户界面。 diff --git a/content/3/chapter12/2.tex b/content/3/chapter12/2.tex index a4e9a88..956be2c 100644 --- a/content/3/chapter12/2.tex +++ b/content/3/chapter12/2.tex @@ -1,47 +1,47 @@ -本章中构建的软件并不复杂——我们将创建一个简单的计算器,将两个数字相加(图12.1)。它将作为一个控制台应用程序发布,带有一个文本用户界面和一个用于执行数学运算的库,这可能用于其他项目。虽然在现实生活中这样的项目没有太多用处,因为C++在其标准库中为计算提供了大量支持,但它将完美地用于探索本书中讨论的所有技术如何在实践中协同工作: +本章中构建的软件并不复杂——我们将创建一个简单的计算器,将两个数字相加(图12.1)。作为一个控制台应用程序发布,带有文本用户界面和一个用于执行数学运算的库,这可能用于其他项目。虽然在现实中没有太多用处,但它将用于探索本书中讨论的所有技术,以及如何在实践中进行协同工作: \begin{center} \includegraphics[width=0.8\textwidth]{content/3/chapter12/images/1.jpg}\\ 图12.1 控制台计算器用户界面的两种状态 \end{center} -通常,项目要么生成面向用户的可执行文件,要么为开发人员生成库。同时具备这两种功能的项目比较少见——一些应用程序提供独立的SDK或库来支持插件,另一种情况可能是提供其用法示例的库。我们在本章中构建的项目在某种程度上属于最后一类。 +通常,项目要么生成面向用户的可执行文件,要么为开发人员生成库。同时具备这两种功能的项目很少见——一些应用程序提供独立的SDK或库来支持插件,另一种情况是提供其用法示例的库。我们在本章中构建的项目在某种程度上属于最后一类。 -这里先回顾一下之前章节的内容,并选择其中描述的技术和工具来构建我们的应用程序: +这里先回顾一下之前章节的内容,并选择相应的技术和工具来构建应用: -第1章: +\textbf{第1章:} -提供关于CMake的基本信息——如何安装它,并使用命令行来构建项目。这里提供的有关项目文件的信息是关键:不同文件的职责、常规使用的名称,以及一些怪癖。本章中,还讨论了生成器的预设文件,但在本项目中先跳过这些文件。 +提供关于CMake的基本信息——如何安装它,并使用命令行来构建项目。这里提供的有关项目文件的信息是关键:不同文件的职责、常规使用的名称,以及一些奇淫技巧。本章中,还讨论了生成器的预设文件,但在本项目中先跳过这些文件。 -第2章: +\textbf{第2章:} 介绍了编写正确的列表文件和脚本所需的工具,分享了关于代码的基本信息:注释、命令调用和参数。我们还详细解释了变量、列表和控制结构,并给出了一些非常有用的命令。这些知识将应用于整个项目。 -第3章: +\textbf{第3章:} 这里的内容将对项目产生关键性影响: \begin{itemize} \item -指定最低的CMake版本将决定,应用哪些CMake策略;命名、版本控制和配置项目语言会影响构建的基本行为。 +指定最低的CMake版本将决定应用哪些CMake策略,命名、版本控制和配置项目语言会影响构建的基本行为。 \item 了解形成目录和文件布局的项目分区和结构。 \item -系统发现来帮助我们决定了如何处理不同的环境,特别是对于这个项目——例如,是否需要运行ldconfig? +系统可以帮助我们处理不同的环境,特别是对于这个项目——例如,是否需要运行ldconfig? \item -工具链配置允许特定版本的C++和编译器支持的标准需求。 +工具链配置允许C++和编译器支持特定的标准需求。 \end{itemize} -本章还说明了禁用源代码内构建通常是一个好主意。 +本章还说明了禁用源内构建的原因。 -第4章: +\textbf{第4章:} -这里,强调了每个现代CMake项目是如何使用目标的,原因如下: +这里,强调了每个现代CMake项目如何使用目标,原因如下: \begin{itemize} \item @@ -56,21 +56,21 @@ 这个项目中,将使用自定义命令为Valgrind和覆盖率报告生成文件,并且使用目标钩子(PRE\_BUILD),来清理覆盖率工具生成的.gcda文件。 -第5章: +\textbf{第5章:} -没有编译就没有C++项目,CMake允许我们以多种方式调整这个过程:扩展目标的源、配置优化器和提供调试信息。对于这个项目,默认的编译标志就可以了,但我们将继续使用预处理器: +没有编译就没有C++项目,CMake可以以多种方式调整这个过程:扩展目标的源、配置优化器和提供调试信息。对于这个项目,默认的编译标志就可以了,但我们将继续使用预处理器: \begin{itemize} \item -将在编译后的可执行文件中存储构建元数据(项目版本、构建时间和Git提交SHA),并将其显示给用户。 +在编译后的可执行文件中存储构建元数据(项目版本、构建时间和Git提交SHA),并将其显示给用户。 \item -将启用头文件的预编译。在如此小的项目中,这并不是必须的,但它将帮助我们实践这个知识点。 +将启用头文件的预编译。在如此小的项目中,这并不是必须的,但会帮助我们实践这个知识点。 \end{itemize} -统一构建将不是必要的——这个项目将不够大,但也可以添加。 +统一构建不是必要的——这个项目不够大,但也可以添加。 -第6章: +\textbf{第6章:} 提供了关于链接的信息(在任何项目中都很有用),其中大部分在默认情况下很有用。但是由于这个项目也提供了一个库,将显式地引用以下的一些构建说明: @@ -84,35 +84,35 @@ 本章概述了如何分离main()进行测试,我们的项目中也有测试。 -第7章: +\textbf{第7章:} -为了使项目更有趣,将引入一个外部依赖项:一个文本UI库。本章中描述了一些依赖管理方法。选择正确的一个并不太难:FetchContent实用程序模块通常是推荐的,也是最方便的(除非解决本章中描述的特定情况)。 +为了使项目更有趣,将引入一个外部依赖项:文本UI库。本章中描述了一些依赖管理方法。选择正确的一个并不太难:FetchContent实用程序模块通常是推荐的,也是最方便的(除非解决本章中描述的特定情况)。 -第8章: +\textbf{第8章:} -适当的自动化测试是必须的,以确保解决方案的质量不会随着时间的推移而下降。我们将添加对CTest的支持,并为测试正确地构造项目(将应用前面提到的main()分离)。 +必须有适当的自动化测试,以确保解决方案的质量不会随着时间而下降。我们将添加对CTest的支持,并为测试正确地构造项目(将应用前面提到的main()分离)。 此外,还讨论了两个测试框架:Catch2和GTest;对于这个项目,我们将使用后者。为了获得关于覆盖率的明确信息,将生成带有LCOV的HTML报告。 -第9章: +\textbf{第9章:} 要执行静态分析,可以从各种各样的工具中进行选择:Clang-Tidy、Cpplint、Cppcheck、include-what-you-use和连接其他工具。本例中,将使用Cppcheck,因为Clang-Tidy不能很好地处理用GCC编译的预编译头文件。动态分析将使用Valgrind的Memcheck工具完成,将使用Memcheck封面包装器生成HTML报告,源代码也将在编译过程中使用ClangFormat自动格式化。 -第10章: +\textbf{第10章:} -因为提供一个库作为这个项目的一部分,所以至少要提供一些与之配套的文档。CMake允许我们用Doxygen自动生成,所以可以通过添加doxygenawesome-css来进行更新文档外观。 +因为提供一个库作为这个项目的一部分,所以要提供一些与之配套的文档。CMake可以用Doxygen自动生成,所以可以通过添加doxygenawesome-css来进行更新文档外观。 -第11章: +\textbf{第11章:} -最后,配置解决方案的安装和打包,将按照描述准备文件以形成包,以及目标定义。我们将通过包含GNUInstallDirs模块将其和构件从构建目标安装到适当的目录中。我们将另外配置一些组件模块化,并与CPack一起使用。 +最后,配置解决方案的安装和打包,将按照描述准备文件以形成包,以及目标定义。我们将通过包含GNUInstallDirs模块,将其和构件从构建目标安装到适当的目录中。我们将另外配置一些组件模块化,并与CPack一起使用。 -专业项目还附带一些文本文件:README、LICENSE、INSTALL等。我们将在最后简要地讨论这个问题。 +专业项目还附带一些文本文件:README、LICENSE、INSTALL等。我们会在最后简要地讨论这个问题。 \begin{tcolorbox}[colback=blue!5!white,colframe=blue!75!black,title=Note] -为了使事情更简单,不会实现检查所有必需的实用程序和依赖项是否可用的逻辑。我们将在这里依赖CMake来显示诊断,并告诉用户缺少什么。若在阅读本书后发布的项目获得了显著的吸引力,可能需要考虑添加这些机制来改善用户体验。 +为了使事情更简单,不会实现检查所有必需的实用程序和依赖项是否可用的逻辑。我们将在这里依赖CMake来显示诊断,并告诉用户缺少什么。若在阅读本书后发布的项目获得了其他人的关注,可能就需要考虑添加这些机制来改善用户体验了。 \end{tcolorbox} -形成了一个清晰的计划之后,再来讨论如何从逻辑目标和目录结构两方面实际构建项目。 +形成了一个清晰的计划之后,再从逻辑目标和目录结构两方面讨论实际的构建项目。 diff --git a/content/3/chapter12/3.tex b/content/3/chapter12/3.tex index a88fdcc..2cd351d 100644 --- a/content/3/chapter12/3.tex +++ b/content/3/chapter12/3.tex @@ -6,7 +6,7 @@ 图12.2 逻辑目标的结构 \end{center} -我们按照构建顺序来探索这个结构。首先,编译calc\_obj,这是一个对象库。我们确实在书中几次提到了对象库,但并没有把它们作为一个概念来介绍。 +我们按照构建顺序来探索这个结构。首先,编译calc\_obj,这是一个对象库。我们确实在书中几次提到了对象库,但并没有作为一个知识点来介绍。 \subsubsubsection{12.3.1\hspace{0.2cm}对象库} @@ -23,7 +23,7 @@ \subsubsubsection{12.3.1\hspace{0.2cm}对象库} add_executable(... $ ...) \end{lstlisting} -或者,可以使用target\_link\_libraries()将它们作为依赖项添加。 +或者,可以使用target\_link\_libraries()将其作为依赖项添加。 Calc库中,对象库将有助于避免为库的静态和动态版本重复编译库源。只需要记住显式地使用POSITION\_INDEPENDENT\_CODE编译目标文件,因为这是动态库的需求。 @@ -31,15 +31,15 @@ \subsubsubsection{12.3.1\hspace{0.2cm}对象库} \subsubsubsection{12.3.2\hspace{0.2cm}比较动态库与静态库} -在第6章中简要介绍了这两种类型的库。然后我们提到,对于使用相同动态库的多个程序,整体内存使用可能会更好,而且用户很可能已经拥有最流行的库,或者知道如何快速安装。更重要的是,动态库是在单独的文件中交付的,这些文件必须安装在特定的路径中,以便动态链接器找到,而静态库是作为可执行文件的一部分。这种形式下,静态库使用起来稍微快一些,因为不需要在内存中查找代码的位置。 +第6章中简要介绍了这两种类型的库,对于使用相同动态库的多个程序,整体内存使用可能会更好,而且用户很可能已经拥有最流行的库,或者知道如何快速安装。更重要的是,动态库是在单独的文件中交付的,这些文件必须安装在特定的路径中,以便动态链接器找到,而静态库是作为可执行文件的一部分,因为不需要在内存中查找代码的位置,所以静态库使用起来稍微快一些。 -作为库作者,可以决定是提供库的静态版本还是动态版本,或者可以简单地提供两个版本,并把这个决定留给使用库的开发者。我们在这里选择后者(只是为了了解如何完成)。 +作为库作者,可以决定是提供库的静态还是动态版本,或者可以简单地提供两个版本,并把这个决定留给使用库的开发者。我们在这里选择后者(只是为了了解如何完成)。 -静态库将由calc\_test目标使用,该目标将包含单元测试,以确保所提供的库业务功能按预期工作。我们从同一组已编译的目标文件构建两个版本,测试任何一个版本都是可以的,因为其行为真的不应该有区别。 +静态库将由calc\_test目标使用,该目标将包含单元测试,以确保所提供的库业务功能按预期工作。我们从同一组已编译的目标文件构建两个版本,测试任何一个都可以,因为其行为没有区别。 由calc\_console\_static目标提供的控制台应用程序将使用动态库。该目标还将链接到一个外部依赖:Arthur Sonzogni的功能终端用户界面(FTXUI)库(在扩展阅读部分有一个到GitHub项目的链接)。它为文本用户界面提供了一个无依赖性、跨平台的框架。 -最后两个目标是calc\_console和calc\_console\_test。calc\_console目标只是一个围绕calc\_console\_static的bootstrap main()包装器,其唯一目的是从业务代码中提取入口点。可以为其编写单元测试(需要提供接口),并使用calc\_console\_test运行。 +最后两个目标是calc\_console和calc\_console\_test。calc\_console目标只是一个围绕calc\_console\_static的bootstrap main()包装器,其目的是从业务代码中提取入口点。可以为其编写单元测试(需要提供接口),并使用calc\_console\_test运行。 现在知道需要建立什么目标,以及它们之间的关系。来看看如何用文件和目录来组织项目。 @@ -75,9 +75,9 @@ \subsubsubsection{12.3.3\hspace{0.2cm}目录结构} \end{tabular} \end{table} -最初,cmake目录比业务代码更繁忙,但随着项目功能的增长,这种情况将很快发生变化。启动一个清洁项目的努力是很重要的,但不要担心——很快就会得到回报。 +最初,cmake目录比业务代码更多,但随着项目功能的增长,这种情况将很快发生变化。启动一个清洁项目的努力是很重要的,但不要担心——很快就会得到回报。 -我们将浏览所有文件,详细了解它们的作用以及它们在项目中扮演的角色。这将分为四个步骤:构建、测试、安装和提供文档。 +我们将浏览所有文件,详细了解它们的作用以及它们在项目中扮演的角色。这将分为四个步骤:构建、测试、安装和生成文档。 diff --git a/content/3/chapter12/4.tex b/content/3/chapter12/4.tex index 2d80dcc..43cc9db 100644 --- a/content/3/chapter12/4.tex +++ b/content/3/chapter12/4.tex @@ -23,17 +23,17 @@ include(Install) \end{lstlisting} -首先提供关键的项目细节,并添加到CMake实用程序模块的路径(项目中的CMake目录)。然后禁用源代码内构建(通过自定义模块),并包含两个关键目录: +首先提供关键的项目细节,并添加到CMake实用程序模块的路径(项目中的CMake目录)。然后禁用源内构建(通过自定义模块),并包含两个关键目录: \begin{itemize} \item -src,包含项目源(在构建树中命名为bin) +src,包含项目源(构建树中命名为bin) \item test,包含所有测试实用程序 \end{itemize} -最后,将包含另一个模块,该模块将设置项目的安装。这将在另一节中讨论。同时,来看一看NoInSourceBuilds模块,了解它是如何工作的: +最后,将包含另一个模块,该模块将设置项目的安装。来看一看NoInSourceBuilds模块,了解它是如何工作的: \begin{lstlisting}[style=styleCMake] # chapter-12/01-full-project/cmake/NoInSourceBuilds.cmake @@ -89,11 +89,11 @@ \subsubsubsection{12.4.1\hspace{0.2cm}构建Calc库} # ... documentation generation \end{lstlisting} -我们声明三个目标: +声明三个目标: \begin{itemize} \item -编译calc.cpp实现文件的对象库,并通过PUBLIC\_HEADER属性引用calc.h头文件,该属性可以在配置的include目录中找到(由于生成器表达式为特定模式提供了适当的路径——构建或安装)。通过使用这个库,避免了对其他目标的重复编译,但还需要启用POSITION\_INDEPENDENT\_CODE,以便动态库可以使用生成的目标文件。 +编译calc.cpp实现文件的对象库,并通过PUBLIC\_HEADER属性引用calc.h头文件,该属性可以在配置的include目录中找到(由于生成器表达式为特定模式提供了适当的路径——构建或安装)。通过使用这个库,避免了对其他目标的重复编译,还要启用POSITION\_INDEPENDENT\_CODE,以便动态库可以使用生成的目标文件。 \item calc\_shared,依赖于calc\_obj的动态库。 @@ -102,7 +102,7 @@ \subsubsubsection{12.4.1\hspace{0.2cm}构建Calc库} calc\_static,依赖于calc\_obj的静态库。 \end{itemize} -完整起见,这里将添加一个calc库的C++代码: +这里将添加calc库的C++代码: \begin{lstlisting}[style=styleCXX] // chapter-12/01-full-project/src/calc/include/calc/calc.h @@ -115,7 +115,7 @@ \subsubsubsection{12.4.1\hspace{0.2cm}构建Calc库} } // namespace Calc \end{lstlisting} -这段代码非常基础:声明了两个包含在Calc命名空间中的全局函数(C++名称空间在库中非常有用,有助于避免名称冲突)。 +这段代码非常基础:声明了两个包含在Calc命名空间中的全局函数(C++命名空间在库中非常有用,有助于避免名称冲突)。 实现文件也非常简单: @@ -135,7 +135,7 @@ \subsubsubsection{12.4.1\hspace{0.2cm}构建Calc库} 这结束了src/calc目录中文件的解释。接下来是src/calc\_console,并使用这个库构建控制台计算器的可执行文件。 -\subsubsubsection{12.4.2\hspace{0.2cm}构建Calc Console可执行文件} +\subsubsubsection{12.4.2\hspace{0.2cm}构建Calc终端可执行文件} calc\_console的源目录包含几个文件:一个列表文件、两个实现文件(业务代码和一个引导程序)和一个头文件。列表文件如下所示: @@ -159,7 +159,7 @@ \subsubsubsection{12.4.2\hspace{0.2cm}构建Calc Console可执行文件} target_link_libraries(calc_console calc_console_static) \end{lstlisting} -列表文件看起来很忙,但是现在,作为有经验的CMake用户,可以很容易地理清里面发生的事情: +列表文件看起来很多,但作为有经验的CMake用户,可以很容易地理清里面发生的事情: \begin{itemize} \item @@ -181,7 +181,7 @@ \subsubsubsection{12.4.2\hspace{0.2cm}构建Calc Console可执行文件} 添加并链接calc\_console引导可执行文件,并提供了入口点。 \end{itemize} -同样,这里把测试和文档的讨论推迟到本章的适当部分。让我们来看看依赖管理和构建信息生成。 +同样,这里把测试和文档的讨论推迟到本章的后续部分。来看看依赖管理和构建信息生成。 注意,我们更喜欢使用实用程序模块,而不是查找模块来引入FTXUI。这是因为该依赖项不太可能已经存在于系统中。而不是希望找到它,我们将获取并安装它: @@ -200,7 +200,7 @@ \subsubsubsection{12.4.2\hspace{0.2cm}构建Calc Console可执行文件} FetchContent_MakeAvailable(FTXTUI) \end{lstlisting} -我们使用推荐的FetchContent方法,第7章有详细介绍,唯一不同的添加是对option()指令的调用。其可以跳过FTXUI构建的冗长步骤,并将其安装配置从该项目的安装中分离出来。对于GTest依赖关系也需要同样的操作。option()指令在扩展阅读部分中有引用。 +使用推荐的FetchContent方法,第7章有详细介绍,唯一不同的添加是对option()指令的调用。其可以跳过FTXUI构建的冗长步骤,并将其安装配置从该项目的安装中分离出来。对于GTest依赖关系也需要同样的操作。option()指令在扩展阅读部分中有引用。 calc\_command的列表文件还包含一个与构建相关的自定义实用程序模块:BuildInfo。我们将使用它来记录三个可以在可执行文件中显示的值: @@ -215,7 +215,7 @@ \subsubsubsection{12.4.2\hspace{0.2cm}构建Calc Console可执行文件} 顶层列表文件中指定的项目版本 \end{itemize} -你可能还记得在第5章中,可以使用CMake来捕获一些构建时的值,并通过模板文件将其提供给C++代码——例如,使用一个C++结构体: +在第5章中,可以使用CMake来捕获一些构建时的值,并通过模板文件将其提供给C++代码——例如,使用C++结构体: \begin{lstlisting}[style=styleCXX] // chapter-12/01-full-project/cmake/buildinfo.h.in @@ -230,7 +230,7 @@ \subsubsubsection{12.4.2\hspace{0.2cm}构建Calc Console可执行文件} }; \end{lstlisting} -为了在配置阶段填充该结构,我们会使用以下代码: +为了在配置阶段填充该结构,可以使用以下代码: \begin{lstlisting}[style=styleCMake] # chapter-12/01-full-project/cmake/BuildInfo.cmake @@ -255,9 +255,9 @@ \subsubsubsection{12.4.2\hspace{0.2cm}构建Calc Console可执行文件} endfunction() \end{lstlisting} -包含该模块将设置包含所需要的信息的变量,然后使用configure\_file()来生成buildinfo.h。剩下的就是调用BuildInfo函数,并添加生成文件的目录,以包含所需目标的目录。然后,可以与多个不同的使用者共享该文件。这种情况下,可能需要在列表文件的顶部添加include\_guard(GLOBAL),以避免对每个目标都运行git命令。 +包含该模块将设置包含所需要的信息的变量,然后使用configure\_file()来生成buildinfo.h。剩下的就是调用BuildInfo函数,并添加生成文件的目录,以包含所需目标的目录。然后,可以与多个不同的使用者共享该文件,并且可能需要在列表文件的顶部添加include\_guard(GLOBAL),以避免对每个目标都运行git命令。 -深入研究控制台计算器的实现之前,不应该过分担心tui.cpp文件的复杂性。要完全理解它,只需要对FXTUI库有一定的了解——这里我们不想太深入。相反,让我们关注突出显示的行: +深入研究控制台计算器的实现之前,不应该过分担心tui.cpp文件的复杂性。要完全理解它,只需要对FXTUI库有一定的了解——我们不想太深入。相反,让我们关注突出显示的行: \begin{lstlisting}[style=styleCXX] // chapter-12/01-full-project/src/calc_console/tui.cpp @@ -323,7 +323,7 @@ \subsubsubsection{12.4.2\hspace{0.2cm}构建Calc Console可执行文件} 这段简短的代码利用ftxui创建一个交互式控制台屏幕,该屏幕接受getTui()返回的Component对象,使其对用户可见,并在循环中收集键盘事件,创建一个界面,如图12.1所示。同样,理解这一点并不真正重要,因为ftxui的主要目的是为我们提供一个外部依赖项,重要的是其可以使用它来练习CMake技术。 -已经介绍了src目录中的所有文件。然后,测试和分析程序的话题。 +已经介绍了src目录中的所有文件。接下来,来看看测试和分析程序。 diff --git a/content/3/chapter12/5.tex b/content/3/chapter12/5.tex index 97dec8c..c516a90 100644 --- a/content/3/chapter12/5.tex +++ b/content/3/chapter12/5.tex @@ -1,13 +1,13 @@ -程序分析和测试一起进行,以确保解决方案的质量。例如,当使用测试代码时,运行Valgrind会变得更加一致。出于这个原因,可以将这两个东西配置在一起。图12.5演示了执行流程和设置它们所需的文件(一些代码片段将被添加到src目录): +程序分析和测试一起进行,以确保解决方案的质量。当使用测试代码时,运行Valgrind会变得更加一致。出于这个原因,可以将这两个东西配置在一起。图12.5演示了执行流程和设置它们所需的文件(一些代码片段将添加到src目录): \begin{center} \includegraphics[width=0.6\textwidth]{content/3/chapter12/images/5.jpg}\\ 图12.5 启动测试和程序分析 \end{center} -测试位于test目录中,其列表文件通过add\_subdirectory()指令从顶级列表文件中执行。来看看里面有什么: +测试位于test目录中,其列表文件通过add\_subdirectory()指令从顶层列表文件中执行。来看看里面有什么: \begin{lstlisting}[style=styleCMake] # chapter-12/01-full-project/test/CMakeLists.txt @@ -17,7 +17,7 @@ add_subdirectory(calc_console) \end{lstlisting} -Testing模块中定义的测试实用程序包含在这个级别,以允许两个目标组(来自calc和calc\_console目录)使用它们: +Testing模块中定义的测试实用程序包含在这个级别,以允许两个目标组(来自calc和calc\_console目录)使用: \begin{lstlisting}[style=styleCMake] # chapter-12/01-full-project/cmake/Testing.cmake (fragment) @@ -38,9 +38,9 @@ ... \end{lstlisting} -启用了测试并包含了FetchContent模块来获取GTest和GMock,这个项目中并没有真正使用GMock,但是这两个框架捆绑在一个存储库中,因此还需要配置GMock。该配置中突出显示的部分将这两个框架的安装从我们的项目安装中分离出来(通过将适当的option()设置为OFF)。 +启用了测试并包含了FetchContent模块来获取GTest和GMock,这个项目中并没有真正使用GMock,但是这两个框架会捆绑在一个库中,因此还需要配置GMock。该配置中突出显示的部分将这两个框架的安装从我们的项目安装中分离出来(将适当的option()设置为OFF)。 -接下来,需要创建一个功能,支持对业务目标进行彻底的测试。可以将它保存在同一个文件中: +接下来,需要创建一个功能,支持对业务目标进行彻底的测试。可以将其保存在同一个文件中: \begin{lstlisting}[style=styleCMake] # chapter-12/01-full-project/cmake/Testing.cmake (continued) @@ -57,11 +57,11 @@ endmacro() \end{lstlisting} -这里,首先包含了必要的模块:GoogleTest与CMake捆绑在一起,但Coverage和Memcheck由我们编写。然后提供一个AddTests宏,其为测试、代码覆盖和内存检查准备一个目标。让我们详细看看它是如何工作的。 +首先包含了必要的模块:GoogleTest与CMake捆绑在一起,但Coverage和Memcheck由我们编写。然后,提供一个AddTests宏,其为测试、代码覆盖和内存检查准备一个目标。让我们详细了解其是如何工作的。 \subsubsubsection{12.5.1\hspace{0.2cm}准备覆盖率模块} -添加覆盖多个目标有点棘手,因为它包含几个步骤。首先引入两个函数,用于在构建之间启用覆盖率跟踪和清理过时的跟踪文件: +添加覆盖多个目标有点棘手,因为其包含几个步骤。首先引入两个函数,用于在构建之间启用覆盖率跟踪和清理过时的跟踪文件: \begin{lstlisting}[style=styleCMake] # chapter-12/01-full-project/cmake/Coverage.cmake (fragment) @@ -81,7 +81,7 @@ \subsubsubsection{12.5.1\hspace{0.2cm}准备覆盖率模块} endfunction() \end{lstlisting} -当得到单独的目标配置(calc\_... 和calc\_console\_...),前面的函数将在后面使用。Coverage模块会将提供一个生成自定义覆盖目标的函数: +当得到单独的目标配置(calc\_...和calc\_console\_...),前面的函数将在后面使用。Coverage模块会提供一个生成自定义覆盖目标的函数: \begin{lstlisting}[style=styleCMake] # chapter-12/01-full-project/cmake/Coverage.cmake (continued) @@ -105,18 +105,18 @@ \subsubsubsection{12.5.1\hspace{0.2cm}准备覆盖率模块} AddCoverage()在测试模块中的AddTests()函数中调用。它与第8章中介绍的略有不同,因为其考虑了目标的名称,并将其添加到输出路径,以避免冲突。 -要为两个测试目标生成报告,只需要运行两个cmake命令(在用Debug构建类型配置项目之后): +要为两个测试目标生成报告,只需要运行两个cmake命令(在Debug构建类型配置项目之后): \begin{tcblisting}{commandshell={}} cmake --build -t coverage-calc_test cmake --build -t coverage-calc_console_test \end{tcblisting} -现在是时候修改我们前面创建的Memcheck模块了(第9章),以处理多个目标。 +现在是时候修改前面创建的Memcheck模块了(第9章),以处理多个目标。 \subsubsubsection{12.5.2\hspace{0.2cm}准备Memcheck模块} -AddTests()使用Valgrind内存管理报告的生成,这里将从这个模块设置开始: +AddTests()使用Valgrind内存管理报告的生成,这里从这个模块设置开始: \begin{lstlisting}[style=styleCMake] # chapter-12/01-full-project/cmake/Memcheck.cmake (fragment) @@ -151,7 +151,7 @@ \subsubsubsection{12.5.2\hspace{0.2cm}准备Memcheck模块} endfunction() \end{lstlisting} -为了处理多个目标,REPORT\_PATH变量可置为存储特定于目标的报表的路径。然后在后续的命令中使用该变量。 +为了处理多个目标,REPORT\_PATH变量可置为存储特定于目标的报表的路径,并在后续的命令中使用该变量。 生成Memcheck报告可以通过以下命令实现(Debug构建类型中可以工作得更好): @@ -160,7 +160,7 @@ \subsubsubsection{12.5.2\hspace{0.2cm}准备Memcheck模块} cmake --build -t memcheck-calc_console_test \end{tcblisting} -这些都是Testing模块使用的所有模块,来看看这是如何使用的。 +这些都是Testing模块使用的所有模块,来看看这如何使用。 \subsubsubsection{12.5.3\hspace{0.2cm}应用测试场景} @@ -177,7 +177,7 @@ \subsubsubsection{12.5.3\hspace{0.2cm}应用测试场景} 需要对这些目标调用AddTests()。 \item -测软件(SUT)需要启用覆盖收集。 +测试软件(SUT)需要启用覆盖收集。 \item 收集的覆盖率应该在构建之间进行清理,以避免段错误。 @@ -205,7 +205,7 @@ \subsubsubsection{12.5.3\hspace{0.2cm}应用测试场景} EnableCoverage(calc_console_static) \end{lstlisting} -简单起见,将提供尽可能简单的单元测试。一个文件将覆盖这个库: +简单起见,可以提供尽可能简单的单元测试。一个文件将覆盖这个库: \begin{lstlisting}[style=styleCXX] // chapter-12/01-full-project/test/calc/calc_test.cpp @@ -221,7 +221,7 @@ \subsubsubsection{12.5.3\hspace{0.2cm}应用测试场景} } \end{lstlisting} -我们将有第二个文件来测试业务代码。为此,将使用FXTUI库。同样,并不期望您能够理解这段源代码的所有细节。本章提供测试清单只是为了项目的完整性: +我们将有第二个文件来测试业务代码。为此,将使用FXTUI库。同样,并不期望您能够理解这段源码的所有细节。本章提供测试清单只是为了项目的完整性: \begin{lstlisting}[style=styleCXX] // chapter-12/01-full-project/test/calc_console/tui_test.cpp @@ -244,7 +244,7 @@ \subsubsubsection{12.5.3\hspace{0.2cm}应用测试场景} 这段测试代码只是将默认状态下的文本UI呈现给静态屏幕对象,然后将其存储在字符串中。为了让测试通过,输出需要包含一个带有默认和的子字符串。 -现在,需要完成剩下的步骤:在创建测试目标并准备好它们的源代码之后,使用Testing模块中的AddTests()函数将它们注册到CTest中了。 +现在,需要完成剩下的步骤:创建测试目标并准备好源码之后,使用Testing模块中的AddTests()函数将其注册到CTest中。 我们对库这样做: @@ -266,13 +266,13 @@ \subsubsubsection{12.5.3\hspace{0.2cm}应用测试场景} EnableCoverage(calc_console_static) \end{lstlisting} -随后,SUT使用EnableCoverage()启用覆盖检测。注意,在库的情况下,必须向对象库添加工具,而不是静态库。这是因为-{}-coverage标志必须添加到编译步骤中,这是在构建calc\_obj时发生的。不过,我们不能在这里添加对覆盖文件的清理,因为CMake要求在与目标定义相同的目录中使用add\_custom\_command钩子。 +随后,SUT使用EnableCoverage()启用覆盖检测。注意,在库的情况下,必须向对象库添加工具,而不是静态库。这是因为-{}-coverage标志必须添加到编译步骤中,这是在构建calc\_obj时发生的。不过,不能在这里添加对覆盖文件的清理,因为CMake要求在与目标定义相同的目录中使用add\_custom\_command钩子。 -这将我们带回到之前没有完成的src/calc和src/calc\_console列表文件。需要添加CleanCoverage(calc\_static)和CleanCoverage(calc\_console\_static)(必须首先包含Coverage模块)。还需要向这些文件添加什么?说明启用静态分析! +这将我们带回到之前没有完成的src/calc和src/calc\_console列表文件。需要添加CleanCoverage(calc\_static)和CleanCoverage(calc\_console\_static)(必须首先包含Coverage模块)。还需要向这些文件添加什么?启用静态分析! \subsubsubsection{12.5.4\hspace{0.2cm}添加静态分析工具} -我们将业务代码列表文件的延续推迟到现在,以便能够在适当的上下文中讨论添加的模块。可以在库列表文件中添加CleanCoverage函数调用和其他一些东西: +我们将业务代码列表文件的延续推迟到现在,以便能够在适当的上下文中讨论添加的模块。可以在库列表文件中添加CleanCoverage函数和其他东西: \begin{lstlisting}[style=styleCMake] # chapter-12/01-full-project/src/calc/CMakeLists.txt (continued) @@ -287,7 +287,7 @@ \subsubsubsection{12.5.4\hspace{0.2cm}添加静态分析工具} # ... documentation generation \end{lstlisting} -我们还可以将它们添加到可执行文件中: +还可以将它们添加到可执行文件中: \begin{lstlisting}[style=styleCMake] # chapter-12/01-full-project/src/calc_console/CMakeLists.cmake (continued) @@ -341,11 +341,11 @@ \subsubsubsection{12.5.4\hspace{0.2cm}添加静态分析工具} endfunction() \end{lstlisting} -这既简单又方便,可能会看到一些类似于Clang-Tidy模块(第9章)的地方。这就是CMake的优势——许多概念以相同的方式工作。注意传递给cppcheck的参数: +这既简单又方便,会看到一些类似于Clang-Tidy模块(第9章)的地方。这就是CMake的优势——许多概念以相同的方式工作。注意传递给cppcheck的参数: \begin{itemize} \item --{}-enable=warning – 指定我们希望获得警告消息,可以启用其他检查——更多详细信息请参阅Cppcheck手册(链接可在扩展阅读部分找到)。 +-{}-enable=warning – 指定想要获得警告消息,可以启用其他检查——更多详细信息请参阅Cppcheck手册(链接可在扩展阅读部分找到)。 \item -{}-error-exitcode=10 – 这指定当cppcheck检测到问题时,希望获得错误代码。这可以是从1到255的任何数字(0表示成功),尽管有些数字可以由系统保留。 @@ -353,7 +353,7 @@ \subsubsubsection{12.5.4\hspace{0.2cm}添加静态分析工具} 使用非常方便——使用AddCppCheck将通知CMake需要在指定的目标上自动运行检查。 -实际上已经在src和test子目录中创建了所有文件。现在,可以构建我们的解决方案并,对其进行全面测试。现在终于到了进行安装和打包的时候了。 +实际上已经在src和test子目录中创建了所有文件。现在,可以构建我们的解决方案并,对其进行全面测试。现在到了进行安装和打包的时候了。 diff --git a/content/3/chapter12/6.tex b/content/3/chapter12/6.tex index b101a7a..f77c378 100644 --- a/content/3/chapter12/6.tex +++ b/content/3/chapter12/6.tex @@ -6,7 +6,7 @@ 图12.6 配置安装和打包的文件 \end{center} -这里只需要文件——大部分工作已经在前面的小节中完成了。顶层的列表文件包括一个CMake模块,它将处理这个过程: +这里只需要文件——大部分工作已经在前面的小节中完成了。顶层的列表文件包括一个CMake模块,将处理这个过程: \begin{lstlisting}[style=styleCMake] # chapter-12/01-full-project/CMakeLists.txt (fragment) @@ -27,7 +27,7 @@ 包定义配置文件将只引入库目标,因为潜在的使用项目不会依赖于可执行文件。 -配置安装步骤之后,将继续进行CPack配置。Install模块的高级概述如下: +配置安装步骤之后,将继续进行CPack配置。Install模块的概述如下: \begin{lstlisting}[style=styleCMake] # chapter-12/01-full-project/cmake/Install.cmake (overview) @@ -38,11 +38,11 @@ # Configuration of CPack \end{lstlisting} -一切都计划好了,所以是时候为库编写一个安装模块了。 +一切都计划好了,所以是时候为库编写安装模块了。 \subsubsubsection{12.6.1\hspace{0.2cm}库的安装} -安装库最好从配置逻辑目标,并为其工件指定目的地开始。为了避免手动提供路径,将使用GNUInstallDirs模块提供的默认值。为了模块化,我们将把构件分组到组件中。默认安装将安装所有文件,可以选择只安装运行时组件,而跳过开发构件: +安装库最好从配置逻辑目标,并为其工件指定目的地开始。为了避免手动提供路径,将使用GNUInstallDirs模块提供的默认值。为了模块化,将把构件分组到组件中。默认安装将安装所有文件,可以选择只安装运行时组件,而跳过开发构件: \begin{lstlisting}[style=styleCMake] # chapter-12/01-full-project/cmake/Install.cmake (fragment) @@ -59,7 +59,7 @@ \subsubsubsection{12.6.1\hspace{0.2cm}库的安装} ) \end{lstlisting} -安装过程中,我们想用ldconfig注册我们复制的动态库: +安装过程中,我们想用ldconfig注册复制的动态库: \begin{lstlisting}[style=styleCMake] # chapter-12/01-full-project/cmake/Install.cmake (continued) @@ -71,7 +71,7 @@ \subsubsubsection{12.6.1\hspace{0.2cm}库的安装} endif() \end{lstlisting} -准备好这些步骤后,就可以通过将库包装在一个可重用的CMake包中,使它对其他CMake项目可见。需要生成并安装目标导出文件和包含它的配置文件: +准备好这些步骤后,就可以通过将库包装在可重用的CMake包中,使它对其他CMake项目可见。需要生成并安装目标导出文件和包含它的配置文件: \begin{lstlisting}[style=styleCMake] # chapter-12/01-full-project/cmake/Install.cmake (continued) @@ -109,11 +109,11 @@ \subsubsubsection{12.6.2\hspace{0.2cm}可执行文件的安装} ) \end{lstlisting} -完成了!让我们转到配置的最后一部分——打包。 +完成了!现在来到了配置的最后一步——打包。 \subsubsubsection{12.6.3\hspace{0.2cm}使用CPack打包} -这时,就可以随心所欲地配置大量受支持的包类型。然而,对于这个项目,基本配置就足够了: +这时,就可以随心所欲地配置受支持的包类型。然而,对于这个项目,基本配置就足够了: \begin{lstlisting}[style=styleCMake] # chapter-12/01-full-project/cmake/Install.cmake (continued) diff --git a/content/3/chapter12/7.tex b/content/3/chapter12/7.tex index bbbd3ff..a11544f 100644 --- a/content/3/chapter12/7.tex +++ b/content/3/chapter12/7.tex @@ -9,7 +9,7 @@ 一般文档(所有其他非技术文档) \end{itemize} -正如我们在第10章中看到的,使用Doxygen可以使用CMake自动生成很多技术文档。 +正如在第10章中看到的,使用Doxygen可以使用CMake自动生成很多技术文档。 \subsubsubsection{12.7.1\hspace{0.2cm}自动生成文档} @@ -22,7 +22,7 @@ \subsubsubsection{12.7.1\hspace{0.2cm}自动生成文档} 图12.7 用于生成文档的文件 \end{center} -为了为我们的目标生成文档,将创建另一个CMake实用程序模块Doxygen。这里可以使用Doxygen查找模块,并下载Doxygen的-awesome-css主题: +我们的生成文档目标,将创建另一个CMake实用程序模块Doxygen。这里可以使用Doxygen查找模块,并下载Doxygen的-awesome-css主题: \begin{lstlisting}[style=styleCMake] # chapter-12/01-full-project/cmake/Doxygen.cmake (fragment) @@ -88,7 +88,7 @@ \subsubsubsection{12.7.1\hspace{0.2cm}自动生成文档} 项目中添加了两个新目标: doxygen-calc和dooxygen-calc\_console,并且可以按需生成技术文档。 -还需要提供其他什么文件么? +还需要提供其他文件么? \subsubsubsection{12.7.2\hspace{0.2cm}非技术性文件} @@ -99,7 +99,7 @@ \subsubsubsection{12.7.2\hspace{0.2cm}非技术性文件} README – 项目概述 \item -LICENSE – 指定项目的法律条款 +LICENSE – 指定项目的软件许可证 \end{itemize} 也可以考虑添加以下内容: @@ -112,13 +112,13 @@ \subsubsubsection{12.7.2\hspace{0.2cm}非技术性文件} CHANGELOG – 列出在不同版本中发生的重要更改 \item -AUTHORS – 若项目有多个贡献者,则包含名单和联系信息 +AUTHORS – 若项目有多个贡献者,则包含名单和联系方式 \item BUGS – 告知已知的错误,并指导如何报告新错误 \end{itemize} -当涉及到这些文件时,CMake本身并没有发挥声明作用——没有自动的行为或脚本可以使用。然而,这些文件是C++项目的重要组成部分,为了完整性,应该将其涵盖。作为参考,这里将提供一个最小的示例文件集,从一个简短的README文件开始: +当涉及到这些文件时,CMake本身并没有发挥声明作用——没有自动的行为或脚本可以使用这些文件是C++项目的重要组成部分,为了完整性应该将其涵盖。作为参考,这里将提供一个最小的示例文件集,从一个简短的README文件开始: \begin{lstlisting}[style=stylePython] # chapter-12/01-full-project/README.md @@ -169,9 +169,9 @@ \subsubsubsection{12.7.2\hspace{0.2cm}非技术性文件} cmake --build -t doxygen-calc_console \end{lstlisting} -这个文件有点长,但涵盖了最重要的需求、步骤和命令,可以很好地满足我们的需求。 +这个文件有点长,但涵盖了最重要的需求、步骤和命令,可以很好地满足需求。 -LICENSE文件有点棘手,因为它需要版权法方面的一些专业知识(或其他)。我们不需要自己编写所有的条款,而是可以像许多其他项目一样使用现成的软件许可。对于这个项目,我们将使用MIT许可证。根据具体项目的需要你可能想要选择其他的东西——查看扩展阅读部分,以获得一些有用的参考: +LICENSE文件有点棘手,因为需要版权法方面的一些专业知识(或其他)。我们不需要自己编写所有的条款,而是可以像许多其他项目一样使用现成的软件许可。对于这个项目,将使用MIT许可。根据具体项目的需要,可能想要选择其他的东西——查看扩展阅读部分,以获得一些有用的参考: \begin{lstlisting}[style=stylePython] # chapter-12/01-full-project/LICENSE @@ -200,7 +200,7 @@ \subsubsubsection{12.7.2\hspace{0.2cm}非技术性文件} OTHER DEALINGS IN THE SOFTWARE. \end{lstlisting} -最后,是CHANGELOG,最好跟踪文件中的更改,以便使用项目的开发人员可以轻松地找到支持所需特性的版本。例如,在0.8.2版本中向库添加了乘法特性,这样说可能会很有用。像下面这样简单的方法已经很有帮助了: +最后是CHANGELOG,最好跟踪文件中的更改,以便使用项目的开发人员可以轻松地找到支持所需特性的版本。例如,在0.8.2版本中向库添加了乘法特性,这样说可能会很有用。像下面这样简单的方法已经很有帮助了: \begin{lstlisting}[style=stylePython] # chapter-12/01-full-project/CHANGELOG @@ -211,7 +211,7 @@ \subsubsubsection{12.7.2\hspace{0.2cm}非技术性文件} 0.2.0 Basic Calc library with Sum function \end{lstlisting} -我们的项目现在已经完成了——可以构建它、测试它、生成包、将所有源代码上传到存储库,并发布工件。当然,若这可以自动发生,也许可以使用CI/CD流水,那就更容易了。但那是另一本书所要做的事情了。 +我们的项目现在已经完成了——可以构建、测试、生成包,将所有源代码上传到存储库,并发布工件。当然,若这可以自动发生,也可以使用CI/CD流水,这就更容易了。但那是另一本书所要做的事情了。 diff --git a/content/3/chapter12/8.tex b/content/3/chapter12/8.tex index bc6ade6..557e94a 100644 --- a/content/3/chapter12/8.tex +++ b/content/3/chapter12/8.tex @@ -1,14 +1,14 @@ 本章结束了我们通过CMake的漫长旅程。现在您完全理解了CMake的目标是解决什么问题,以及自动化这些解决方案需要哪些步骤。 -前三章中,探索了所有的基础知识:什么是CMake,用户如何利用它来激活原始源代码,CMake的关键组件是什么,以及不同的项目文件有什么目的。我们解释了CMake的语法:注释、命令调用、参数、变量和控制结构。我们已经发现了模块和子项目是如何工作的,正确的项目结构是什么,以及如何使用各种平台和工具链。 +前三章中,探索了所有的基础知识:什么是CMake,用户如何利用它来激活原始源代码,CMake的关键组件是什么,以及不同的项目文件有什么目的。我们解释了CMake的语法:注释、命令调用、参数、变量和控制结构。了解模块和子项目是如何工作的,正确的项目结构是什么,以及如何使用各种平台和工具链。 -本书的第二部分教我们如何使用CMake进行构建:如何使用目标、定制命令、构建类型和生成器表达式。我们深入研究了编译的技术细节,以及预处理器和优化器的配置,讨论了链接并介绍了不同的库类型。然后,研究了CMake如何使用FetchContent和ExternalProject模块帮助管理项目的依赖性,还研究了Git子模块作为可能的替代方案。最重要的是,研究了如何使用find\_package()和FindPkgConfig查找已安装的包。若这些还不够,可以编写自己的查找模块。 +本书的第二部分教我们如何使用CMake进行构建:如何使用目标、定制命令、构建类型和生成器表达式。我们深入研究了编译的技术细节,以及预处理器和优化器的配置,讨论了链接并介绍了不同的库类型。然后,研究了CMake如何使用FetchContent和ExternalProject模块帮助管理项目的依赖性,还研究了Git子模块作为可能的替代方案,研究了如何使用find\_package()和FindPkgConfig查找已安装的包。若这些还不够,可以编写自己的查找模块。 -最后一部分告诉我们如何进行自动化测试、分析、文档编制、安装和打包。我们研究了CTest和测试框架:Catch2、GoogleTest和GoogleMock。报道也包括在内。第9章,程序分析工具,了解了不同的分析工具:格式化器和静态检查器(Clang-Tidy、Cppcheck等),并解释了如何从Valgrind套件中添加Memcheck内存分析器。接下来,简要描述了如何使用Doxygen生成文档以及如何使文档看起来更美观。最后,演示了如何在系统上安装项目,创建可重用的CMake包,以及配置和使用CPack生成二进制包。 +最后一部分告诉我们如何进行自动化测试、分析、文档编制、安装和打包。我们研究了CTest和测试框架:Catch2、GoogleTest和GoogleMock。报告也包括在内。第9章,程序分析工具,了解了不同的分析工具:格式化器和静态检查器(Clang-Tidy、Cppcheck等),并解释了如何从Valgrind套件中添加Memcheck内存分析器,这里简要描述了如何使用Doxygen生成文档,以及如何使文档看起来更美观。最后,演示了如何在系统上安装项目,创建可重用的CMake包,以及配置和使用CPack生成二进制包。 最后一章使用了所有这些知识来展示一个完全专业的项目。 -\textit{恭喜你完成了这本书。我们介绍了开发、测试和打包高质量C++软件所需的所有内容。从这里取得进步的最好方法是将您所学到的应用到实践中,从而创建更多优秀的软件。好运!} +\textit{恭喜你阅读完了这本书。我们介绍了开发、测试和打包高质量C++软件所需的所有内容。从这里取得进步的最好方法是将所学到的应用到实践中,从而创建更多优秀的软件。祝诸君好运!} R. diff --git a/content/Appendix/0.tex b/content/Appendix/0.tex index 31bbbc5..769d882 100644 --- a/content/Appendix/0.tex +++ b/content/Appendix/0.tex @@ -1,6 +1,6 @@ 每种语言都有实用命令,在各种场合都会派上用场。CMake在这方面也没有什么不同:它为简单的算术、位操作、字符串操作,以及对列表和文件的操作提供了工具。有趣的是,需要它们的情况相对较少(多亏了多年来编写的所有增强和模块),但在更自动化的项目中仍然需要。 -因此,本附录简要总结了各种命令及其多种模式。将此作为一个方便的离线参考或官方文档的简化版本。如果需要更多信息,请访问提供的链接。 +因此,本附录简要总结了各种命令及其多种模式。将此作为一个方便的离线参考或官方文档的简化版本。若需要更多信息,请访问提供的链接。 \begin{itemize} \item diff --git a/content/Appendix/1.tex b/content/Appendix/1.tex index 88485dd..71fa998 100644 --- a/content/Appendix/1.tex +++ b/content/Appendix/1.tex @@ -2,7 +2,7 @@ 完整的细节可以在在线文档中找到: \url{https://cmake.org/cmake/ help/latest/command/string.html}。 -接受参数的String()模式将接受多个值,并在执行命令前将它们连接起来: +接受参数的String()模式将接受多个值,并在执行命令前将其连接起来: \begin{lstlisting}[style=styleCMake] string(PREPEND myVariable "a" "b" "c") @@ -24,7 +24,7 @@ \begin{itemize} \item -string(FIND [REVERSE]) 在字符串中搜索,并将找到的位置作为整数写入变量。若使用REVERSE标志,它将从字符串的末尾搜索到开头。这只适用于ASCII字符串(不提供多字节支持)。 +string(FIND [REVERSE]) 在字符串中搜索,并将找到的位置作为整数写入变量。若使用REVERSE标志,将从字符串的末尾搜索到开头。这只适用于ASCII字符串(不提供多字节支持)。 \item string(REPLACE ) 用替换的所有出现,并存储在变量中。 @@ -36,7 +36,7 @@ string(REGEX MATCHALL ) 用匹配的所有出现,并将它们作为逗号分隔的列表存储在变量中。 \item -string(REGEX REPLACE ) 用表达式替换的所有出现,并将它们存储在变量中。 +string(REGEX REPLACE ) 用表达式替换的所有出现,并存储在变量中。 \end{itemize} 正则表达式操作遵循标准库标头中定义的C++语法。可以使用捕获组添加匹配表达式与数字占位符:\verb|\|\verb|\|1,\verb|\|\verb|\|2…(需要双反斜杠,以便正确解析参数)。 @@ -58,7 +58,7 @@ string(CONCAT ) 连接所有提供的字符串并将它们存储在变量中。 \item -string(JOIN ) 将所有提供的字符串与值交错,并将它们作为串联的字符串存储在变量中(不要对列表变量使用此模式)。 +string(JOIN ) 将所有提供的字符串与值交错,并将其作为串联的字符串存储在变量中(不要对列表变量使用此模式)。 \item string(TOLOWER ) 将转换为小写并将其存储在变量中。 @@ -90,7 +90,7 @@ string(COMPARE ) \end{lstlisting} -参数是以下参数之一:LESS,GREATER,EQUAL,NOTEQUAL,LESS\_EQUAL或GREATER\_EQUAL。它将用于比较,结果(true或false)将存储在变量中。 +参数是以下参数之一:LESS,GREATER,EQUAL,NOTEQUAL,LESS\_EQUAL或GREATER\_EQUAL。将用于比较,结果(true或false)将存储在变量中。 \hspace*{\fill} \\ %插入空行 \noindent @@ -102,7 +102,7 @@ string( ) \end{lstlisting} -它哈希,并将结果存储在变量中。支持以下算法: +哈希有两个输入,并将结果存储在变量中。支持以下算法: \begin{itemize} \item @@ -197,7 +197,7 @@ SET ... 使用路径或字符串中返回上升到一个或多个元素的结果。 \item -EQUAL 计算是否相等。 +EQUAL 计算是否相等。 \end{itemize} diff --git a/content/Appendix/2.tex b/content/Appendix/2.tex index c25901f..b2296ba 100644 --- a/content/Appendix/2.tex +++ b/content/Appendix/2.tex @@ -73,7 +73,7 @@ 默认情况下,该动作应用于所有元素,但可以通过添加来限制效果。若提供了OUTPUT\_VARIABLE关键字,提供的列表将发生变化(就地更改),结果将存储在变量中。 -以下选择器可用:AT ,FOR [],以及REGEX 。操作包括APPEND , PREPEND ,TOLOWER,TOUPPER,STRIP,GENEX\_STRIP和REPLACE 。工作原理与具有相同名称的string()模式完全相同。 +以下选择器可用:AT ,FOR [],以及REGEX 。操作包括APPEND ,PREPEND ,TOLOWER,TOUPPER,STRIP,GENEX\_STRIP和REPLACE 。工作原理与具有相同名称的string()模式相同。 \end{itemize} diff --git a/content/Appendix/3.tex b/content/Appendix/3.tex index 8ff7d4c..919ca25 100644 --- a/content/Appendix/3.tex +++ b/content/Appendix/3.tex @@ -12,7 +12,7 @@ \begin{itemize} \item -file(READ [OFFSET ] [LIMIT ] [HEX]) 从读取文件到变量。读取可选地从偏移量开始,并遵循字节的可选限制。>HEX标志指定输出应该转换为十六进制表示。 +file(READ [OFFSET ] [LIMIT ] [HEX]) 从读取文件到变量。读取可选地从偏移量开始,并遵循字节的可选限制。HEX标志指定输出应该转换为十六进制表示。 \item file(STRINGS ) 从处的文件读取字符串到变量。 @@ -94,7 +94,7 @@ \begin{itemize} \item file(REAL\_PATH [BASE\_DIRECTORY ]) 从相对路径计算绝对路径并将其存储在变量中。可选地接受 -基目录。它从CMake 3.19开始就可以使用了。 +基目录。从CMake 3.19开始可用。 \item file(RELATIVE\_PATH ) 计算相对于路径,并将其存储在变量中。 @@ -131,7 +131,7 @@ [TIMEOUT ]) \end{lstlisting} -该锁可以选择作用域为FUNCTION、FILE或PROCESS,并以的超时进行限制。要释放锁,提供release关键字,结果将存储在变量中。 +该锁可以选择作用域为FUNCTION、FILE或PROCESS,并以的超时进行限制。要释放锁,需要RELEASE关键字,结果将存储在变量中。 \hspace*{\fill} \\ %插入空行 \noindent @@ -146,7 +146,7 @@ [MTIME ] [VERBOSE]) \end{lstlisting} -它在路径上创建一个存档文件,其中包含支持的格式之一的文件:7zip、gnutar、pax、paxr、raw或zip (paxr是默认格式)。如果所选格式支持压缩级别,则可以将其提供为一个单位数整数0-9,其中0为默认值。 +它在路径上创建一个存档文件,其中包含支持的格式之一的文件:7zip、gnutar、pax、paxr、raw或zip (paxr是默认格式)。若所选格式支持压缩级别,则可以将其提供为一个单位数整数0-9,其中0为默认值。 提取模式具有以下签名: @@ -155,7 +155,7 @@ [PATTERNS ...] [LIST_ONLY] [VERBOSE]) \end{lstlisting} -它将匹配可选值的文件从提取到目标。如果提供了LIST\_ONLY关键字,则不会提取文件,而是只列出文件。 +它将匹配可选值的文件从提取到目标。若有LIST\_ONLY关键字,则不会提取文件,而是只列出文件。 diff --git a/content/Appendix/4.tex b/content/Appendix/4.tex index 285d237..310050a 100644 --- a/content/Appendix/4.tex +++ b/content/Appendix/4.tex @@ -2,13 +2,13 @@ \url{https://cmake.org/cmake/help/latest/command/math.html} -要计算一个数学表达式并将其作为可选<格式>(十六进制或十进制)的字符串存储在变量中,请使用以下签名: +要计算一个数学表达式并将其作为可选(十六进制或十进制)的字符串存储在变量中,请使用以下签名: \begin{lstlisting}[style=styleCMake] math(EXPR "" [OUTPUT_FORMAT ]) \end{lstlisting} -值是一个字符串,它支持C代码中出现的操作符(它们在这里有相同的含义): +值是一个字符串,支持C代码中出现的操作符(它们在这里具有相同含义): \begin{itemize} \item @@ -21,7 +21,7 @@ 括号 (...) \end{itemize} -常量值可以用十进制或十六进制格式提供。 +常量值可以以十进制或十六进制格式提供。