Logic
向着梦想进发

🥹学习c++从学习cmake开始(正在施工)

编译的时候发生了什么?

通常我们会用这样的命令来编译一个 cpp 文件:

我们教材告诉我们编译的过程是“预处理-编译-链接”。但是这显然难以让我们清楚理解这个问题。

就以最简单的 hello world 文件为例:

在这里 g++ 实际上是把 main.cpp 和 libstdc++ 做了链接。

使用 objdump -D a.out | less 查找 main 函数的位置:

我们发现主函数调用了 std::basic_ostream& operator<<(std::basic_ostream&, const char*); 这个函数,我们继续找这个函数的定义:

我们会发现他只是一个跳转。进一步的,我们使用 ldd 查看程序依赖库:

我们会发现 a.out 链接了 libstdc++.so。

单文件编译虽然方便,但是有缺点。当我们的项目变大的时候,会不断放大这个缺点。所以我需要多文件编译。我们可以通过 g++ -c hello.cpp -o hello.ohello.cpp 编译成中间文件,最后只需要链接这个 .o 文件即可。

但是这同样存在问题,当我们的文件依赖关系变多的情况下,我们不可能每一次都重写编译指令。这就有了 makefile,只需要写出文件的依赖关系即可。不过,makefile 不跨平台,而且编写的时候比较头疼,这就有了 cmake

什么是库(library)

考虑我们编写代码的过程,如果我们使用模块化编程的思想,那么我们会有一些头文件。最简单的方式就是 head-only。不过这也会导致一些问题,也就是说当我们的头文件过于庞大的时候,每一次我们都需要重新编译一遍程序。我们会发现 boost 库的编译很慢,就是这个原因(当然这是由于模板是不能分离头文件和源文件导致的,如果我们需要模板编程,那么我们必须在头文件中就有实现)。

所以,我们可以分离声明和定义。也就是说头文件只有声明的作用,让编译器自动去连接函数的声明。这样我们把源文件编译成库,就可以让多个文件使用。

库分为动态库与静态库。其中静态库会直接把代码插入可执行文件,而动态库则是在可执行文件中加入一个“插桩”函数,当程序执行到这里的时候则会将 .dll 文件中的函数加载到内存中。

(等待施工)

赞赏
本文作者: Logic
本文链接: https://i.needwe.top/cmake-cpp-learning/
本文采用 CC BY-NC-SA 4.0 Unported 协议进行许可
#
首页      coding      🥹学习c++从学习cmake开始(正在施工)

发表回复

textsms
account_circle
email

永恒幻想 Eternal Fanta5y

🥹学习c++从学习cmake开始(正在施工)
编译的时候发生了什么? 通常我们会用这样的命令来编译一个 cpp 文件: [crayon-673ed765341f6962888678/] 我们教材告诉我们编译的过程是“预处理-编译-链接”。但是这显然难以让…
扫描二维码继续阅读
2024-10-08