大家好,又见面了,我是你们的朋友全栈君。
做开发的特别是C/C++开发者一般都会用到Makefile,然而多数时候在公司做项目都不需要自己去写Makefile,仅仅停留在能看懂的基础上。因为make命令编译实在是太方便了,所以自己写写小项目用一用还是挺好的。网上关于Makefile教程也很多,总结一下近几年用到的常用脚本,方便自己查阅,如果能帮到别人那便是极好的_。
单文件项目
其实一个文件的项目也没必要写Makefile了,哈哈。便于理解就先从最基础的开始吧,Makefile实际上就是写有gcc等编译链接语句的脚本,加上一些可以缩写这些语句的规则。
假设有hello.c文件。
all: Hello
Hello:
gcc -o Hello hello.c
clean:
rm -rf Hello
多文件项目
假设一个工程下,有main.c和有多个.c源文件以及同名的.h头文件,虽然可以类似上述例子一样把每条gcc语句都写出来,但是这么就太啰嗦了。可以使用一些Makefile自带的规则简化着写。
# 方便起见一般都会先定义编译器链接器
CC = gcc
LD = gcc
# 正则表达式表示目录下所有.c文件,相当于:SRCS = main.c a.c b.c
SRCS = $(wildcard *.c)
# OBJS表示SRCS中把列表中的.c全部替换为.o,相当于:OBJS = main.o a.o b.o
OBJS = $(patsubst %c, %o, $(SRCS))
# 可执行文件的名字
TARGET = Hello
# .PHONE伪目标,具体含义百度一下一大堆介绍
.PHONY:all clean
# 要生成的目标文件
all: $(TARGET)
# 第一行依赖关系:冒号后面为依赖的文件,相当于Hello: main.o a.o b.o
# 第二行规则:$@表示目标文件,$^表示所有依赖文件,$<表示第一个依赖文件
$(TARGET): $(OBJS)
$(LD) -o $@ $^
# 上一句目标文件依赖一大堆.o文件,这句表示所有.o都由相应名字的.c文件自动生成
%.o:%.c
$(CC) -c $^
# make clean删除所有.o和目标文件
clean:
rm -f $(OBJS) $(TARGET)
多个文件,多个程序
这个用的比较少,网上的资料更少,当年我费了老大劲最终才找到这个方法。因为当时在一个目录下写了好多小程序,就是这个项目,可以点进去看一下。要把a.c/b.c/d.c都要编译成可执行文件a/b/c。
C_SRC = $(wildcard *.c)
C_OBJ = $(patsubst %c, %o, $(C_SRC))
# 目标文件也是多个
TARGETLIST = $(patsubst %.c, %, $(C_SRC))
.PHONY:all clean
# 这句不写规则的语句可以自动把相应的a.c b.c编译成a b,神奇~
all:${TARGETLIST}
clean:
rm -f ${TARGETLIST} *.o
指定头文件目录,库文件及目录
拿这个工程为例,工程需要用到libs目录下的libtomcrypt.a静态库和include目录下libtom的头文件。
CC = cc
LD = cc
SRCS = $(wildcard *.cpp)
OBJS = $(patsubst %cpp, %o, $(SRCS))
# -I指定头文件目录
INCLUDE = -I./include
# -L指定库文件目录,-l指定静态库名字(去掉文件名中的lib前缀和.a后缀)
LIB = -L./libs -ltomcrypt
# 开启编译warning和设置优化等级
CFLAGS = -Wall -O2
TARGET = LibtomDemo
.PHONY:all clean
all: $(TARGET)
# 链接时候指定库文件目录及库文件名
$(TARGET): $(OBJS)
$(LD) -o $@ $^ $(LIB)
# 编译时候指定头文件目录
%.o:%.cpp
$(CC) -c $^ $(INCLUDE) $(CFLAGS)
clean:
rm -f $(OBJS) $(TARGET)
遍历执行子目录下的Makefile
有这么个应用场景,当前目录下有多个子目录,且每个子目录下都有独立的Makefile文件,相当于目录下有多个独立的工程,现在需要执行make把各个子目录下的工程全部编译。
.PHONY:all clean
# 排除目录
exclude_dirs := .git
# 显示深度为1的子目录
dirs := $(shell find . -type d -maxdepth 1)
# 去掉获取到目录名称前面的./
dirs := $(basename $(patsubst ./%, %, $(dirs)))
# 过滤指定目录
dirs := $(filter-out $(exclude_dirs), $(dirs))
all:
$(foreach N,$(dirs),make -C $(N);)
clean:
$(foreach N,$(dirs),make -C $(N) clean;)
注意事项
- 规则语句前面是制表符TAB,写成空格会出错!
- 赋值符号:=基本赋值,:=覆盖之前的指,?=如果没有值则赋值,+=继续添加后面的值。
暂时没了,想到时候再补充,有任何问题欢迎留言讨论。
大型项目手写Makefile有点繁琐,建议使用cmake,可以参考 cmake CMakeLists.txt 常用模板。
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/138517.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...