1.在写代码之前先把Makefile弄好,然后集中精力学TCP/IP
-
EXE=main
-
CC=gcc
-
SRC=$(wildcard *.c) --> a
-
OBJ=$(SRC:.c=.o) --> b
-
DEP=$(patsubst %.c,.%.d,$(SRC)) --> c
-
CFLAGS=-g --> d
-
$(EXE):$(OBJ) --> e
-
$(CC) $^ -o $@
-
-
$(DEP):.%.d:%.c --> f
-
@set -e; rm -f $@; \
-
$(CC) -MM $< > $@.$$$$; \
-
sed 's,/($*/)/.o[ :]*,/1.o $@ : ,g' < $@.$$$$ > $@; \
-
rm -f $@.$$$$
-
-
-include $(DEP) -->g
-
-
clean: -->h
-
@rm $(EXE) $(OBJ) $(DEP) -f
解释说明
a. SRC
=$(wildcard
*.c
)
SRC的内容就是一个以"*.c"结尾的文件列表
b. OBJ
=$(SRC
:.c
=.o
)
这个等同于OBJ=$(patsubst %.c,%.o,$(SRC)),在SRC的一堆文件名中,将.c结尾的文件替换成.o
c. DEP=$(patsubst %.c,.%.d,$(SRC))
在SRC的一堆文件名中,将.c结尾的文件替换成.d,
注意这儿是.%.d,前面还有个点,这是为了生成隐藏文件
d. CFLAGS
Makefile中的内含变量CFLAGS
, 这个在编译时会自动用到
e. 链接
将所有的.o连接生成目标文件
f. 生成DEP, 为什么要加入DEP呢?引用说明一下
Makefile的自动推导功能只会推导出目标文件对源文件的依赖关系,而不会增加头文件的依赖关系!!!这导致的直接问题就是修改项目的头文件,不会导致make的自动更新!除非修改头文件后运行一次make clean,再运行make……
g. -include
include前面的‘-’,是为了避免第一次make时由于.depend文件不存在报告错误信息
h. @rm
rm前面加@,不输出任何信息
参考文章:
http://www.cnblogs.com/fanzhidongyzby/p/3141041.html
Makefile.txt (下载后将Makefile.txt改名为Makefile)
2. 特殊情况的改进
-
├── main.c --> include了testlib目录下的testadd.c时 #include "testadd.h"
-
├── Makefile
-
└── testlib
-
├── Makefile
-
├── testadd.c
-
└── testadd.h
cong@msi:/work/test/test/3testlib$ gcc -MM main.c -->在生成头文件的依赖关系时失败
main.c:3:21: fatal error: testadd.h: No such file or directory
#include "testadd.h"
^
compilation terminated.
2.1 改进后的Makefile
-
cong@msi:/work/test/test/3testlib$ cat Makefile
-
EXE=main
-
CC=gcc
-
SRC=$(wildcard *.c)
-
#OBJ=$(SRC:.c=.o)
-
OBJ=$(patsubst %.c,%.o,$(SRC))
-
DEP=$(patsubst %.c,.%.d,$(SRC))
-
INCDIR=-I./testlib
-
CFLAGS = -g -O0 $(INCDIR)
-
LDFLAGS = -L./testlib/ -ltestadd
-
$(EXE):$(OBJ)
-
make -C ./testlib
-
$(CC) $^ -o $@ $(LDFLAGS)
-
-
$(DEP):.%.d:%.c
-
@set -e; rm -f $@; \
-
$(CC) $(INCDIR) -MM $< > $@.$$$$; \
-
sed 's,/($*/)/.o[ :]*,/1.o $@ : ,g' < $@.$$$$ > $@; \
-
rm -f $@.$$$$
-
-
-include $(DEP)
-
clean:
-
@rm $(EXE) $(OBJ) $(DEP) -f
-
@make -C ./testlib clean
3. 运行时的库
上述改法编译链接都没有问题,但是在运行时会出现如下:
-
cong@msi:/work/test/test/3testlib$ ./main
-
./main: error while loading shared libraries: libtestadd.so: cannot open shared object file: No such file or directory
虽然通过export LD_LIBRARY_PATH=$(
LD_LIBRARY_PATH):./testlib可以解决,
但问题是libtestlib只有这一个程序用,export
LD_LIBRARY_PATH之后,所有的程序在加载时都会查找到testlib这个目录了。
这儿用到了ld的 -rpath选项,它是指定运行时的搜索路径,硬编码到可执行文件内部的搜索路径。
注意: 在gcc中使用ld链接选项时,需要在选项前面加上前缀-Wl
注意2: 加了-rpath之后, readelf -d ./main 查看,会比没加的多这一行
0x000000000000000f (RPATH) Library rpath: [testlib:testsub]
readelf -d -d --dynamic Display the dynamic section (if present)
3.1 加入运行时库的
-
EXE=main
-
CC=gcc
-
SRC=$(wildcard *.c)
-
#OBJ=$(SRC:.c=.o)
-
OBJ=$(patsubst %.c,%.o,$(SRC))
-
DEP=$(patsubst %.c,.%.d,$(SRC))
-
INCDIR=-I./testlib
-
CFLAGS = -g -O0 $(INCDIR)
-
LDFLAGS = -L./testlib/ -ltestadd -Wl,-rpath,testlib --> 在gcc中使用ld链接选项时,需要在选项前面加上前缀-Wl
-
$(EXE):$(OBJ)
-
make -C ./testlib
-
$(CC) $^ -o $@ $(LDFLAGS)
-
-
$(DEP):.%.d:%.c
-
@set -e; rm -f $@; \
-
$(CC) $(INCDIR) -MM $< > $@.$$$$; \
-
sed 's,/($*/)/.o[ :]*,/1.o $@ : ,g' < $@.$$$$ > $@; \
-
rm -f $@.$$$$
-
-
-include $(DEP)
-
clean:
-
@rm $(EXE) $(OBJ) $(DEP) -f
-
@make -C ./testlib clean
3.2代码下载
3testlib.rar (下载后改名为3testlib.tar.gz)
3.3 多个库的情况
-
EXE=main
-
CC=gcc
-
SRC=$(wildcard *.c)
-
OBJ=$(patsubst %.c,%.o,$(SRC))
-
DEP=$(patsubst %.c,.%.d,$(SRC))
-
INCDIR=-I./testlib -I./testsub
-
CFLAGS = -g -O0 $(INCDIR)
-
LDFLAGS = -L./testlib/ -ltestadd -L./testsub/ -ltestsub -Wl,-rpath,testlib:testsub
-
$(EXE):$(OBJ)
-
make -C ./testlib
-
make -C ./testsub
-
$(CC) $^ -o $@ $(LDFLAGS)
-
-
$(DEP):.%.d:%.c
-
@set -e; rm -f $@; \
-
$(CC) $(INCDIR) -MM $< > $@.$$$$; \
-
sed 's,/($*/)/.o[ :]*,/1.o $@ : ,g' < $@.$$$$ > $@; \
-
rm -f $@.$$$$
-
-
-include $(DEP)
-
clean:
-
@rm $(EXE) $(OBJ) $(DEP) -f
-
@make -C ./testlib clean
-
@make -C ./testsub clean
3.4 代码下载
4multlib.rar (下载后改名为4.multlib.tar.gz)
阅读(1914) | 评论(0) | 转发(0) |