.cpp | .c | .mm)编译为可执行文件、目标文件或动态库main.cpp util.cpp util.h ,此时想要进行一次性编译所有源文件静态库和动态库的区分吧
预处理(Preprocessing)
实现的是处理源代码中的预处理指令,类似于:#include #define #ifdef,展开头文件,替换宏,删除注释,生成纯 cpp 代码
输入 .cpp 是基本的源代码文件吧
输出:预处理后的源代码文件吧,一般用的是 .i 结尾的呢
执行的命令为:clang++ -E main.cpp -o main.i -E表示的是只执行预处理即可,-o 执行输出文件
编译(Compilation)
将预处理后的代码(.i)翻译成汇编语言(与 CPU 架构相关的低级指令)
输入:预处理后的 .i 文件
输出:汇编代码文件 .s 为后缀
clang++ -S main.i -o main.s
汇编(Assembly)
将汇编代码(.s)翻译成机器码(二进制指令),生成目标文件
clang++ -c main.s -o main.o
链接(Linking)
将多个目标文件(.o)和所需的库文件(静态库 / 动态库)合并,解决函数调用、变量引用的地址关联,最终生成可执行文件
clang++ main.o util.o -o myprogram
使用背景:当代码需要被多个程序复用(如工具函数、算法库)时,通常会打包为
静态库或动态库,两者的核心区别在于链接时机和依赖方式
后缀区分:
liunx/macOS 是 .a
windows 是 .lib
特点是:
链接时被 “嵌入” 可执行文件,生成的程序不依赖外部库,可独立运行;
缺点:可执行文件体积大,若静态库更新,所有依赖它的程序都需重新编译。
独立的二进制文件,编译时仅记录 “引用关系”,程序运行时才被加载到内存中,可被多个程序共享
后缀区分
linux .so
macOS .dylib
windows .dll
特点是:
不嵌入可执行文件,节省磁盘空间和内存(多个程序共享同一份库);
库更新后,依赖它的程序无需重新编译(只需替换动态库文件);
缺点:程序运行时必须依赖动态库存在,否则会报错(“找不到库文件”)。