我们开始新的Makefile学习之路。
在windows的Visual Studio中,你也可以编译debug和release版本,那么使用Makefile,能不能做到这样呢?
答案是 能。
为什么非要定义一个debug和一个release版本呢?因为
debug: 也就是调试版本,通常是在我们开发期间使用,因为它带有调试信息,方便调试。但是它是没有被优化的,因此运行速度慢,另外它一般链接的是debug版本的运行库(这个在链接时指定,这不是严格规定)
relase: 发布版本,通常要发布产品的时候都以这种形式发布,代码经过优化的。
关于debug和release版本的关系,不是我们讨论的重点,所以要是对这方面感兴趣的,可以参看:
http://haacked.com/archive/2004/02/14/difference-between-debug-vs-release-build.aspx
接下来我们看看如何做到在同一个Makefile中同时定义debug和release版本,然后通过:
make debug ——————————– 编译出debug版本
make release ——————————– 编译出release版本
make ——————————– 同时编译出debug和release版本
先说下我们的测试工程的结构:
[当前目录]
———— include
————- external.h
———— lib
————- libexternal.so
———— src
————– main.cpp
————– Makefile
工程目的:
所有的代码集中在src文件中,main.cpp是入口函数的定义文件,此文件中会使用external这个库中的函数,因此需要包含其头文件和链接它的库。
下面Makefile的内容:
CC = g++
OUTPUT = main
OUTPUTd = mainD
OBJ = main.o
OBJd = mainD.o
OBJS = $(OBJ) $(OBJd)
SRC = main.cpp
INCLUDE = ../include/
LIBPATH = ../lib/
.PHONY: clean
.PHONY: debug
.PHONY: release
.PHONY: all
all: $(OUTPUT) $(OUTPUTd)
echo "all build successfully"
# release version
$(OUTPUT): $(OBJ)
$(CC) $^ -L$(LIBPATH) -Bdynamic -lexternal -o $@
# debug version
$(OUTPUTd): $(OBJd)
$(CC) $^ -L$(LIBPATH) -Bdynamic -lexternal -o $@
$(OBJ): $(SRC)
$(CC) -O2 -I$(INCLUDE) -c $^ -o $(OBJ)
$(OBJd): $(SRC)
$(CC) -g -I$(INCLUDE) -c $^ -o $(OBJd)
clean:
rm -f $(OBJS) $(ALL)
debug: $(OUTPUTd)
echo "compile debug version"
release: $(OUTPUT)
echo "compile release version"
这里的关键在于3个伪目标的定义:
.PHONY: debug ——————————————— debug伪目标
.PHONY: release ——————————————— release伪目标
.PHONY: all ——————————————— debug和release伪目标
因为debug伪目标依赖于$(OUTPUTd),所以g++编译器会去编译$(OUTPUTd),而$(OUTPUTd)定义就是我们的debug版本的可执行程序,这样就达到我们的目的了。release同理。
而all却依赖$(OUTPUTd)和$(OUTPUT)
这样当我们的目标是all,它所依赖的$(OUTPUTd)和$(OUTPUT)都会编译。而且all作为我们的第一目标,而Makefile规定,Makefile文件中定义的第一个目标就是默认是目标,因此当你执行,
make
的时候,就相当于执行:
make all
看看上面debug和release的执行语句:
$(CC) -g -I$(INCLUDE) -c $^ -o $(OBJd) ————— debug
$(CC) -O2 -I$(INCLUDE) -c $^ -o $(OBJ) —————- release
你会发现区别就是编译选项而已。
-g表示编译时,增加debug调试信息
-O2表示编译时,进行优化处理。
更多的gcc的编译选项请参考:
http://gcc.gnu.org/onlinedocs/gcc/Option-Summary.html
上面的我们只定义了2个版本,debug和release。你可以定义带有不同的编译选项的更多的版本。这个作为你自己的练习。
这里还定义另外一个伪目标就是clean,其作用就是删除所有编译出的文件。
版权所有,禁止转载. 如需转载,请先征得博主的同意,并且表明文章出处,否则按侵权处理.