当前位置: 首页 > web >正文

《C++——makefile》

一、Makefile 是什么

Makefile 是一个包含了一系列规则的文件,这些规则告诉 make 工具如何编译和链接程序。make 工具会根据 Makefile 中的规则,判断哪些文件需要重新编译,然后执行相应的命令,最终生成可执行文件或库。

二、基本规则格式

Makefile 的基本规则格式如下:

目标: 依赖命令
  • 目标:可以是可执行文件、目标文件,也可以是一个动作如 clean,可以理解为最后要生成的是什么。
  • 依赖:生成目标所需要的文件或其他目标。
  • 命令:生成目标所需要执行的命令(需要以 Tab 键开头)。

例如,我们有一个简单的 hello.cpp 文件,要编译它生成可执行文件 hello,可以写这样的规则:

hello: hello.cppg++ hello.cpp -o hello

在这里插入图片描述

三、变量的使用

在 Makefile 中,我们可以使用变量来简化书写,尤其是当编译选项、文件列表等需要重复使用时。

我们可以自定义变量来表示编译选项、源文件列表等。例如:

# 定义编译器
CXX = g++
# 定义编译选项
CXXFLAGS = -std=c++11 -Wall
# 定义源文件列表
SRCS = hello.cpp world.cpp
# 定义目标文件列表,将源文件的 .cpp 替换为 .o
OBJS = $(SRCS:.cpp=.o)
# 定义可执行文件名
TARGET = my_program

可以理解为给这个文件定义了一个集合别名,就像模板一样

然后在规则中使用这些变量:

$(TARGET): $(OBJS)$(CXX) $(CXXFLAGS) $^ -o $@
%.o: %.cpp$(CXX) $(CXXFLAGS) -c $< -o $@

这里 $^ 表示所有的依赖文件,$< 表示第一个依赖文件,$@ 表示目标文件。

如果不用自定义:

# 最终可执行文件
my_program: hello.o world.og++ -std=c++11 -Wall hello.o world.o -o my_program# 编译hello.o
hello.o: hello.cppg++ -std=c++11 -Wall -c hello.cpp -o hello.o# 编译world.o
world.o: world.cppg++ -std=c++11 -Wall -c world.cpp -o world.o

怎么比自定义还短?那我用自定义不是多此一举吗?
虽然在极简单的小项目中,直接写命令可能看起来更短,但当项目规模扩大、需求变化时,自定义变量的优势会非常明显,就如c++中的#define,typedef一样,在上千上万行代码里,一个一个去更改变量,不如提前定义好只需要修改定义的部分就行

四、多目标与伪目标

如果我们有多个可执行文件需要编译,可以在 Makefile 中定义多个目标。例如,我们有 server、client 两个可执行文件:

CXX = g++
CXXFLAGS = -std=c++11 -Wall
LDFLAGS = -lpthreadSERVER_SRCS = server.cpp
CLIENT_SRCS = client.cppSERVER_OBJS = $(SERVER_SRCS:.cpp=.o)
CLIENT_OBJS = $(CLIENT_SRCS:.cpp=.o)all: server clientserver: $(SERVER_OBJS)$(CXX) $(CXXFLAGS) $^ -o $@ $(LDFLAGS)
client: $(CLIENT_OBJS)$(CXX) $(CXXFLAGS) $^ -o $@ $(LDFLAGS)%.o: %.cpp$(CXX) $(CXXFLAGS) -c $< -o $@.PHONY: clean
clean:rm -f server client $(SERVER_OBJS) $(CLIENT_OBJS)

在这里插入图片描述

这里使用了伪目标.PHONY: clean
伪目标不是一个实际的文件,而是一个动作的标识。最常见的伪目标是 clean,用于清理编译生成的文件。我们需要用 .PHONY 来声明伪目标,防止项目中存在同名文件时 make 误判。例如上面的 clean 目标,执行 make clean 会删除生成的可执行文件和目标文件。

五、实战

CFLAG= -std=c++11 -I ../../build/release-install-cpp11/include/
LFLAG= -L../../build/release-install-cpp11/lib  -lmuduo_net -lmuduo_base -pthread
all: server client text
server: server.cppg++  $(CFLAG) $^ -o $@ $(LFLAG)
client: client.cppg++  $(CFLAG) $^ -o $@ $(LFLAG)
text: text.cppg++  $(CFLAG) $^ -o $@ $(LFLAG).PHONY:clean
clean:rm -f server client
  1. 变量定义:
    CFLAG:编译选项,指定 C++11 标准和第三方库(如 muduo)的头文件路径。
    LFLAG:链接选项,指定库文件路径及需要链接的库(muduo 网络库、基础库和线程库)。
  2. 目标规则:
    默认目标 all 会依次编译 server、client、text 三个可执行文件。
    每个目标对应一个 .cpp 源文件,通过统一的 g++ 命令编译,利用 $^(依赖文件)和 $@(目标文件)简化书写。
  3. 清理操作:
    clean 伪目标用于删除编译生成的可执行文件,但当前缺少对 text 的清理,需补充以避免残留。

通用 Makefile 模板:

# 编译器与选项
CXX = g++
CXXFLAGS = -std=c++11 -Wall -g
LDFLAGS = # 链接库(如需要可添加-lpthread -lm等)# 项目文件
TARGET = main
SRCS = $(wildcard *.cpp)
OBJS = $(SRCS:.cpp=.o)# 默认编译
all: $(TARGET)# 链接
$(TARGET): $(OBJS)$(CXX) $^ -o $@ $(LDFLAGS)# 编译
%.o: %.cpp$(CXX) $(CXXFLAGS) -c $< -o $@# 清理
clean:rm -f $(OBJS) $(TARGET)# 伪目标
.PHONY: all clean

一般只需要:

  • 改文件名:修改TARGET的值
  • 加库:在LDFLAGS后添加(如-L/path -lmuduo)
  • 改标准:调整CXXFLAGS中的-std=c++11(如c++17)

如果需要分开执行文件,可以不需要编译,生成多个执行文件

http://www.xdnf.cn/news/19391.html

相关文章:

  • 三重积分的性质
  • 【MATLAB绘图进阶教程】(2-6)动态绘图制作详解与例程,包括drawnow、pause、getframe、video write等命令
  • 机器学习时间序列算法进行随机划分数据是不合适的!
  • Dify1.8.0最新版本安装教程:Ubuntu25.04系统本地化安装部署Dify详细教程
  • 移动零,leetCode热题100,C++实现
  • IP-Guard支持修改安全区域密级文字和密级级数
  • 嵌入式学习日记(38)HTTP
  • Java学习笔记-多线程基础
  • Kafka 4.0 生产者配置全解析与实战调优
  • Go语言流式输出实战:构建高性能实时应用
  • 数据结构(力扣刷题)
  • 蜂窝通信模组OpenCPU的介绍
  • REST-assured获取响应数据详解
  • 手写链路追踪优化-自动全局追踪代替局部手动追踪
  • 做一个实用的节假日工具
  • Java面试-spring boot框架
  • 98、23种设计模式之代理模式(7/23)
  • 【SpringMVC】SSM框架【二】——SpringMVC超详细
  • ModuleNotFoundError: No module named ‘cairosvg‘
  • 浔川社团阅读量破历史记录
  • 得物25年春招-安卓部分编程题
  • GD32入门到实战21--输入捕获
  • 【C++】日期类实现详解:代码解析与复用优化
  • C#正则表达式与用法
  • 【基础-单选】关于Tabs组件页签的位置设置,下面描述错误的是
  • 免费在线图片合成视频工具 ,完全免费
  • uni.onBLECharacteristicValueChange接收到数据,返回的value为{}的原因及其获取方法
  • 佳易王钟表维修养护管理系统:开启钟表维修高效管理新篇章​就#软件操作教程
  • Mysql 学习day 2 深入理解Mysql索引底层数据结构
  • React前端开发_Day6-Day9_极客园项目