在 Linux 环境下使用 make 工具能够比较容易的构建一个属于你自己的工程。在执行 make 之前,需要一个创建一个名为 makefile 的特殊文件,在 makefile 文件中描述了整个工程所有文件的编译顺序、编译规则。
make 命令不仅仅用于完成编译程序,当需要通过多个输入文件来生成输出文件时,都可以用它来完成。
当使用 make 工具进行编译时,以下几种文件在执行 make 时将会被编译(重新编译):
- 所有的源文件没有被编译过,则对各个 C 源文件进行编译并进行链接;
- 每一个在上次执行 make 之后修改过的 C 源代码文件在本次执行make 时将会被重新编译;
- 头文件在上一次执行 make 之后被修改。则所有包含此头文件的 C 源文件在本次执make 时将会被重新编译。
make 命令
make 最常用的 3 个参数:
-k : 让 make 命令在发现错误时仍继续执行。可以一次发现所有为编译成功的源文件。
-n : 让 make 命令输出将要执行的操作步骤,而不是真正执行。
-f filename : 用指定的文件作为 makefile 文件。
makefile 语法
makefile 文件由一系列依赖关系和规则组成。每个依赖关系由一个目标和一组该目标所依赖的源文件组成。
- 依赖关系:先写目标的名称,紧跟冒号,接着是空格或 Tab,最后是用空格或 Tab 隔开的源文件列表。
- 规则:必须以 Tab 开头,gcc 命令
例如目标文件 show,源文件 main.c、list.c、list.h,一个 makefile 文件如下:
show: main.o list.o #依赖关系,目标文件 show 依赖于 main.o 和 list.o
gcc -o show main.o list.o #规则,必须以 Tab 开头
main.o: main.c list.h
gcc -c main.c
list.o: list.c list.h
gcc -c list.c
当 make 执行到 [.o] 时,会自动把 [.c] 加入到依赖关系中。所以以上 makefile 可以简化如下:
objects=main.o list.o #指定变量 objects ,在需要使用这两个文件时,可以使用 $(objects)代替
show: $(objects)
gcc -o list $(objects)
main.o: list.h
gcc -c main.c
list.o: list.h
gcc -c list.c
makefile 文件中出现在命令之前的两个特殊字符:
- :告诉 make 忽略所有错误,例如删除一个文件,在 rm 命令前加一个减号。
@ :执行指令时不显示命令。
多个目标
增加一个 clean 选项删除不需要的目标文件,增加一个 install 选择将编译成功的程序安装到另一个目录。
#install to
INSTDIR=/usr/local/bin
show: main.o list.o #依赖关系,目标文件 show 依赖于 main.o 和 list.o
gcc -o show main.o list.o #规则,必须以 Tab 开头
main.o: main.c list.h
gcc -c main.c
list.o: list.c list.h
gcc -c list.c
clean:
-rm main.o list.o
install:show
@if [ -d $(INSTDIR) ]; then \
cp show $(INSTDIR) &&\
chmod a+x $(INSTDIR)/show && \
chmod og-w $(INSTDIR)/show && \
echo "install in $(INSTDIR)"; \
else \
echo "$(INSTDIR) doen not exist"; \
fi
上面在每行代码结尾加一个反斜杠 \,让所有的命令在逻辑上处于同一行。&& 在Bash shell 中的有介绍,表示前一个指令执行成功,才会执行后一个指令。
库文件连接
Linux下的大多数函数都默认将头文件放到 /usr/include/ 目录下,而库文件则放到 /usr/lib/ 目录下,但并不是所有的情况都是这样。GCC在编译时必须有自己的办法来查找所需要的头文件和库文件。
-I:指定第一个寻找头文件的目录
-L:指定第一个寻找库文件的目录
-l:表示在库文件目录中寻找指定的动态库文件
例如,如果在 /home/gf/include/ 目录下有编译时所需要的头文件,在 /home/gf/lib/ 目录下有连接时所需要的库文件。
gcc -I /home/gf/include -c test.c
gcc -L /home/gf/lib -o test test.o