Skip to content
This repository has been archived by the owner on Jul 3, 2023. It is now read-only.

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
xiaoweiChen committed Nov 16, 2022
1 parent af22fce commit 9c1526f
Show file tree
Hide file tree
Showing 13 changed files with 122 additions and 122 deletions.
8 changes: 4 additions & 4 deletions content/3/chapter12/0.tex
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@

我们收集了建造专业项目所需的所有知识,学习了结构化、构建、依赖管理、测试、分析、安装和打包。是时候通过创建一个连贯、专业的项目来将这些获得的技能付诸实践了。
我们收集了建造专业项目所需的所有知识,了解了结构化、构建、依赖管理、测试、分析、安装和打包。是时候通过创建一个连贯、专业的项目来将这些获得的技能付诸实践了。

重要的是要理解,即使是微不足道的程序也将受益于自动化的质量检查和简化的端到端流程,将原始代码转化为完整的解决方案。的确,这通常是一项相当大的投资,因为需要采取许多步骤来正确地准备一切——若试图将这些机制添加到已经存在的代码库中(通常,已经非常庞大和复杂),则需要采取更多步骤。
重要的是要理解,即使是微不足道的程序也可受益于自动化的质量检查和简化的端到端流程,将原始代码转化为完整的解决方案。这通常是一项相当大的投资,需要许多步骤来准备这一切——若试图将这些机制添加到现存在的代码库中(通常,已经非常庞大和复杂),则需要采取更多步骤。

这就是从一开始就使用CMake并将所有管道设置在前面的原因,不仅将更容易配置,更重要的是,也更有效地尽早进行,因为所有的质量控制和构建自动化无论如何都必须添加到长期项目中
这就是从一开始就使用CMake并在前面对所有流水进行设置的原因,不仅更容易配置,也能更有效地尽早进行测试,因为所有的质量控制和自动化构建都必须添加到长期项目中

这正是在本章要做的——将编写一个尽可能小而简单的新解决方案。只执行一个(几乎)功能——两个数字相加,限制业务代码的功能将让我们专注于项目的其他方面
这正是在本章要做的——编写一个尽可能小而简单的新解决方案。只执行一个(几乎)功能——两个数字相加,限制业务代码的功能可以让我们更专注于项目的其他方面

为了解决一个更复杂的问题,这个项目将构建一个库和一个可执行文件。该库将提供内部业务逻辑,也可以供其他项目作为CMake包使用。可执行文件将只针对最终用户,并将实现一个显示底层库功能的用户界面。

Expand Down
62 changes: 31 additions & 31 deletions content/3/chapter12/2.tex
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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章:}

提供了关于链接的信息(在任何项目中都很有用),其中大部分在默认情况下很有用。但是由于这个项目也提供了一个库,将显式地引用以下的一些构建说明:

Expand All @@ -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}

形成了一个清晰的计划之后,再来讨论如何从逻辑目标和目录结构两方面实际构建项目
形成了一个清晰的计划之后,再从逻辑目标和目录结构两方面讨论实际的构建项目



Expand Down
16 changes: 8 additions & 8 deletions content/3/chapter12/3.tex
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
图12.2 逻辑目标的结构
\end{center}

我们按照构建顺序来探索这个结构。首先,编译calc\_obj,这是一个对象库。我们确实在书中几次提到了对象库,但并没有把它们作为一个概念来介绍
我们按照构建顺序来探索这个结构。首先,编译calc\_obj,这是一个对象库。我们确实在书中几次提到了对象库,但并没有作为一个知识点来介绍

\subsubsubsection{12.3.1\hspace{0.2cm}对象库}

Expand All @@ -23,23 +23,23 @@ \subsubsubsection{12.3.1\hspace{0.2cm}对象库}
add_executable(... $<TARGET_OBJECTS:objlib> ...)
\end{lstlisting}

或者,可以使用target\_link\_libraries()将它们作为依赖项添加
或者,可以使用target\_link\_libraries()将其作为依赖项添加

Calc库中,对象库将有助于避免为库的静态和动态版本重复编译库源。只需要记住显式地使用POSITION\_INDEPENDENT\_CODE编译目标文件,因为这是动态库的需求。

解决了这些问题,回到这个项目的目标:calc\_obj将提供编译的目标文件,然后将用于calc\_static和calc\_shared库。它们之间的实际区别是什么?为什么要提供两个库?

\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运行。

现在知道需要建立什么目标,以及它们之间的关系。来看看如何用文件和目录来组织项目。

Expand Down Expand Up @@ -75,9 +75,9 @@ \subsubsubsection{12.3.3\hspace{0.2cm}目录结构}
\end{tabular}
\end{table}

最初,cmake目录比业务代码更繁忙,但随着项目功能的增长,这种情况将很快发生变化。启动一个清洁项目的努力是很重要的,但不要担心——很快就会得到回报。
最初,cmake目录比业务代码更多,但随着项目功能的增长,这种情况将很快发生变化。启动一个清洁项目的努力是很重要的,但不要担心——很快就会得到回报。

我们将浏览所有文件,详细了解它们的作用以及它们在项目中扮演的角色。这将分为四个步骤:构建、测试、安装和提供文档
我们将浏览所有文件,详细了解它们的作用以及它们在项目中扮演的角色。这将分为四个步骤:构建、测试、安装和生成文档



Expand Down
Loading

0 comments on commit 9c1526f

Please sign in to comment.