Linux学习笔记|GCC编译指令基础|静动态库|makefile
一、GCC 编译指令基础
- 基本编译命令
gcc -o code code.c
和gcc code.c -o code
:这两条命令功能相同,都是使用 GCC 编译器将code.c
源文件编译成名为code
的可执行文件。-o
选项用于指定输出文件名,选项位置在源文件前后不影响最终结果。
- 编译过程分步指令
- 预处理:
gcc -E code.c -o code.i
,该指令对code.c
进行预处理,生成code.i
文件,预处理主要处理源文件中的宏定义、头文件包含等。 - 编译:
gcc -S code.i -o code.s
,将预处理后的code.i
文件编译成汇编语言文件code.s
,此过程将高级语言转换为汇编语言。 - 汇编:
gcc -c code.s -o code.o
,把汇编语言文件code.s
汇编成目标文件code.o
,目标文件是机器语言代码,但还未进行链接。 - 链接:
gcc code.o -o code
,将目标文件code.o
与必要的库文件链接起来,生成最终可执行文件code
。
- 预处理:
- 编译选项及问题
-c
选项:gcc -c code.c
可生成目标文件code.o
,但此时code.o
不能直接执行,因为还缺少链接步骤,未解决外部符号引用等问题。- 权限问题:编译生成的可执行文件可能存在权限问题,如提示
not a dynamic executable
或you do not have execute permission for './code.o'
,需要通过chmod
命令赋予执行权限,如chmod +x code
。 - 链接库问题:如果程序依赖某些库,编译时可能需要指定库路径和库名。例如,链接动态库时,若提示找不到库文件,可通过
-L
选项指定库路径,-l
选项指定库名(如gcc code.c -L/path/to/lib -lmylib -o code
)。
二、静态链接与动态链接
- 库的分类与命名
- 静态库:在 Windows 下通常以
.lib
为后缀,在 Linux 下以.a
为后缀,命名一般为libXXX.a
。 - 动态库:Windows 下后缀为
.dll
,Linux 下后缀为.so
,命名形式如libXXX.so
。
- 静态库:在 Windows 下通常以
- 链接方式及特点
- 静态链接:使用
-static
选项,如gcc code.c -o myexe_static -static
。优点是可执行文件独立,不依赖外部库就能运行;缺点是文件体积大,若多个程序使用相同库,会在内存中存在多份库代码副本。 - 动态链接:默认链接方式,如
gcc code.c -o myexe
。优点是可执行文件体积小,多个程序可共享库的内存副本;缺点是运行时依赖库文件存在且版本正确,否则会出现找不到库或库版本不兼容问题 。
- 静态链接:使用
三、Makefile 基础
- 基本概念
make
是 Linux 系统内置命令,Makefile
是用户编写的文本文件,用于自动化构建和维护项目。
- 编写规则
- 目标、依赖关系和命令:一个简单的
Makefile
示例:myexe: code.cgcc -o myexe code.c
- 目标、依赖关系和命令:一个简单的
依赖关系+依赖方法 =等于我们要编译程序的目的
这里myexe
是目标,code.c
是依赖文件,gcc -o myexe code.c
是构建目标的命令。
- 自动推导:
Makefile
能自动推导一些常见命令,如对于myexe: code.c
,若不写具体命令,make
会尝试使用默认规则推导命令(类似于gcc -o myexe code.c
)。 - 清理规则:常添加
clean
目标用于清理生成的文件,如:
clean:rm -f myexe code.o
使用make clean
可执行清理操作。
3. 最佳实践
- 文件时间戳判断:
make
根据文件的修改时间戳判断是否需要重新构建目标。如果目标文件不存在,或目标文件的时间戳比其依赖文件旧,make
会执行相应命令重新构建。 - 多目标和复杂依赖处理:对于大型项目,
Makefile
可处理多个目标以及复杂的依赖关系,通过合理组织规则,提高项目构建效率。