Makefile学习之路 – 3(debug和rlease之定义)

Makefile学习之路 – 2

我们开始新的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,其作用就是删除所有编译出的文件。

 

 

版权所有,禁止转载. 如需转载,请先征得博主的同意,并且表明文章出处,否则按侵权处理.

    分享到:

留言

你的邮箱是保密的 必填的信息用*表示