Makefile常用模板「建议收藏」

Makefile常用模板「建议收藏」做开发的特别是C/C++开发者一般都会用到Makefile,然而多数时候在公司做项目都不需要自己去写Makefile,仅仅停留在能看懂的基础上。因为make命令编译实在是太方便了,所以自己写写小项目用一用还是挺好的。网上关于Makefile教程也很多,总结一下近几年用到的常用脚本,方便自己查阅,如果能帮到别人那便是极好的^_^。单文件项目其实一个文件的项目也没必要写Makefil…

大家好,又见面了,我是你们的朋友全栈君。

做开发的特别是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;)

注意事项

  1. 规则语句前面是制表符TAB,写成空格会出错!
  2. 赋值符号:=基本赋值,:=覆盖之前的指,?=如果没有值则赋值,+=继续添加后面的值。

暂时没了,想到时候再补充,有任何问题欢迎留言讨论。

大型项目手写Makefile有点繁琐,建议使用cmake,可以参考 cmake CMakeLists.txt 常用模板

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/138517.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • JSON文件内容加注释的几种方法「建议收藏」

    JSON文件内容加注释的几种方法「建议收藏」JSON规范,不支持注释。之所以不允许加注释,主要是防止:过多的注释,影响了文件本身的数据载体的目的。有些文件,尤其是配置文件,加入解释说明一些数据项的含义,是有必要的。1、使用JSON5规范JSON5规范允许在JSON文件中加入注释:单行注释,多行注释均可。2、直接用json-schema,使用规范中的注释字段优点:功能强大缺点:json-s…

    2022年8月31日
    0
  • 演示:基于EIGRP的非等价负载平衡 (基本配置篇)

    演示:基于EIGRP的非等价负载平衡 (基本配置篇)

    2022年3月12日
    40
  • 并发编程之深入理解Condition

    并发编程之深入理解Condition

    2021年8月3日
    75
  • win7下vs2008过期没有输入序列号的解决办法[通俗易懂]

    win7下vs2008过期没有输入序列号的解决办法[通俗易懂]vs2008在win7下过期后,无法找到升级的序列号输入框。使用网上修改Setup\setup.sdb不得法,输入序列号却没有输入的地方。经过查找发现在win7下序列号输入框已被隐藏,使用打补丁方式可现实输入框。

    2022年8月10日
    9
  • Lena图像分解成小块与从小块合成

    Lena图像分解成小块与从小块合成 ➤01背景在2020年人工神经网络课程第一次作业第八题中需要对Lena图像使用AutoEncode网络进行压缩。将Lena(灰度图像)拆解成不同尺寸的大小形成训练压缩样本过程;或者从训练结果重新组合成Lena灰度图像是实验的基础。▲Lena灰度图像下面给出相关操作的Python程序和相关的结果。主要操作包括:将512×512的Lena灰度图片(0~255)分割成边长8~16的图像块,并通过行扫描形行向量;对图像进行归一化,形成数据在-0.5~0.5之

    2022年6月19日
    19
  • c语言数组定义(详细)「建议收藏」

    c语言数组定义(详细)「建议收藏」数组:什么是数组:变量的组合,是一种定义变量的手段。定义:类型数组名[数量];数组定义后,默认值同样不确定,因此也需要初始化。intarr[5]<==>intnum1,num2,num3,num4,num5;使用:数组名[编号]编号(下标)从0开始,范围[0,数量-1]遍历:配合for循环从头到尾显示,循环变量i就当做数组的下标。intarr[5];f…

    2022年7月22日
    7

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号