长沙做网站好的公司,长春免费网站建站模板,公职人员可以做网站吗,wordpress支付功能简介 Makefile 是和 make 命令一起配合使用的#xff0c;很多大型项目的编译都是通过 Makefile 来组织的,。 我建立工程的方法有以下三点#xff1a; 1.makefile#xff1a; 优点#xff1a;使用非常广泛#xff0c;通用性强#xff0c;可跨平台。 缺点#xff1a;语法比… 简介 Makefile 是和 make 命令一起配合使用的很多大型项目的编译都是通过 Makefile 来组织的,。 我建立工程的方法有以下三点 1.makefile 优点使用非常广泛通用性强可跨平台。 缺点语法比较蛋疼。要写出一个通用便于管理且兼容性强的makefile比较困难。 2.cmake 优点简单易用使用较广泛方便管理可跨平台。 缺点自动生成的makefile太臃肿。 3.sh脚本 优点自由高度定制。简单易用可操作性强。方便维护。甚至还可以生成makefile 缺点sh建的工程太少了估计没人这么搞吧 但我考虑到方便移植和管理其他人的工程还是选择了第一种以makefile建立管理工程。其实我的内心是比较向往第三种sh脚本建工程的。下面来介绍下makefile的规则以及语法 PS:我本意是想写短一点的只是想写点常用的东西方便大家查阅。精炼了这么久可还有这么多内容15000字。所以大家还是耐心的学习吧想学好linux这是必不可少的一步。 规则 说明 target1 target2.... : prerequisites1 prerequisites2... [TAB] command1 [TAB] command2 ... target可以是一个object file(目标文件)也可以是一个执行文件还可以是一个标签label。对于标签这种特性在后续的“伪目标”章节中会有叙述。 prerequisites就是要生成那个target所需要的文件或是目标。 command也就是make需要执行的命令。任意的shell命令 这是一个文件的依赖关系也就是说target这一个或多个的目标文件依赖于prerequisites中的文件其生成规则定义在 command中。说白一点就是说prerequisites中如果有一个以上的文件比target文件要新的话command所定义的命令就会被执行。这就是makefile的规则。也就是makefile中最核心的内容。 经典示例 原始版本 objects main.o kbd.o command.o display.o \insert.o search.o files.o utils.oedit : $(objects)cc -o edit $(objects)
main.o : main.c defs.hcc -c main.c
kbd.o : kbd.c defs.h command.hcc -c kbd.c
command.o : command.c defs.h command.hcc -c command.c
display.o : display.c defs.h buffer.hcc -c display.c
insert.o : insert.c defs.h buffer.hcc -c insert.c
search.o : search.c defs.h buffer.hcc -c search.c
files.o : files.c defs.h buffer.h command.hcc -c files.c
utils.o : utils.c defs.hcc -c utils.c
clean :rm edit $(objects)自动推导版本 objects main.o kbd.o command.o display.o \insert.o search.o files.o utils.occ gccedit : $(objects)cc -o edit $(objects)main.o : defs.h
kbd.o : defs.h command.h
command.o : defs.h command.h
display.o : defs.h buffer.h
insert.o : defs.h buffer.h
search.o : defs.h buffer.h
files.o : defs.h buffer.h command.h
utils.o : defs.h.PHONY : clean
clean :rm edit $(objects)理解 1.内容展开 list_a 1.a 2.a
list_b 1.b 2.b 3.b#list_a中的元素每次单个展开连接list_b中的所有元素
#结果如下
test:list_a
%.a:list_b #展开1.a1.b 2.b 3.b #此时1.a $1.b 2.b 3.b2.a1.b 2.b 3.b #此时2.a $1.b 2.b 3.b#内容还可以继续展开
%.b:%.x #自动推导展开1.b:1.x2.b:2.x3.b:3.x2.include 相当于将内容复制展开export可以共享全局变量。 3.用make遍历子目录makefile时相当于用新进程开启make。因此export不能共享全局变量。 注意 1.注意空格与TAB有些编辑器会自动将TAB转换成4个空格难以发现 2.注意 与 : 的区别 包括export 在内的所有变量都不能共享 如果使用cd make进行遍历。那么最好转换成绝对路径 3.如果使用cd make进行遍历。那么最好转换成绝对路径 语法 1.符号 1) 命令前缀 [不用前缀 ]输出执行的命令以及命令执行的结果, 出错的话停止执行 [前缀 ]只输出命令执行的结果, 出错的话停止执行 [前缀 -]命令执行有错的话, 忽略错误, 继续执行 2) 通配符 *表示任意一个或多个字符? 表示任意一个字符[...] [abcd] 表示a,b,c,d中任意一个字符, [^abcd]表示除a,b,c,d以外的字符, [0-9]表示 0~9中任意一个数字 3) 自动变量 在下文的 自动变量 4) 赋值 与 : 相同点都是给内容赋值 区别与Verilog的和类似。 其中 和 : 的区别在于 : 只能使用前面定义好的变量, 可以使用后面定义的变量 赋值符号 [] 最后再赋值 # Makefile内容
OBJS2 $(OBJS1) programC.o
OBJS1 programA.o programB.oall:echo $(OBJS2)# bash中执行 make, 可以看出虽然 OBJS1 是在 OBJS2 之后定义的, 但在 OBJS2中可以提前使用
$ make
programA.o programB.o programC.o赋值符号 [:] : 立即赋值 # Makefile内容
OBJS2 : $(OBJS1) programC.o
OBJS1 : programA.o programB.oall:echo $(OBJS2)# bash中执行 make, 可以看出 OBJS2 中的 $(OBJS1) 为空
$ make
programC.o赋值符号 [] 变量追加值 # Makefile内容
SRCS : programA.c programB.c programC.c
SRCS programD.call:echo SRCS: $(SRCS)# bash中运行make
$ make
SRCS: programA.c programB.c programC.c programD.c5) 伪目标 .PHONY .PHONY : clean
clean :-rm edit $(objects)2. 隐含规则 1) 自动推倒命名 编译C时*.o 的目标会自动推导为 *.c 2) 隐含变量 [RM] rm -f [AR] ar [CC] cc [CXX] g [ARFLAGS] AR命令的参数 [CFLAGS] 语言编译器的参数 [CXXFLAGS] C语言编译器的参数 3) 自动变量 [$] 目标集合 [$%] 当目标是函数库文件时, 表示其中的目标文件名 [$] 第一个依赖目标. 如果依赖目标是多个, 逐个表示依赖目标 [$?] 比目标新的依赖目标的集合 [$^] 所有依赖目标的集合, 会去除重复的依赖目标 [$] 所有依赖目标的集合, 不会去除重复的依赖目标 [$*] 这个是GNU make特有的, 其它的make不一定支持 1.o: 1.cecho $ : $ # bash中执行 make:
1.o : 1.c3.定义 不限于makefile还有部分shell指令 1) 查看依赖关系 gcc -MM $ gcc -MM kvm_main.c
kvm_main.o: kvm_main.c iodev.h coalesced_mmio.hasync_pf.h #这句就可以加到 Makefile 中作为编译 kvm_main.o 的依赖关系2) 定义命令包 define command-name command ... endef # Makefile 内容
define run-hello-makefile
echo -n Hello
echo Makefile!
echo 这里可以执行多条 Shell 命令!
endefall:$(run-hello-makefile)# bash 中运行make
$ make
Hello Makefile!
这里可以执行多条 Shell 命令!3) 条件判断 # Makefile 内容
all:
ifeq (aa, bb)echo equal
elseecho not equal
endif# bash 中执行 make
$ make
not equal4) 自定义函数 $(call expression,parm1,parm2,parm3...) # Makefile 内容
hello hello $(1) worldall:echo $(call hello,我是参数1)# bash 中执行 make
$ make
hello 我是参数1 world5) 执行shell指令 $(shell shell command) 与 shell command 作用:执行一个shell命令, 并将shell命令的结果作为返回.注意 是反引号(英文状态下键盘的ESC下面那个键) 4.函数 不限于makefile还有部分shell指令 1) 传参同一个进程 export export EX_VAR value
export EX_VAR : value
export EX_VAR value
# : 与上面的描述基本相同注意是同一个进程下的make才有用。当多级遍历make时是无法全局的。 2) 字符串处理 (1) 字符串替换函数 $( substsource,new,text) 功能: 把字符串text 中的source 替换为new 返回: 替换过的字符串 # Makefile 内容
all:echo $(subst t,e,maktfilt) -- 将t替换为e# bash 中执行 make
$ make
makefile(2) 字符串中每个元素替换函数 $( patsubst source,new,text) 功能: 把字符串 text 中的的每个元素 source 替换为new 返回: 替换过的字符串 # Makefile 内容
all:echo $(patsubst %.c,%.o,programA.c programB.c)# bash 中执行 make
$ make
programA.o programB.o(3) 去空格函数 $(strip text) 功能: 去掉 string 字符串中开头和结尾的空字符 返回: 被去掉空格的字符串值 # Makefile 内容
VAL : aa bb cc all:echo 去除空格前: $(VAL)echo 去除空格后: $(strip $(VAL))# bash 中执行 make
$ make
去除空格前: aa bb cc
去除空格后: aa bb cc(4) 判断字符串内是否存在特定字符串 $(findstringtext,elem) 功能: 在字符串 text 中查找 elem 字符串是否存在 返回: 如果找到, 返回 elem 字符串, 否则返回空字符串 # Makefile 内容
VAL : aa bb cc all:echo $(findstring aa,$(VAL))echo $(findstring ab,$(VAL))# bash 中执行 make
$ make
aa3) 文件元素相关 (1) 取文件函数 保留符合条件的元素 $(filter elem1 elem2...,text) # Makefile 内容
all:echo $(filter %.o %.a,program.c program.o program.a)# bash 中执行 make
$ make
program.o program.a
program.c去掉符合条件的元素 $(filter-out elem1 elem2...,text) # Makefile 内容
all:echo $(filter-out %.o %.a,program.c program.o program.a)# bash 中执行 make
$ make
program.c获取该目录下所有文件 获取该目录下所有.x文件 $(wildcard *.x) # Makefile 内容
all:echo $(wildcard *.c)# bash 中执行 make
$ make
a.x b.x c.x(2) 路径函数 去掉路径 $(notdir elem elem...) 功能: 去掉序列的路径 返回: 文件名序列 elem 中的非目录部分 # Makefile 内容
all:echo $(notdir /home/a.c ./bb.c ../c.c d.c)# bash 中执行 make
$ make
a.c bb.c c.c d.c取路径 $(dir elem1 elem2...) 功能: 从文件名序列 elem 中取出目录部分 返回: 文件名序列 elem 中的目录部分 # Makefile 内容
all:echo $(dir /home/a.c ./bb.c ../c.c d.c)# bash 中执行 make
$ make
/home/ ./ ../ ./(3) 取前后缀 取后缀函数 $(suffix elem1 elem2...) 功能: 从文件名序列 elem 中取出各个文件名的后缀 返回: 文件名序列 elem 中各个文件名的后缀, 没有后缀则返回空字符串 # Makefile 内容
all:echo $(suffix /home/a.c ./b.o ../c.a d)# bash 中执行 make
$ make
.c .o .a取前缀函数 $(basename elem1 elem2...) 功能: 从文件名序列 elem 中取出各个文件名的前缀 返回: 文件名序列 elem 中各个文件名的前缀, 没有前缀则返回空字符串 # Makefile 内容
all:echo $(basename /home/a.c ./b.o ../c.a /home/.d .e)# bash 中执行 make
$ make
/home/a ./b ../c /home/(3) 增添前后缀 增添后缀函数 $(addsuffix suffix,elem1 elem2...) 功能: 把后缀 suffix 加到 elem 中的每个单词后面 返回: 加过后缀的文件名序列 # Makefile 内容
all:echo $(addsuffix .c,/home/a b ./c.o ../d.c)# bash 中执行 make
$ make
/home/a.c b.c ./c.o.c ../d.c.c增添前缀函数 $(addprefix prefix, elem1 elem2...) 功能: 把前缀 prefix 加到 elem 中的每个单词前面 返回: 加过前缀的文件名序列 # Makefile 内容
all:echo $(addprefix test_,/home/a.c b.c ./d.c)# bash 中执行 make
$ make
test_/home/a.c test_b.c test_./d.c我写的管理大型项目的makefile 以下内容为基础版本。可以混编C和C。 但没有加入平台兼容性验证等功能。 在ubuntu16.04下测试通过。 tree
.
├── app
│ ├── app1
│ │ ├── main.c
│ │ └── makefile
│ └── makefile
├── make_conf.mk
├── makefile
├── make_fun.mk
├── module
│ ├── makefile
│ └── test
│ ├── drive
│ │ ├── cpp_test.cpp
│ │ ├── cpp_test.h
│ │ ├── test.c
│ │ └── test.h
│ ├── hal
│ │ ├── test_hal.c
│ │ └── test_hal.h
│ └── makefile
└── output├── bin│ ├── app1.bin│ └── app2.bin├── lib│ └── libobj.a└── obj├── app│ ├── app1│ │ └── main.o│ └── app2│ └── main.o└── module└── test├── drive│ ├── cpp_test.o│ └── test.o└── hal└── test_hal.o17 directories, 22 files顶层 makefile # -------------------------------------------
# FileName :makefile
# Author :wind
# Date :2018-1-16
# Description
#
# Top makefile.
#
# ------------------------------------------- # 设置当前路径
DIR_ROOT:.# 设置递归子目录
DIR_LIST_SUB :module appinclude $(DIR_ROOT)/make_conf.mk
all:make_root
clean:make_clean
include $(DIR_ROOT)/make_fun.mk中间遍历层 makefile # -------------------------------------------
# FileName :xx/makefile
# Author :wind
# Date :2018-1-16
# Description
#
# Level1 makefile.
#
# ------------------------------------------- # 设置当前路径
DIR_ROOT:..# 添加递归子目录
DIR_LIST_SUB :\
app1\
app2\# 添加源文件
FILE_LIST_C \FILE_LIST_CPP \FILE_LIST_S \# 添加头文件路径
DIR_LIST_INCLUDE\include $(DIR_ROOT)/make_conf.mk
all:make_show make_subdir
clean:make_clean
include $(DIR_ROOT)/make_fun.mk app的makefile # -------------------------------------------
# FileName :xx/xx/makefile
# Author :wind
# Date :2018-1-16
# Description
#
# Level2 makefile.
#
# ------------------------------------------- # 设置当前路径
DIR_ROOT:../..# 添加递归子目录
DIR_LIST_SUB :\# 添加源文件
FILE_LIST_C \
main.c\FILE_LIST_CPP \FILE_LIST_S \# 添加头文件路径
DIR_LIST_INCLUDE\
$(DIR_ROOT)/module/test/hal\
$(DIR_ROOT)/module/test/drive\include $(DIR_ROOT)/make_conf.mk
all:make_show make_app
clean:make_clean
include $(DIR_ROOT)/make_fun.mk drive的makefile # -------------------------------------------
# FileName :xx/xx/makefile
# Author :wind
# Date :2018-1-16
# Description
#
# Level2 makefile.
#
# ------------------------------------------- # 设置当前路径
DIR_ROOT:../..# 添加递归子目录
DIR_LIST_SUB :\# 添加源文件
FILE_LIST_C \
drive/test.c\
hal/test_hal.c\FILE_LIST_CPP \
drive/cpp_test.cpp\FILE_LIST_S \# 添加头文件路径
DIR_LIST_INCLUDE\
hal\
drive\include $(DIR_ROOT)/make_conf.mk
all:make_show make_lib_a
clean:make_clean
include $(DIR_ROOT)/make_fun.mk 配置文件 make_conf.mk # -------------------------------------------
# FileName :make_set.inc
# Author :wind
# Date :2018-1-16
# Description
#
# 工程相关设置。
#
# -------------------------------------------# 设置常用指令
# -------------------------------------------
RM rm -f
MV mv -f
MKDIR mkdir -p
RMDIR rm -rf # 颜色输出
# -------------------------------------------
ECHO_END:\033[0m
ECHO_GREEN:echo \033[32m
ECHO_RED:echo \033[31m
ECHO_YELLOW:echo \033[33m
ECHO_BLUE:echo \033[34m
ECHO_GREEN_YELLOW:echo \033[42;30m# 编译缺省设置
# -------------------------------------------# 默认编译
CXX:g#编译选项
COMPILE_C ? $(CXX)
COMPILE_CXX ? $(CXX)
COMPILE_ASM ? $(CXX)
COMPILE_AR ? ar# 设置优化等级
OPT ?0# 设置警告开关
COMPILE_WARN ? -Wall # 设置静态编译
COMPILE_STATIC ? -s# 在环境基础下添加设置
CFLAGS $(DIR_LIST_INCLUDE_I) $(COMPILE_WARN) -O$(OPT) $(COMPILE_STATIC)
CXXFLAGS $(DIR_LIST_INCLUDE_I) $(COMPILE_WARN) -O$(OPT) $(COMPILE_STATIC)
ASFLAGS -Wa,-adhlns$(:.S.lst),-gstabs $(DIR_LIST_INCLUDE_I)# 编译设置汇总
COMPILE_CFLAGS $(CFLAGS)
COMPILE_CXXFLAGS $(CXXFLAGS)
COMPILE_ASFLAGS $(ASFLAGS)#链接选项
LDFLAGS -lstdc#编译C
LDFLAGS -lpthread#使用了线程
LDFLAGS -fPIC#编译为位置独立的代码
LDFLAGS -ldl#引用动态库
LDFLAGS $(DIR_LIST_INCLUDE_I)#引用其他静态库
FILE_LIST_LIB_A\ 功能文件 make_fun.mk # -------------------------------------------
# FileName :make_fun.mk
# Author :wind
# Date :2018-1-16
# Description
#
# 实际编译过程。
#s
# ------------------------------------------- # 路径关系
# -------------------------------------------
DIR_ROOT_REAL$(realpath $(DIR_ROOT))
NAME_MODULE : $(notdir $(CURDIR))#所在的文件夹名称
DIR_OUTPUT:$(DIR_ROOT)/output
DIR_BIN:$(DIR_OUTPUT)/bin
DIR_OBJ:$(DIR_OUTPUT)/obj
DIR_LIB:$(DIR_OUTPUT)/lib# 路径处理成可用参数
# -------------------------------------------
DIR_LIST_INCLUDE_I:$(addprefix -I,$(DIR_LIST_INCLUDE))#添加编译选项-I
DIR_LIST_SUB:$(addprefix $(CURDIR)/,$(DIR_LIST_SUB))#转换成绝对路径
DIR_CURDIR:$(subst $(DIR_ROOT_REAL),,$(CURDIR))#相对路径
DIR_OBJ_OUT:$(DIR_OBJ)$(DIR_CURDIR)#文件处理
FILE_LIST_OBJ:$(FILE_LIST_C:%.c%.o)
FILE_LIST_OBJ$(FILE_LIST_CPP:%.cpp%.o)
FILE_LIST_OBJ$(FILE_LIST_S:%.s%.o)FILE_LIST_OBJ:$(addprefix $(DIR_OBJ_OUT)/,$(FILE_LIST_OBJ))#转换成带绝对路径的中间文件
FILE_LIB_A:$(DIR_LIB)/libobj.a
FILE_LIST_LIB_APP:$(DIR_BIN)/$(NAME_MODULE).bin# 函数库
# -------------------------------------------
make_root:make_start make_subdir make_end# 工程开始
make_start:$(ECHO_BLUE)\t-----------------------------$(ECHO_END)$(ECHO_BLUE)\t-\t [编译开始] \t -$(ECHO_END)$(ECHO_BLUE)\t-----------------------------$(ECHO_END)$(ECHO_BLUE)[COMPILE_C]$(COMPILE_C) [COMPILE_CFLAGS]$(COMPILE_CFLAGS)$(ECHO_END)$(ECHO_BLUE)[COMPILE_CXX]$(COMPILE_CXX) [COMPILE_CXXFLAGS]$(COMPILE_CXXFLAGS)$(ECHO_END)$(ECHO_BLUE)[COMPILE_ASM]$(COMPILE_ASM) [COMPILE_ASFLAGS]$(COMPILE_ASFLAGS)$(ECHO_END)$(ECHO_BLUE)[COMPILE_AR]$(COMPILE_AR) [LDFLAGS]$(LDFLAGS)$(ECHO_END)$(ECHO_BLUE)[OPT]$(OPT) $(ECHO_END)$(ECHO_BLUE)[COMPILE_STATIC]$(COMPILE_STATIC) $(ECHO_END)$(ECHO_BLUE)[FILE_LIST_LIB_A]$(FILE_LIST_LIB_A) $(ECHO_END)# 工程完成
make_end: $(ECHO_BLUE)[编译完成]$(ECHO_END) # 递归子目录
make_subdir:for list in $(DIR_LIST_SUB);\do\cd $$list make all|| exit 1;\done# 生成可执行文件
make_app:make_lib_a make_bin# 生成静态链接库
make_lib_a:make_obj$(MKDIR) dirname $(FILE_LIB_A)$(ECHO_YELLOW)[$(COMPILE_AR)]-rcs $(FILE_LIB_A) $(FILE_LIST_OBJ)$(ECHO_END)$(COMPILE_AR) -rcs $(FILE_LIB_A) $(FILE_LIST_OBJ)# 链接
make_bin:$(FILE_LIST_LIB_APP)# 编译
make_obj:$(FILE_LIST_OBJ)# 清除
make_clean:$(RMDIR) $(DIR_OUTPUT)# 显示参数方便调试
make_show:$(ECHO_GREEN_YELLOW)[DIR_CURDIR] $(DIR_CURDIR) $(ECHO_END)$(ECHO_GREEN)[FILE_LIST_C] $(FILE_LIST_C) $(ECHO_END)$(ECHO_GREEN)[DIR_LIST_INCLUDE] $(subst $(DIR_ROOT)/,[DIR_ROOT]/,$(DIR_LIST_INCLUDE)) $(ECHO_END)# 文件操作过程
# ------------------------------------------- # 编译过程成中间文件
$(DIR_OBJ_OUT)/%.o: %.c$(MKDIR) dirname $$(ECHO_YELLOW)[$(COMPILE_C)]$ -o $ $(ECHO_END)$(COMPILE_C) -c $(COMPILE_CFLAGS) $ -o $$(DIR_OBJ_OUT)/%.o: %.cpp$(MKDIR) dirname $$(ECHO_YELLOW)[$(COMPILE_CXX)]$ -o $ $(ECHO_END)$(COMPILE_CXX) -c $(COMPILE_CXXFLAGS) $ -o $$(DIR_OBJ_OUT)/%.o: %.s$(MKDIR) dirname $$(ECHO_YELLOW)[$(COMPILE_C)]$ -o $ $(ECHO_END)$(COMPILE_ASM) -c $(COMPILE_ASFLAGS) $ -o $# 链接成二进制文件
$(FILE_LIST_LIB_APP): $(FILE_LIB_A)$(MKDIR) dirname $$(ECHO_YELLOW)[$(COMPILE_C)]$ -o $ $(ECHO_END)$(COMPILE_C) $(LDFLAGS) -L$(DIR_LIB) -lobj $ $(FILE_LIST_LIB_A) -o $ 内容推荐 跟我一起写MakefileMakefile 使用总结项目实用makefileMakefile之大型工程项目子目录Makefile的一种通用写法 引用本地址 https://www.cnblogs.com/wittxie/p/9836097.html 转载于:https://www.cnblogs.com/wittxie/p/9836097.html