Makefile详解和实例

来源:互联网 发布:sql server error 编辑:程序博客网 时间:2024/06/07 22:41

 Makefile隐含规则使用的变量

在隐含规则中的命令中,基本上都是使用了一些预先设置的变量。你可以在你的makefile中改变这些变量的值,或是在make的命令行中传入这些值,或是在你的环境变量中设置这些值,无论怎么样,只要设置了这些特定的变量,那么其就会对隐含规则起作用。当然,你也可以利用make的“-R”或“--no–builtin-variables”参数来取消你所定义的变量对隐含规则的作用。

例如,第一条隐含规则——编译C程序的隐含规则的命令是“$(CC)–c $(CFLAGS)$(CPPFLAGS)”。Make默认的编译命令是“cc”,如果你把变量“$(CC)”重定义成“gcc”,把变量“$(CFLAGS)”重定义成“-g”,那么,隐含规则中的命令全部会以“gcc –c -g $(CPPFLAGS)”的样子来执行了。

我们可以把隐含规则中使用的变量分成两种:一种是命令相关的,如“CC”;一种是参数相的关,如“CFLAGS”。下面是所有隐含规则中会用到的变量:

1、关于命令的变量。

AR 

    函数库打包程序。默认命令是“ar”。 

AS 

    汇编语言编译程序。默认命令是“as”。

CC 

    C语言编译程序。默认命令是“cc”。

CXX 

   C++语言编译程序。默认命令是“g++”。

CO 

    从 RCS文件中扩展文件程序。默认命令是“co”。

CPP 

    C程序的预处理器(输出是标准输出设备)。默认命令是“$(CC) –E”。

FC 

   Fortran 和 Ratfor 的编译器和预处理程序。默认命令是“f77”。

GET 

    从SCCS文件中扩展文件的程序。默认命令是“get”。 

LEX 

    Lex方法分析器程序(针对于C或Ratfor)。默认命令是“lex”。

PC 

   Pascal语言编译程序。默认命令是“pc”。

YACC 

   Yacc文法分析器(针对于C程序)。默认命令是“yacc”。

YACCR 

   Yacc文法分析器(针对于Ratfor程序)。默认命令是“yacc –r”。

MAKEINFO 

    转换Texinfo源文件(.texi)到Info文件程序。默认命令是“makeinfo”。

TEX 

    从TeX源文件创建TeX DVI文件的程序。默认命令是“tex”。

TEXI2DVI 

    从Texinfo源文件创建军TeX DVI 文件的程序。默认命令是“texi2dvi”。

WEAVE 

    转换Web到TeX的程序。默认命令是“weave”。

CWEAVE 

    转换C Web 到 TeX的程序。默认命令是“cweave”。

TANGLE 

    转换Web到Pascal语言的程序。默认命令是“tangle”。

CTANGLE 

    转换C Web 到 C。默认命令是“ctangle”。

RM  

    删除文件命令。默认命令是“rm –f”。

2、关于命令参数的变量

下面的这些变量都是相关上面的命令的参数。如果没有指明其默认值,那么其默认值都是空。

ARFLAGS 

    函数库打包程序AR命令的参数。默认值是“rv”。

ASFLAGS 

    汇编语言编译器参数。(当明显地调用“.s”或“.S”文件时)。 

CFLAGS 

    C语言编译器参数。

CXXFLAGS 

   C++语言编译器参数。

COFLAGS 

   RCS命令参数。 

CPPFLAGS 

    C预处理器参数。( C 和 Fortran 编译器也会用到)。

FFLAGS 

   Fortran语言编译器参数。

GFLAGS 

   SCCS “get”程序参数。

LDFLAGS 

    链接器参数。(如:“ld”)

LFLAGS 

   Lex文法分析器参数。

PFLAGS 

   Pascal语言编译器参数。

RFLAGS 

   Ratfor 程序的Fortran 编译器参数。

YFLAGS 

   Yacc文法分析器参数。 

 

 

Makefile实例详解

# 一、 操作系统及shell相关

########################################################################################

#指定使用的shell及取得操作系统类型,宏定义常用shell命令

 

#指定SHELL ,SHELL := /bin/sh ,或者使用当前SHELL设置

#SHELL := /bin/bash

 

#取得操作系统名称#OS_NAME="Linux:SunOS:HP-UX:AIX"

OS_NAME := $(shell uname -s)

 

#把常用的几个系统命令自定义名称和选现,rm命令前面加了一个小减号的意思就是,

#也许某些文件出现问题,但不要管,继续做后面的事

AR := ar           

SED:= sed         

AWK:= awk

MV := mv

RM := rm -f

ECHO := echo

 

#=======================================================================================

# 二、C编译器选项

########################################################################################

#指定C编译器, 如gcc 编译器

CC     := gcc

#指定C编译时的选项

#CFLAGS         C语言编译器参数,编译时使用。

CFLAGS := -c -g  -W -Wall

 

# CPP , C 预编译器的名称,默认值为$(CC) -E。

CPP :=

#  CPPFLAGS , C 预编译的选项。

CPPFLAGS :=

 

# 三、C++编译器选项

########################################################################################

#=======================================================================================

 

#指定C++编译器, 如g++ 编译器

CXX     := g++

#指定C编译时的选项

#CXXFLAGS         C++语言编译器参数,编译时使用。

CXXFLAGS := -c -g -W -Wall

 

# CXXPP , C++ 预编译器的名称,默认值为$(CC) -E。

CXXPP :=

#  CXXPPFLAGS , C++ 预编译的选项。

CXXPPFLAGS :=

 

#=======================================================================================

 

# 四、指定额外搜索的头文件路径、库文件路径、引入的库

########################################################################################

#指定搜索路径, 也可用include指定具体文件路径,编译时使用

# The include files ( C and C++ common).

INCLUDES := -I$(ORACLE_HOME)/rdbms/demo-I$(ORACLE_HOME)/rdbms/public  \

 -I$(ORACLE_HOME)/plsql/public -I$(ORACLE_HOME)/network/public  -I./include-I./include/app -I./include/tools  \

 -I./include/tools/file -I./include/tools/common

 

# 指定函数库搜索路径DIRECTORY 搜寻库文件(*.a)的路径,加入需要的库搜索路径 功能同–l,由用户指定库的路径,否则编译器将只在标准库的目录找。          

#连接时使用

LIBDIRS :=-L$(ORACLE_HOME)/lib-L$(ORACLE_HOME)/rdbms/lib

 

# 链接器参数,  连接时搜索指定的函数库LDFLAGS。,引入需要的库-lLDFLAGS    指定编译的时候使用的库. 连接库文件开关。例如-lugl,则是把程序同libugl.a文件进行连接。

#连接时使用

#-lclntsh -lnsl -lpthread -Wl,-Bdynamic -lgcc_s    ,同时有动态库和静态库时默认使用动态库,   -Wl,-Bdynamic 指定和动态库相连, -Wl,-Bstatic 指定和静态库相连

CLDFLAGS   :=  -lm  -lclntsh -lnsl -lpthread  -Wl,-Bdynamic -lgcc_s

CXXLDFLAGS :=  -lm  -lclntsh -lnsl -lpthread  -Wl,-Bdynamic -lgcc_s  -lstdc++

 

#宏定义,如果没有定义宏的值,默认是字符串1 ,定义值为数字时直接写数字,字符和字符串需用 \"和\'转义

#DCPPFLAGS :=  -D${OS_NAME}  -D_TEST1_  -D_TEST2_=2  -D_TEST3_=\"a\"  -D_TEST4_=\'b\'-DOS_NAME=\"${OS_NAME}\"

DCPPFLAGS := -D${OS_NAME}  

 

#各平台'SunOS'   'Linux' link类库差异, 设置特定值

ifeq '${OS_NAME}' 'SunOS'

   CLDFLAGS += -lsocket

   CXXLDFLAGS += -lsocket

   DCPPFLAGS += -D_POSIX_PTHREAD_SEMANTICS -D_REENTRANT

endif

 

#=======================================================================================

 

#  五、 指定源文件的路径 、支持的源文件的扩展名 、源文件搜索路径

########################################################################################

# 指定SRC_DIR 源代码文件路径./src  ./src2   src2/src3

SRC_DIR  := .  ./src  ./src/copyfile  ./src/displayfile ./include/tools/file  ./include/tools/common

 

#指定支持的源代码扩展名 SFIX     := .out .a .ln  .o .c  .cc .C  .p .f  .F

#.r .y  .l  .s .S  .mod  .sym .def  .h  .info .dvi  .tex  .texinfo .texi

#.txinfo .w  .ch .web  .sh .elc  .el

SFIX    :=  .c .C .cpp  .cc .CPP .c++  .cp  .cxx

 

#在当当前目录找不到的情况下,到VPATH所指定的目录中去找寻文件了。如:VPATH = src:../headers

#(当然,当前目录永远是最高优先搜索的地方)

VPATH := ${SRC_DIR}

 

#定义安装目录           

BIN := ./bin

 

#=======================================================================================

 

#  六、 得到源文件名称集合、OBJS目标文件名集合

########################################################################################

 

#依次循环取得各目录下的所有源文件,在各目录下取源文件时过滤不支持的源文件格式,

#得到源文件集合(带路径)

SOURCES := $(foreach x,${SRC_DIR},\

          $(wildcard  \

            $(addprefix  ${x}/*,${SFIX}) ) )

 

#去掉路径信息,去掉扩展名,再追加.o的扩展名,得到目标文件名集合(不带路径),需要去掉路径信息,否则连接时有可能找不到.o文件

OBJS := $(addsuffix .o ,$(basename $(notdir${SOURCES}) ) )   

 

#去掉路径信息,去掉扩展名,再追加.d的扩展名,得到依赖文件名集合(不带路径)

#DEPENDS := $(addsuffix .d ,$(basename$(notdir ${SOURCES}) ) )

 

#去掉扩展名,再追加.d的扩展名,得到依赖文件名集合(带路径)

DEPENDS := $(addsuffix .d ,$(basename  ${SOURCES} ) ) 

#DEPENDS := $(SOURCES:$(SFIX)=.d)

 

#=======================================================================================

 

#  七、 定义生成程序的名称

########################################################################################

 

#生成可执行程序的名称

PROGRAM  := example

 

#=======================================================================================

 

#  八、 定义依赖关系 ,编译、链接规则

########################################################################################

 

#.PHONY”表示,clean是个伪目标文件。

.PHONY : all check  clean install

 

#定义编译、链接任务all

all : ${PROGRAM}  install

 

#检查源码中,除了C源码外是否有C++源码 ,并定义变量LDCXX存储检查结果

LDCXX := $(strip $(filter-out  %.c , ${SOURCES} ) )

 

#编译器重置

ifdef LDCXX   #有C++源码时,所有源码都使用g++编译,包括C源码,将CC、CFLAGS 的值设置为对应的${CXX}、 ${CXXFLAGS}的值

   CC := ${CXX}                    #重置C编译器为C++编译器

   CFLAGS :=  ${CXXFLAGS}          #重置C编译选现为C++编译选现

   CPP :=  ${CXXPP}                #重置C预编译器为C++预编译器

   CPPFLAGS := ${CXXPPFLAGS}       #重置C预编译的选项为C++预编译的选项

endif

 

#链接

${PROGRAM} :  ${DEPENDS} ${OBJS}

ifeq ($(strip $(filter-out  %.c  ,${SOURCES} ) ),)    #只有C源码时使用gcc连接

   ${CC}  ${LIBDIRS}  ${CLDFLAGS}   ${OBJS} -o $@   

else                                                #有C++源码时使用g++连接

   $(CXX) ${LIBDIRS} ${CXXLDFLAGS}    ${OBJS} -o$@    

endif

 

# Rules for producing the objects. (.o)BEGIN

#---------------------------------------------------

 

%.o : %.c

   $(CC)      ${DCPPFLAGS}    ${CFLAGS}      ${INCLUDES}   $<

 

%.o : %.C

   $(CXX)     ${DCPPFLAGS}    ${CXXFLAGS}    ${INCLUDES}   $<

 

%.o : %.cc

   ${CXX}     ${DCPPFLAGS}    ${CXXFLAGS}    ${INCLUDES}   $<

 

%.o : %.cpp

   ${CXX}     ${DCPPFLAGS}    ${CXXFLAGS}    ${INCLUDES}   $<

 

%.o : %.CPP

   ${CXX}     ${DCPPFLAGS}    ${CXXFLAGS}    ${INCLUDES}   $<

 

%.o : %.c++

   ${CXX}     ${DCPPFLAGS}    ${CXXFLAGS}    ${INCLUDES}   $<

 

%.o : %.cp

   ${CXX}     ${DCPPFLAGS}    ${CXXFLAGS}    ${INCLUDES}   $<

 

%.o : %.cxx

   ${CXX}     ${DCPPFLAGS}    ${CXXFLAGS}    ${INCLUDES}   $<

 

#---------------------------------------------------

# Rules for producing the objects.(.o) END

 

 

# Rules for creating the dependency files(.d). BEGIN

#---------------------------------------------------

%.d : %.c

   @${CC}     -M   -MD   ${INCLUDES} $<

 

%.d : %.C

   @${CXX}    -MM  -MD   ${INCLUDES} $<

 

%.d : %.cc

   @${CXX}    -MM  -MD   ${INCLUDES} $<

 

%.d : %.cpp

   @${CXX}    -MM  -MD   ${INCLUDES} $<

 

%.d : %.CPP

   @${CXX}    -MM  -MD   ${INCLUDES} $<

 

%.d : %.c++

   @${CXX}    -MM  -MD   ${INCLUDES} $<

 

%.d : %.cp

    @${CXX}   -MM  -MD    ${INCLUDES} $<

 

%.d : %.cxx

   @${CXX}    -MM  -MD   ${INCLUDES} $<

 

#---------------------------------------------------

# Rules for creating the dependency files(.d). END

 

 

#=======================================================================================

 

#  九、 定义其他 check  install clean 等任务

########################################################################################

 

#定义检查环境相关的变量的任务

check :

   @${ECHO}  MAKEFILES : ${MAKEFILES}

   @${ECHO}  MAKECMDGOALS :${MAKECMDGOALS}

   @${ECHO}  SHELL  : ${SHELL}

   @${ECHO}  OS_NAME  : ${OS_NAME}

   @${ECHO}  SRC_DIR : ${SRC_DIR}

   @${ECHO}  SFIX : ${SFIX}

   @${ECHO}  VPATH : ${VPATH}

   @${ECHO}  BIN : ${BIN}

   @${ECHO}  SOURCES : ${SOURCES}

   @${ECHO}  OBJS : ${OBJS}

   @${ECHO}  DEPENDS : ${DEPENDS}

   @${ECHO}  PROGRAM : ${PROGRAM}

   @${ECHO}  CC :  ${CC}

   @${ECHO}  CFLAGS : ${CFLAGS}

   @${ECHO}  CPP : ${CPP}

   @${ECHO}  CPPFLAGS : ${CPPFLAGS}

   @${ECHO}  CXX :  ${CXX}

   @${ECHO}  CXXFLAGS : ${CXXFLAGS}

   @${ECHO}  CXXPP : ${CXXPP}

   @${ECHO}  CXXPPFLAGS :${CXXPPFLAGS}      

   @${ECHO}  INCLUDES : ${INCLUDES}

   @${ECHO}  LIBDIRS : ${LIBDIRS}

   @${ECHO}  CLDFLAGS : ${CLDFLAGS}

   @${ECHO}  CXXLDFLAGS :${CXXLDFLAGS}

    @${ECHO}  DCPPFLAGS : ${DCPPFLAGS}

   uname    -a

 

#定义清理的任务 core.*  ,rm命令前面加了一个小减号的意思就是, 也许某些文件出现问题,但不要管,继续做后面的事

clean :

   -${RM} ${BIN}/${PROGRAM}

   -${RM} ${BIN}/*.o

   -${RM} ${BIN}/*.d

   -${RM} *.o

   -${RM} *.d

 

#将目标文件及可执行程序拷贝到安装目录

install :

   -${MV} ${PROGRAM} ${BIN}

   -${MV}  *.o ${BIN}

   -${MV}  *.d ${BIN}

 

#=======================================================================================

0 0