一。 由繁到简写Makefile .
二。 如何应付多路径,多语言(C/C++)混杂环境下的Makfile.
三。 用Makefile编译动态库(.so)/* 操作系统: Oracle Linux 6.4 编译版本: [root@ol64 test4]# gcc --version gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-3) 例子目录结构: [root@ol64 test4]# ls * callso.c main.c Makefile lib: add.c calc.h Makefile sub.c */注意,例子代码文件附在 " 编译小结(3) 动态库(.so)编译及二种调用技巧" 一章中。
[root@ol64 test4]# cat Makefile #author: xiongchuanliang CC = gcc CFLAGS = -m64 -fPIC TARGET = demo01 OBJS = main.o add.o sub.o $(TARGET): $(OBJS) $(CC) $(CFLAGS) -o $(TARGET) $(OBJS) main.o: main.c lib/calc.h $(CC) $(CFLAGS) -c main.c -I./lib add.o: lib/add.c lib/calc.h $(CC) $(CFLAGS) -c lib/add.c sub.o: lib/sub.c lib/calc.h $(CC) $(CFLAGS) -c lib/sub.c .PHONY: clean clean: -rm -f $(TARGET) $(OBJS)上面这个的Makfile就不细说。很规范的Makefile格式,特点是用一些宏代替了每一行要重复输入的东西。
[root@ol64 test4]# make gcc -m64 -fPIC -c main.c -I./lib gcc -m64 -fPIC -c lib/add.c gcc -m64 -fPIC -c lib/sub.c gcc -m64 -fPIC -o demo01 main.o add.o sub.o [root@ol64 test4]# ./demo01 add() = 8 sub() = 2 MAIL:[email protected] BLOG:http://blog.csdn.net/xcl168
[root@ol64 test4]# cat Makefile #author: xiongchuanliang CC = gcc CFLAGS = -m64 -fPIC TARGET = demo02 OBJS = main.o add.o sub.o $(TARGET):main.o add.o sub.o $(CC) $(CFLAGS) -o $(TARGET) $(OBJS) main.o: main.c lib/calc.h $(CC) $(CFLAGS) -c $< -I./lib add.o: lib/add.c lib/calc.h $(CC) $(CFLAGS) -c $< sub.o: lib/sub.c lib/calc.h $(CC) $(CFLAGS) -c $< .PHONY: clean clean: -rm -f $(TARGET) $(OBJS)
[root@ol64 test4]# cat Makefile #author: xiongchuanliang CC = gcc CFLAGS = -m64 -fPIC -I./lib TARGET = demo03 OBJS = main.o lib/add.o lib/sub.o $(TARGET):$(OBJS) $(CC) $(CFLAGS) -o $(TARGET) $(OBJS) main.o: main.c lib/calc.h add.o: lib/add.c lib/calc.h sub.o: lib/sub.c lib/calc.h .PHONY: clean clean: -rm -f $(TARGET) $(OBJS)小技巧:
[root@ol64 test4]# cat Makefile #author: xiongchuanliang CC = gcc CXX = g++ CFLAGS = -m64 -fPIC -I./lib TARGET = demo04 %.o: %.c $(CC) $(CFLAGS) -c $< -o $@ SOURCES = $(wildcard *.c) $(wildcard lib/*.c) OBJS = $(patsubst %.c,%.o,$(SOURCES)) $(TARGET) : $(OBJS) $(CXX) $(CFLAGS) -o $(TARGET) $^ .PHONY: clean clean: -rm -f $(TARGET) $(OBJS)首先我把几个匹配符说明下:
[root@ol64 test4]# cat Makefile #author: xiongchuanliang SOURCES = $(wildcard *.c) $(wildcard lib/*.c) OBJS = $(patsubst %.c,%.o,$(SOURCES)) NODIR = $(notdir $(OBJS)) all: @echo $(SOURCES) @echo $(OBJS) @echo $(NODIR) [root@ol64 test4]# make main.c lib/add.c lib/sub.c main.o lib/add.o lib/sub.o main.o add.o sub.o参数说明:
[root@ol64 test4]# make gcc -m64 -fPIC -I./lib -c main.c -o main.o gcc -m64 -fPIC -I./lib -c lib/add.c -o lib/add.o gcc -m64 -fPIC -I./lib -c lib/sub.c -o lib/sub.o g++ -m64 -fPIC -I./lib -o demo05 main.o lib/add.o lib/sub.o [root@ol64 test4]# ./demo05 add() = 8 sub() = 2 MAIL:[email protected] BLOG:http://blog.csdn.net/xcl168 [root@ol64 test4]# cat Makefile #author: xiongchuanliang CC = gcc CXX = g++ CFLAGS = -m64 -fPIC -I./lib TARGET = demo05 #OBJS = main.o lib/add.o lib/sub.o %.o: %.c $(CC) $(CFLAGS) -c $< -o $@ %.o: %.cpp $(CXX) $(CFLAGS) -c $< -o $@ SOURCES = $(wildcard *.c *.cpp) $(wildcard lib/*.c) OBJS = $(patsubst %.c,%.o,$(patsubst %.cpp,%.o,$(SOURCES))) $(TARGET) : $(OBJS) $(CXX) $(CFLAGS) -o $(TARGET) $^ .PHONY: clean clean: -rm -f $(TARGET) $(OBJS)个人理解这个Makefile是不管C还是C++文件,编译用"wildcard"宏,拼出文件串。
[root@ol64 lib]# cat Makefile #author: xiongchuanliang CC = gcc CFLAGS = -m64 -fPIC SHARED = -shared TARGET = libcalc01.so OBJS = add.o sub.o $(TARGET): $(OBJS) $(CC) -o $(TARGET) $(OBJS) $(CFLAGS) $(SHARED) add.o: add.c calc.h sub.o: sub.c calc.h .PHONY: clean clean: rm -f $(TARGET) $(OBJS)例2
[root@ol64 lib]# cat Makefile #author: xiongchuanliang CC = gcc CFLAGS = -m64 -fPIC SHARED = -shared TARGET = libcalc02.so %.o: %.c $(CC) $(CFLAGS) -c $< -o $@ SOURCES = $(wildcard *.c) OBJS = $(patsubst %.c,%.o,$(SOURCES)) $(TARGET) : $(OBJS) $(CXX) $(CFLAGS) $(SHARED) -o $(TARGET) $^ .PHONY: clean clean: -rm -f $(TARGET) $(OBJS)
如果你做的动态库有跨平台的需求,还可以看下面的例子。
Windows下的动态库,通常会定义一个def文件,来定义要指定导出的函数。
gcc也可以,通过 --retain-symbols-file 与 --version-script 两个参数控制。
//要注意下面Makefile中"EXPFUN"一行 [root@ol64 lib]# cat Makefile #author: xiongchuanliang CC = gcc CFLAGS = -m64 -fPIC SHARED = -shared EXPFUN = -Wl,--retain-symbols-file=dy.sym -Wl,--version-script=dy.map TARGET = libcalc.so OBJS = add.o sub.o $(TARGET): $(OBJS) $(CC) -o $(TARGET) $(OBJS) $(CFLAGS) $(SHARED) $(EXPFUN) add.o: add.c calc.h sub.o: sub.c calc.h .PHONY: clean clean: rm -f $(TARGET) $(OBJS) //控制动态导出符号 对应 :--version-script //global表示要导出的符号,local表示不导出的,*表示都不导出 [root@ol64 lib]# cat dy.map { global: sub; local: *; }; //控制静态导出符号 对应 :--retain-symbols-file [root@ol64 lib]# cat dy.sym sub //可以用 readelf 来查看导出函数 [root@ol64 lib]# readelf -s libcalc.so //例子中没有指定要导出add函数,当被调用时,会报下面的错。 [root@ol64 lib]# ./../callso [main] cadd() failed! /xcl/test4/lib/libcalc.so: undefined symbol: add
四。 用Makefile编译静态库(.a)
只简单展示下静态库的Makefile怎么写,关于静态库的编译知识,[root@ol64 lib]# cat Makefile #author: xiongchuanliang CC = gcc CFLAGS = -maix64 -fPIC TARGET = libcalc01.a %.o: %.c $(CC) $(CFLAGS) -c $< -o $@ SOURCES = $(wildcard *.c) OBJS = $(patsubst %.c,%.o,$(SOURCES)) $(TARGET) : $(OBJS) ar -X64 -rcs $(TARGET) $(OBJS) $^ .PHONY: clean clean: -rm -f $(TARGET) $(OBJS) [root@ol64 lib]# make ar -X64 -rcs libcalc01.a add.o sub.o add.o sub.o
ar要注意编译成64位时,要加对应的参数,可用man ar查出。 这个很容易被忽视,特别是在UNIX下。
搞定收工。
MAIL: [email protected]
BLOG:http://blog.csdn.net/xcl168