本文介绍比入门级稍高的Makefile写法和静态库的生成及使用。
先看一个目录结构
lib // 库
plus.c
reduce.c
Makefile
include
plus.h
reduce.h
app // 主体程序
main.c // 很多开源代码都有一个或者多个main.c,而且里边往往实现了 main 函数。某想这可能是为了方便读者找到入口函数
Makefile
Make.defines // app和lib中的两个Makefile会依赖此文件
在这个实例中,我们会把plus.c reduce.c生成一个静态库,提供给main.c文件来使用。
某发现很多开源的代码目录下都有一个lib文件夹,里边存放的会是一些其它主程序可能用到的函数库。(说到开源,某知道一个网站http://www.oschina.net/非常不错,很多知名或不知名的源码都有,不是做广告哦。另外还有http://code.google.com,http://www.codeproject.com/等,你如果知道这些网站请忽略此广告)
此处,app中的main.c会用到lib中的plus.c,reduce.c中的函数。具体内容如下
// lib/plus.c int plus(int a, int b) { return a+b; }
// lib/reduce.c int reduce(int a, int b) { return a-b; }
// app/main.c #include <stdio.h> #include "plus.h" #include "reduce.h" int main(int argc, char** argv) { int a; int b; a = 10; b = 5; printf("a + b = %d\n", plus(a, b)); printf("a - b = %d\n", reduce(a, b)); return 0; }
Make.define内容如下
# write by jogger
CC = gcc
CFLAGS = -I../include -g -O2 -Wall
LIBS = ../libjogger.a
LIBJOGGER_NAME = ../libjogger.a
LIB_OBJS = plus.o reduce.o
CLEANFILES = core core.* *.core *.o *.out
由于main.c文件使用到了plus和reduce的功能,我们需要将plus.c reduce.c生成静态库。
先来看一下lib中的Makefile:
include ../Make.defines
all: ${LIB_OBJS}
ar rv ${LIBJOGGER_NAME} $?
clean:
rm -f ${CLEANFILES}
核心是ar命令,这个命令可是将源码生成静态库。LIB_OBJS,LIBJOGGER_NAME,CLEANFILES这三个宏就在Make.define中定义了。${LIB_OBJS}这个语法就表示LIB_OBJS的真实值。(小白学makefile之一已经讲过makefile的一些基本语法。)
然后就是很简单的在lib目录下执行 make命令,libjogger.a库就会生成并输出到上层目录中(与Make.define同级)。为什么会输出到上层目录?因为Make.define中LIBJOGGER_NAME = ../libjogger.a定义了它的输出目录是上级。为什么要输出到上层目录?这样app中(或者其它同级目录)的源文件比如main.c,只要包含了Make.define,就不需要关心libjogger.a存放在哪里了,并且不用再次定制路径。
再来看app中的Makefile:
include ../Make.defines
PROGS = main
all: ${PROGS}
main: main.o
${CC} ${CFLAGS} -o $@ main.o ${LIBS}
clean:
rm -f ${PROGS} ${CLEANFILES}
这个稍微有点点复杂。注意all字段是all=${PROGS}等价于all=main makefile会去寻找main目标并且编译。
执行命令相当于 gcc -I../include -g -O2 -Wall -o main main.o ../libjogger.a
所以make命令就能在当前目录生成一个可执行文件main,即目标文件。
执行 ./main产生如下输出:
$ ./main
a + b = 15
a - b = 5