1 func1.c func1.h func2.c func2.h 被 main.c 和 debug.c 共同调用的makefile如何写?
-
CROSS_COMPILE = arm-none-linux-gnueabi-
-
CC = $(CROSS_COMPILE)gcc
-
RM = rm
-
-
EXES = main debug
-
SRCS = func1.c func2.c
-
OBJS = $(SRCS:.c=.o)
-
-
all:$(EXES)
-
-
main:main.o $(OBJS)
-
$(CC) -o $@ $^
-
-
debug:debug.o $(OBJS)
-
$(CC) -o $@ $^
-
-
clean:
-
$(RM) -rf *.o $(EXES)
-
-
%.o:%.c
-
$(CC) -o $@ -c $<
顺便提醒一下Makefile常识:当Makefile中有多个目标(target)时,若执行make指令时不指定执行哪一个target,则系统默认只执行第一个target。
1.1 $@ $^ $< 分别代表什么意思?
$@ 表示目标文件
$^ 表示所有的依赖文件
$< 表示第一个依赖文件
1.2 常用的makefile写法中
SRCS = func1.c func2.c
OBJS = $(SRCS:.c=.o)
或
OBJS = func1.o func2.o
SRCS = $(OBJS:.o=.c)
表示什么意思?
前者被makefile解释为:
SRCS = func1.c func2.c
OBJS = func1.o func2.o
后者被makefile解释为:
OBJS = func1.o func2.o
SRCS = func1.c func2.c
这下明白了吧。
2 若把func1.c func1.h func2.c func2.h作为动态链接库comm呢?
-
CROSS_COMPILE = arm-none-linux-gnueabi-
-
CC = $(CROSS_COMPILE)gcc
-
RM = rm
-
LD = ld
-
-
EXES = main debug
-
SRCS = func1.c func2.c
-
OBJS = $(SRCS:.c=.o)
-
LIBS = libcomm.so
-
-
all:$(LIBS) $(EXES)
-
-
main: main.o
-
$(CC) -o $@ $^ -L./ -lcomm
-
-
debug: debug.o
-
$(CC) -o $@ $^ -L./ -lcomm
-
-
$(LIBS):$(OBJS)
-
$(CC) -shared -o $@ $^
-
-
clean:
-
$(RM) -rf *.o $(EXES) $(LIBS)
-
-
main.o:main.c
-
$(CC) -o $@ -c $^
-
-
debug.o:debug.c
-
$(CC) -o $@ -c $^
-
-
$(OBJS):%.o:%.c
-
$(CC) -fPIC -o $@ -c $<
2.1 必须先调用$(LIBS)规则生成libcomm.so。否则,报错:找不到libcomm.so。
2.2 必须要使用“makefile静态模式”。否则,报错:
gcc -o func1.o -c func1.c func2.c
gcc: 致命错误: 当有多个文件时不能在已指定 -c 或 -S 的情况下指定 -o 编译中断。
注意若把静态模式,即上面的
$(OBJS):%.o:%.c
$(CC) -fPIC -o $@ -c $<
改为
$(OBJS):%.o:%.c
$(CC) -fPIC -o $@ -c $^
效果是一样的。
但是,改写为
$(OBJS):$(SRCS)
$(CC) -fPIC -o $@ -c $^
或者
$(OBJS):$(SRCS)
$(CC) -fPIC -o $@ -c $<
都是不行的。
这是因为:
静态模式表示依次对$(OBJS)下的.c编译为.o。是依次,不是一次,所以$<改为$^效果是一样的。
2.3 执行前必须将生成的libcomm.so拷贝到/usr/lib/下。否则,报错:./main: error while loading shared libraries: libcomm.so: cannot open shared object file: No such file or directory。
其实,“找不到所依赖的动态链接库文件”是个非常常见的问题,解决方法有很多种,参考我的另一篇博文:export。具体用什么方法,视情况而定,如上拷贝比较方便,但有时无root权限,就只能用export LD_LIBRARY_PATH的方法了。
事实上,执行main或debug前,使用ldd main或ldd debug就可以测试是否正确动态链接,而不一定必须通过执行来发现找不到动态链接库文件。
3 小结
%.o:%.c 和 makefile静态模式:$(OBJS):%.o:%.c 对于编译大量.c文件非常高效率。执行起来类似于for循环一样,需要注意的是理解其commands中使用的是$<,而非$^,虽然使用$<或$^的执行过程相同。
3.1 %.o:%.c常用的几种写法:
%.o:%.c
$(CC) -o $@ -c $<
%.o:%.c
$(CC) -o $@ $<
利用Makefile缺省规则的写法:
.c.o:
$(CC) -o $@ -c $<
.c.o:
$(CC) -o $@ $<
.c.o:
$(CC) -c $<
注意其中的.c.o,其实是和%o:%c等价,是一个旧格式。
3.2 makefile静态模式:$(OBJS):%.o:%.c常用的几种写法:
$(OBJS):%.o:%.c
$(CC) -o $@ -c $<
$(OBJS):%.o:%.c
$(CC) -o $@ $<
阅读(1830) | 评论(0) | 转发(0) |