Makefile简述

makefile用途总体描述

Make是一种控制编译或重复编译的软件工具。它自动决定一个程序中哪些文件需要重新编译,并重新运行指定的命令。
Make的默认输入文件是当前目录下的 GNUmakefile, makefile或是Makefile文件。当然,也可以通过-f开关来指定具体的文件名。
Makefile主要描述了一些目标和一些依赖的关系,以及它们对应的一些命令。举个例子,一个执行文件通常依赖于目标文件生成,而目标文件又是依赖于由源代码生成的。

Makefile文件包含一系列的“规则”:
目标(target) : 依赖(prerequiries)
<tab>命令(command)
1、目标(target)可以是要产生的文件的名称,如可执行文件或OBJ文件,也可是一个执行的动作名称,如'clean'。
2、依赖是用来输入从而产生目标的文件,一个目标经常有几个依赖。依赖是可选的,可以没有。
3、命令一定要以一个Tab键作为开头。make并不管命令是怎么工作的,他只管 执行所定义的命令。make比较targets和prerequisites 文件的修改日期,如果prerequisites文件的日期要比 targets文件的日期要新或target不存在,make就会执行后续定义的命令
4、Make会自动解析目标的依赖关系。
5、缺省情况下,make将Makefile里的第一个目标做为其目标。要执行其它目标,则需要指定该目标,如make clean。

变量定义及使用
变量的定义语法形式如下:
          immediate = deferred 递归展开
          immediate ?= deferred 先判断是否有值,没有才进行赋值
          immediate := immediate 立即展开
          immediate += deferred or immediate  追加
如:
   LIB_PATH = -L$(LOCAL_PATH)/lib /
    -L${SEARCH_PATH}/lib /
      -L../lib /
   对变量的引用可以使用$(foo)或${foo}形式,如果在命令或文件名中包含”$”要转义成 “$$”才有效果

 

几个奇怪的变量(自动变量) $@ , $< , $^ , $?
这些变量不需要括号括住。
$*不包含扩展名的目标文件名称
$@ 扩展成当前规则的目的文件名
$< 扩展成依靠列表中的第 一个依靠文件
$^ 扩展成整个依靠的列表(除掉了里面所有重 复的文件名)
$? 所有比目标新的依赖目标的集合。以空格分隔
类似的变量还有不少,以上是比较常用的几个
SAMPLE
objects = a.o b.o c.o d.o
$(TARGET) : $(objects)
$(GCC) -o $@ $^ $(LIB_PATH) $(LIB)
%.o : %.cpp
$(GCC) $(CPPFLAGS) -c $< -o $@ $(INCLUDE_PATH)

 

模式匹配符 %
通配符
Makefile中的通配符和Bourne shell中的通配符一样是‘*’、‘?’和‘[…]’。
例如:‘*.c’指在当前目录中所有以‘.c’结尾的文件。
通配符与变量使用的一些问题
如,objects = *.o
上面这个例子,表示了,通符同样可以用在变量中。但是objects的值就是字符串“*.o” ! Makefile中的变量其实就是C/C++中的宏
如果你要让通配符在变量中展开,也就是让objects的值是所有[.o]的文件名的集合,需要使用内建函数wildcard。

wildcard函数, patsubst函数
Makefile中的函数格式为$(函数名 参数,参数,…)。
内建函数wildcard:功能是展开成一列所有符合由其参数 描述的文 件名,文件间以空格间隔。
objects = $(wildcard *.o)
内建函数patsubst (patten substitude,匹配替换的缩写):它需要3个参数,参数1表示需要匹配的 式样,参数2表示用什么来替换它,参数3是一个需要被处理的由空格分隔的字列。
   objects := $(patsubst%.c,%.o,$(wildcard *.c))

include 关键字,将其它文件包含进来
include ../../include/Makefile.env
vpath关键字
vpath %.cpp ../
在查找cpp文件时,将会搜索../文件夹

Phony伪目标
如果文件名中有个和你的目标名相同的文件名,且目标没有依赖体,则make会认为目标是最新的而不执行命令。
如上述的clean目标,如果同时有一个文件名为clean,这时,make clean就会报
make: `clean' is up to date.

解决方法:使用.PHONY声明该目标为伪目标,如
.PHONY: clean
Clean:
rm –rf *.o

其他:

如果只是测试makefile生成的命令而不实际执行可以make –n
如果要指定到某个目录里执行make,可以使用make –C path,而且本命令不会改变工作目录
Makefile中也可以使用条件分支,ifeq,else,endif等
可以用shell命令 PLATFORM := $(shell uname -m)
错误忽略,make对每次shell命令执行时都会判断返回值,出错就退出,如果对是太重要的命令可以考虑忽略,在执行命令前加-,如<tab>-rm *.o  

demo1:

VERSION_ID=mpi_train 1.0.0.2

VERSION64_SIGN=64bit
VERSION32_SIGN=
ifeq ($(MAC),64)
VERSION_SIGN=-D__64BIT__
VERSION_ID+=$(VERSION64_SIGN)
else
VERSION_SIGN=
VERSION_ID+=$(VERSION32_SIGN)
endif

CC = mpicc
CXX=mpic++
LD=ld
AR=ar cr
RM=rm -f
MKDIR=mkdir -p
CP=cp -f
RMDIR=rm -Rf

EXEC = mpi_train
MY_CPP_FILES = $(wildcard *.cpp)
MY_OBJ_FILES = $(patsubst %.cpp, %.o, $(MY_CPP_FILES))
CPPFLAGS = -g -Werror -D_GUN_SOURCE -Wfloat-equal -Wall -Wunused -Winline -pipe -D__VERSION_ID__="/"$(VERSION_ID)/""

TOPDIR = ../../../../../
CONF_DIR = ./conf/
SCRIPT_DIR = ./script/
OUTPUT_DIR = ./output/
ULLIB_PATH=$(TOPDIR)/lib2-64/ullib/
ECOMMON_PATH=$(TOPDIR)/app/ecom/elib/ecommon-lib/

INCLUDES = -I./ -I$(ULLIB_PATH)/include/ -I$(ECOMMON_PATH)/output/include/

LDFLAGS = -L./ -L$(ULLIB_PATH)/lib/ -L$(ECOMMON_PATH)/output/lib/ -lellib -lullib -lpthread -lcrypto -lz -lm

.PHONY: all
all: $(EXEC) output

$(EXEC) : $(MY_OBJ_FILES)
$(CXX) $(CPPFLAGS) -o $@ $^ $(INCLUDES) $(LDFLAGS)

%.o : %.cpp
$(CXX) $(CPPFLAGS) -c $< -o $@ $(INCLUDES)

.PHONY: output
output : $(EXEC)
if [ ! -d $(OUTPUT_DIR) ]; then $(MKDIR) $(OUTPUT_DIR); fi
if [ -d $(OUTPUT_DIR) ]; then $(RMDIR) $(OUTPUT_DIR)/*; fi
$(MKDIR) $(OUTPUT_DIR)/bin/;
$(MKDIR) $(OUTPUT_DIR)/conf/;
$(MKDIR) $(OUTPUT_DIR)/script/;
$(CP) $(EXEC) $(OUTPUT_DIR)/;
$(CP) $(CONF_DIR)/*.conf $(OUTPUT_DIR)/conf/;
$(CP) $(SCRIPT_DIR)/functions.sh $(OUTPUT_DIR)/script/;
$(CP) $(SCRIPT_DIR)/mpi_model_train.sh $(OUTPUT_DIR)/;
$(RM) *.o

.PHONY: clean
clean:
$(RM) *.o $(EXEC)
if [ -d $(OUTPUT_DIR) ]; then $(RMDIR) $(OUTPUT_DIR)/; fi

demo2:
export VERSION_ID=1.0.0.3

all     : clean
if [ ! -d output/ ];then mkdir output/;fi
if [ ! -d output/script ];then mkdir -p output/script;fi
if [ ! -d output/conf ];then mkdir -p output/conf/;fi
make -C r1_globalID
make -C r2_splitFile
make -C r3_localDict
make -C ins2id
make -C local2global
make -C r0_evalSort
cp tools/functions.sh output/script
cp tools/tools.sh output/script
cp tools/pack_and_submit.sh output/
cp distro_sign2ID_control.sh output/
cp mpi_sign2ID_control.sh output/
cp conf/*.conf output/conf/

clean :
make -C ins2id clean
make -C local2global clean
make -C r1_globalID clean
make -C r0_evalSort clean
make -C r2_splitFile clean
make -C r3_localDict clean
if [ -d output/ ];then rm -r output/;fi

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值