Compile and Link

编译

  • 编译即将程序员所编写的源代码翻译为机器代码的过程
  • 编译永远都是以单个源文件为单位的,对单个源文件进行编译的结果是对应的目标文件(.o文件,是对二进制代码的一种封装,Linux下为elf格式,Windows下为pe格式),gcc -c xxx.c 即会编译出.o文件。在Linux下使用readelf -h xxx.o命令可以查看elf文件详细信息。
  • .o文件不可以直接执行,操作系统也不允许直接执行.o文件。因为编译的过程中每个源文件是单独进行的,单个文件中可能会调用未定义的函数。
  • 单个文件中只知道对调用其他文件中函数的声明,并不知道定义,编译结束后的相应函数跳转地址暂时会用0代替,等到链接的过程再进行修正。

链接

  • 静态链接
    • 将全部编译好的目标文件(连同一些库)一起链接成为一个可执行文件的过程,可执行文件便可在相应操作系统直接运行。gcc xxx.o xx.o -o xxx
    • 链接时,编译器会自动将之前暂时设置的函数跳转地址进行修正。
    • 静态链接最大的问题是生成的文件体积大、并且相当耗费内存资源。静态链接的构建过程很慢,但是只有单独的可执行文件运行时不会出现麻烦的依赖缺失问题。
  • 动态链接
    • 相对于静态链接,动态链接在现代软件中更常被使用。
    • 将一些通用的代码单独拿出来编译成动态链接库(Windows下.dll文件、Linux下.so文件),其他程序在运行时再将需要的动态链接库加载到内存。
    • gcc -shared add.c -o libadd.so可以将add.c文件构建为动态链接库,so指shared object。在构建其他程序时的命令格式为gcc test.c -l add -L. -o test(-l add省略了lib和.so,-L指定.so文件目录),但是Linux中必须将.so文件放入系统路径,否则运行中报错(linux默认只会去系统路径下搜索动态链接库)。
    • 动态链接可以节省空间,方便的更新软件(因为动态链接库是独立的,只需进行单独的替换),实现插件功能等。

构建工具

在大项目中,手动编译链接非常费力,使用构建工具可以帮助程序员简单的构建项目

  • Makefile
    • 一种自动化构建脚本,指定了编译、链接的过程命令;输出文件的命名;构建过程结束后删除的文件流程信息等,其核心是对项目依赖的管理。
    • make 项目名称命令会按makefile中的指令进行构建,并且make不会重复构建已存在的文件,会单独对更改的文件进行构建。