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 ...) ...
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)
我的成功实例↓
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指令:
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
结果:
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文件)依赖。
g++ -g -o AirlineTicket.o -c AirlineTicket.cpp
g++ -g -o AirlineTicketTest.exe AirlineTicketTest.o AirlineTicket.o