1) make命令: 终端输入 main 或vim 命令输入:main
make 会调用 makefile文件进行编译连接构造程序。命令会依次搜索当前目录下名为makefile、Makefile、GNUmakefile的文件。建议采用Makefile为名字,目录下子目录或文件名首字母为小写,这样有利于查找。
make最常用的三个选项:
-k: 指定发现错误时仍然继续,发现所有未编译成功的源文件
-n: 输出执行步骤,而不真正执行
-f: 指定特定的makefile文件名
-jN; 同时执行N条命令,以缩短编译的时间,j是jobs的首字母
2) makefile的格式
makefile由一组的目标+依赖关系+规则组成,目标一般指可执行文件或.o目标文件,依赖关系定义目标与源文件的关系,规则定义了目标的创建方式,以下是基本的格式:
all : 目录1 目标2 ...
目标1:依赖
规则
目标2:依赖
规则
clean:
-rm *.o
install: 目标1
........
注意:规则一行必须以制表符开头
多目标下可以通过命令参数指定执行的目标,如 make clean 或 make install
可以通过gcc的-MM选项来产生依赖关系表,如 gcc -MM main.c hello.c 分别得到main.c hello.c 的依赖关系
3) makefile的特殊字符以及宏定义
makefile文件中的注释以#号开头,直到该行结束。一行代表一个命令,所以一行写不完时需要在行尾添加反斜杠 “\”如下:
@if [ -d $(dir) ]; \
then \
cp fi $(dir); \
fi
@表示执行这些规则之前不在标准输出上显示命令本身。另一常用的特殊字符 - 告诉命令忽略所有的错误,例如-rm
可以添加宏来增加灵活性或设置编译器的选项。语句为MACRONAME=value,引用为$(MACRONAME)或${MACRONAME}。常用的内置宏如下表:
$? 当前目标所依赖的文件列表中比当前目标文件还要新的文件
$@ 当前目标的名字
$< 当前依赖文件的名字
$* 当前依赖文件的名字,不包括后缀名 ($*.o)
4) 规则
make 自带了很多的内置规则,可以简化makefile文件的内容,甚至不需要写 makefile,如在main.c 里面写hello world,然后命令行输入make main就可以了编译完成了,也可以通过宏来改变默认行为如 make CC=gcc CFLAGS="-Wall -g" main。 可以通过make -p打印出所有内置规则,内容极其多。
后缀规则:根据不同的后缀名编译源文件
模式规则:自定义规则来编译某种源文件
示例1:.cpp文件编译成.o文件
.cpp.o:
$(CC) -xc++ $(CFLAGS) -I$(INCLUDE) -c $<
示例2:.c文件编译成.a文件 (库文件)
.c.a:
$(CC) $(CFLAGS) -c $<
$(AR) $(ARFLAGS) $@ $*.o
第一条规则编译所有的文件($<) 为.o文件
第二条规则将所有的.o文件($*.o)生成目标文件($@), $(AR)和$(ARFLAGS) 默认值分别为命令ar 和 选项rv
生成库文件的语法是lib(file.o),可以直接拿来用而不需要定义上面示例2的规则来生成,如 mylib.a: mylib.a(file1.o) mylib.a(file2.o)
5) 子目录
大型项目中往往需要分为多个子目录,每个子目录生成各自的函数库,再由多个函数库生成可执行文件,就像是VS一个解决方案下面有很多个项目。可以用两种方法来做这事。
第一种方法是在子目录里编写makefile文件
mylib.a
{ cd mylibdir; $(MAKE) }
注意:括号把两个命令放在一个shell里面处理
第二种方法是添加宏,改写后缀规则
.c.o:
$(CC) $(CFLAGS) -c $(@D)/$(<F) -o $(@D)/$(@F)
字母D和F分别代表目录和文件
用如下依赖和规则来更新库
mylib.a: mydir/2.o mydir/3.o
ar -rv mylib.a $?
注意某些函数对于gcc 需要指明选项才能编译过,如 vsnprintf需要 -std=c99
all: main
# which compiler
CC=gcc
# where are include files kept
INCLUDE=.
# options for debug
CFLAGS=-g -Wall -ansi
# options for release
#CFLAGS=-o -Wall -ansi
# local libraries
MYLIB=hello.a
main: main.o $(MYLIB)
$(CC) -o main main.o $(MYLIB)
main.o: main.c hello.h
$(CC) -I$(INCLUDE) $(CFLAGS) -c main.c
hello.o: hello.c hello.h
$(CC) -I$(INCLUDE) $(CFLAGS) -c hello.c
$(MYLIB): $(MYLIB)(hello.o)
# or use inner regular to bulid archive
# .c.a:
# $(CC) -I$(INCLUDE) $(CFLAGS) -c $<
# $(AR) $(ARFLAGS) $@ $*.o
# use "make clean" to execute this object
clean:
-rm main.o $(MYLIB)
-I 包含头文件目录
-L 包含库文件目录
-o 生成目标可执行文件
-c 编译文件,生成.o文件
以上知识基本能学会编写makefile文件,在实际中不断学习才是真理,更详细的可以参考《linux 程序设计》《跟我一起写makefile》
参考