Makefile编写和使用技巧

Makefile

可以用文本编辑器编写makefile文件,与源文件保存在同一目录下,名称取为"Makefile"或"makefile".

在确定安装好Mingw并且配置好环境变量后,使用命令行,转到源文件所在的目录下,然后输入命令"mingw32-make", 即可编译成功。如果你的Makefile名称为其他(比如buildFile.mk),则在Build命令执行时需要特别指定,即make -f buildFile.mk 。

A makefile consist of Rules and these Rules consist of three main things:Targets,Dependencies and Commands. In GNU Documentation these are called:Target,Requirements and Recipe. And this is how it looks:

target ... : dependencies ...
	command
	...
	...

command 是命令行,如果其不与“target:prerequisites”在一行,那么,必须以[Tab键]开头;如果和 prerequisites 在一行,那么可以用分号(;)做为分隔。

This is how a Rule look as in GNU Documentation:

target ... : requirements ...
	recipe
	...
	...

A makefile can consist of other elements that help us write better Rules to handle our source code, some of these elements are:Comments,Macros and Functions. Here you can see how they look:

# MY LINE COMMENT ...
 
myMACRO = myVALUE ...
...
 
$(theFunction ...)
 
...
-->>Referenced from  http://www.captaincps.net/2011/11/28/writting-simple-mingw-makefile/

Sample Makefile

# A sample Makefile
# This Makefile demonstrates and explains 
# Make Macros, Macro Expansions,
# Rules, Targets, Dependencies, Commands, Goals
# Artificial Targets, Pattern Rule, Dependency Rule.

# Comments start with a # and go to the end of the line.

# Here is a simple Make Macro.
LINK_TARGET = test_me.exe

# Here is a Make Macro that uses the backslash to extend to multiple lines.
# This allows quick modification of more object files.
OBJS =  \
 Test1.o \
 Test2.o \
 Main.o

# Here is a Make Macro defined by two Macro Expansions.
# A Macro Expansion may be treated as a textual replacement of the Make Macro.
# Macro Expansions are introduced with $ and enclosed in (parentheses).
REBUILDABLES = $(OBJS) $(LINK_TARGET)

# Make Macros do not need to be defined before their Macro Expansions,
# but they normally should be defined before they appear in any Rules.
# Consequently Make Macros often appear first in a Makefile.

# Here is a simple Rule (used for "cleaning" your build environment).
# It has a Target named "clean" (left of the colon ":" on the first line),
# no Dependencies (right of the colon),
# and two Commands (indented by tabs on the lines that follow).
# The space before the colon is not required but added here for clarity.
clean : 
 rm -f $(REBUILDABLES)
 echo Clean done

# There are two standard Targets your Makefile should probably have:
# "all" and "clean", because they are often command-line Goals.
# Also, these are both typically Artificial Targets, because they don't typically
# correspond to real files named "all" or "clean".  

# The rule for "all" is used to incrementally build your system.
# It does this by expressing a dependency on the results of that system,
# which in turn have their own rules and dependencies.
all : $(LINK_TARGET)
 echo All done

# There is no required order to the list of rules as they appear in the Makefile.
# Make will build its own dependency tree and only execute each rule only once
# its dependencies' rules have been executed successfully.

# Here is a Rule that uses some built-in Make Macros in its command:
# $@ expands to the rule's target, in this case "test_me.exe".
# $^ expands to the rule's dependencies, in this case the three files
# main.o, test1.o, and  test2.o.
$(LINK_TARGET) : $(OBJS)
 g++ -g -o $@ $^

# Here is a Pattern Rule, often used for compile-line.
# It says how to create a file with a .o suffix, given a file with a .cpp suffix.
# The rule's command uses some built-in Make Macros:
# $@ for the pattern-matched target
# $lt; for the pattern-matched dependency
%.o : %.cpp
 g++ -g -o $@ -c $<

# These are Dependency Rules, which are rules without any command.
# Dependency Rules indicate that if any file to the right of the colon changes,
# the target to the left of the colon should be considered out-of-date.
# The commands for making an out-of-date target up-to-date may be found elsewhere
# (in this case, by the Pattern Rule above).
# Dependency Rules are often used to capture header file dependencies.
Main.o : Main.h Test1.h Test2.h
Test1.o : Test1.h Test2.h
Test2.o : Test2.h

# Alternatively to manually capturing dependencies, several automated
# dependency generators exist.  Here is one possibility (commented out)...
# %.dep : %.cpp
#        g++ -M $(FLAGS) $< > $@
# include $(OBJS:.o=.dep)


The following -k flag tells make to continue making other independent rules even when one rule fails. This is helpful for build large projects.

-->>Referenced from  http://help.eclipse.org/helios/index.jsp?topic=%2Forg.eclipse.cdt.doc.user%2Fconcepts%2Fcdt_c_makefile.htm

另外,若对上面的g++ 命令后的参数不懂,可以在命令行下输入g++ --help, 以查看它的使用帮助。


下面是另一份makefile的模板:

#makefile的细节:
#1.每行命令后面不要带多余的空格
#2.windows和linux下的shell命令、目录表示不同
#3.CINCS = -I.\includes 中I和.之间不能有空格

#几个特殊变量的含义
 #$@  用在生成规则中,表示当前目标 
 #$<  用在生成规则中,表示当前目标的第一个依赖目标
 #$^  用在生成规则中,表示当前目标的所有依赖目标
 
 #########################################################
 #本makefile对应的工程目录组织
 # ./ ------- project root
 #   +sources/
 #   +includes/
 #   +objs/
 #    TARGET
 #    resource.rc
 #    resource.h
 #    makefile
 #修改时,根据实际改变响应的目录名,另外重填./sources下源文件列表
 #########################################################
 
TARGET = winhello.exe 

#msys

##########目录设置 ##########
####工程根目录
PROJECT_ROOT = .
###源代码根目录####

SRC_DIR = $(PROJECT_ROOT)/sources
OBJS_DIR := $(PROJECT_ROOT)/objs

APP_CSRCS = main.c
RES_SRC      = resource.rc

ifdef APP_CSRCS
CSRCS := $(addprefix $(SRC_DIR)/,$(APP_CSRCS))
endif

############## 添加路径 #############
COBJS := $(addprefix $(OBJS_DIR)/, $(patsubst %.c,%.o,$(notdir $(CSRCS))))

ifdef RES_SRC
RES_OBJ = $(addprefix $(OBJS_DIR)/, $(patsubst %.rc,%.o,$(notdir $(RES_SRC))))
endif

###########编译器命令相关#########
CC = gcc 
RESC = windres
RM = rm
#注意 windows下将等于号后面的rm改为del,linux下RM = rm

#头文件目录
INC_DIR := ./includes 

#编译选项
CFLAGS = -g -Wall
CFLAGS += -I$(INC_DIR)

all : $(TARGET)

version :
        @echo Show $(CC)  Version
        $(CC) --version

$(TARGET) : $(COBJS) $(RES_OBJ)
        @echo 连接目标文件,生成最终target -- $@
#       $(CC)  $(COBJS) $(RES_OBJ)-o $@ 
        $(CC) $^ -o $@

# 编译C程序
$(OBJS_DIR)/%.o : $(SRC_DIR)/%.c
        @echo 正在编译c文件: $< --> $@
        $(CC) -c $(CFLAGS) $< -o $@
        
$(RES_OBJ):$(RES_SRC)
        $(RESC) $< -o $@

.PHONY:msg clean
msg:
        @echo CSRCS是$(CSRCS)
        @echo COBJS是$(COBJS)
        @echo CFLAGS是$(CFLAGS)
        @echo RM命令是$(RM)
        @echo RESC是$(RESC)
        @echo RES_SRC是$(RES_SRC)
        @echo RES_OBJ是$(RES_OBJ)
        
clean:cleanobj cleanexe
        @echo obj文件和exe文件已删除

cleanobj:
        @echo 删除所有.o文件
        -$(RM) $(COBJS) 
        -$(RM) $(RES_OBJ)
cleanexe:
        @echo 删除所有.exe文件
        -$(RM) $(TARGET)


我的成功实例↓





makefile文件的内容:

LINK_TARGET = AirlineTicketTest.exe
OBJS = \
 AirlineTicketTest.o \
 AirlineTicket.o


 
$(LINK_TARGET) : $(OBJS)
 g++ -g -o $@ $^
AirlineTicketTest.o : AirlineTicketTest.cpp
 g++ -g -o $@ -c $<
AirlineTicket.o : AirlineTicket.cpp
 g++ -g -o $@ -c $<

AirlineTicketTest.o
: AirlineTicket.h
AirlineTicket.o
: AirlineTicket.h

clean
:
# rm -f $(OBJS)

 -del
$(OBJS)
 echo Clean done
all :$(LINK_TARGET)
 echo All done

























使用mingw32-make Build指令:

C:\workspace>mingw32-make
g++ -g -o AirlineTicketTest.o -c AirlineTicketTest.cpp
g++ -g -o AirlineTicket.o -c AirlineTicket.cpp
g++ -g -o AirlineTicketTest.exe AirlineTicketTest.o AirlineTicket.o








结果:

C:\workspace >mingw32-make -k clean all
del AirlineTicketTest.o AirlineTicket.o
echo Clean done
Clean done
g++ -g -o AirlineTicketTest.o -c AirlineTicketTest.cpp
g++ -g -o AirlineTicket.o -c AirlineTicket.cpp
g++ -g -o AirlineTicketTest.exe AirlineTicketTest.o AirlineTicket.o
echo All done
All done












其实,我们直接在命令行下输入以下语句,也可以编译得到同样的结果,只是少了很多控制的便利,比如根据文件依赖关系和修改时间来重新编译程序等。不过这也证明了g++可以直接根据程序文件(.cpp文件)推断出同名的头文件(.h文件)依赖


C:\workspace >g++ -g -o AirlineTicketTest.o -c AirlineTicketTest.cpp
g++ -g -o AirlineTicket.o -c AirlineTicket.cpp
g++ -g -o AirlineTicketTest.exe AirlineTicketTest.o AirlineTicket.o







  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值