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

上层 Makefile 控制下层 Makefile 的方法

在复杂的项目中,通常会将项目划分为多个模块或子项目,每个模块都有自己的 Makefile。上层 Makefile 的作用是协调和控制这些下层 Makefile 的构建过程。下面是几种常见的示例,实现上层 Makefile 对下层 Makefile 的控制。

  1. 直接调用:通过 $(MAKE) 或 make 命令直接调用下层 Makefile

  2. 传递变量:通过环境变量或命令行参数将变量传递给下层 Makefile

  3. 递归构建:通过递归调用 make 命令构建所有模块。

  4. 导入规则:通过 include 指令导入下层 Makefile 的规则和变量。


目录

一个实际例子

1.工程目录结构

2.主目录Makefile内容

3.Service目录的Makefile

4.Client目录的Makefile 

方法 1:直接调用下层 Makefile

示例项目结构

上层 Makefile 示例

下层 Makefile 示例(module1/Makefile)

使用说明

方法 2:传递变量给下层 Makefile

上层 Makefile 示例

下层 Makefile 示例(module1/Makefile)

使用说明

方法 3:使用递归构建

上层 Makefile 示例

下层 Makefile 示例(module1/Makefile)

使用说明

方法 4:使用 include 导入下层 Makefile

上层 Makefile 示例

下层 Makefile 示例(module1/Makefile)

使用说明

总结


一个实际例子

1.工程目录结构

├── ChatRoom
│   ├── Client
│   │   ├── Client.c
│   │   ├── Makefile
│   │   ├── Tcp_Sock.c
│   │   ├── Tcp_Sock.h
│   │   ├── main
│   │   └── obj
│   └── Service
│       ├── Makefile
│       ├── Service.c
│       ├── Tcp_Sock.c
│       ├── Tcp_Sock.h
│       ├── main
│       └── obj
├── Makefile

2.主目录Makefile内容

简单版本:

SUBDIR1 = ChatRoom/Service
SUBDIR2 = ChatRoom/Client
SUBDIRS = $(SUBDIR1) $(SUBDIR2)
 
.PHONY: all clean $(SUBDIRS)
 
all: $(SUBDIRS)
 
$(SUBDIRS):
	$(MAKE) -C $@
 
clean:
	for dir in $(SUBDIRS); \
	do \
		$(MAKE) -C $$dir clean; \
	done
# 定义模块路径
##################################
########用户配置区#################
MODULE1 = ChatRoom/Client
MODULE2 = ChatRoom/Service

MODULE1_TARGET = $(MODULE1)/main
MODULE2_TARGET = $(MODULE2)/main

MODULES = $(MODULE1) $(MODULE2)
MODULES_TARGET = $(MODULE1_TARGET) $(MODULE2_TARGET)
##################################
# 默认目标
all: $(MODULES_TARGET)

# 构建模块
$(MODULE1_TARGET): $(MODULE1)
	@echo "正在编译模块:$(MODULE1)"
	$(MAKE) -C $(MODULE1) all

$(MODULE2_TARGET): $(MODULE2)
	@echo "正在编译模块:$(MODULE2)"
	$(MAKE) -C $(MODULE2) all

# 清理所有模块
clean:
	$(MAKE) -C $(MODULE1) clean
	$(MAKE) -C $(MODULE2) clean
	rm -f $(MODULE1_TARGET) $(MODULE2_TARGET)

# 帮助信息
help:
	@echo "可用命令:"
	@echo "  make          编译所有模块"
	@echo "  make clean    清理所有模块"
	@echo "  make help     查看帮助信息"

3.Service目录的Makefile

CC = gcc
SCRC = $(wildcard *.c)
OBJS_DIR = ./obj
OBJ = $(SCRC:%.c=$(OBJS_DIR)/%.o)
CFLAGS = -Wall -O2
LDFLAGS = -lpthread
TARGET = main

# 默认目标
all: $(TARGET)

$(TARGET):$(OBJ)
	$(CC) $^ -o $@ $(LDFLAGS)
$(OBJS_DIR)/%o:%c
	@mkdir -p $(OBJS_DIR)
	$(CC) $< -o $@	$(CFLAGS) -c 
	

echo:
	@echo $(OBJ)

clean:
	rm -rf ./obj

.PHONY:clean
.PHONY:echo

4.Client目录的Makefile 

CC = gcc
SCRC = $(wildcard *.c)
OBJS_DIR = ./obj
OBJ = $(SCRC:%.c=$(OBJS_DIR)/%.o)
CFLAGS = -Wall -O2
LDFLAGS = -lpthread
TARGET = main

# 默认目标
all: $(TARGET)

$(TARGET):$(OBJ)
	$(CC) $^ -o $@ $(LDFLAGS)
$(OBJS_DIR)/%o:%c
	@mkdir -p $(OBJS_DIR)
	$(CC) $< -o $@	$(CFLAGS) -c 
	

echo:
	@echo $(OBJ)

clean:
	rm -rf ./obj

.PHONY:clean
.PHONY:echo

方法 1:直接调用下层 Makefile

上层 Makefile 可以通过 $(MAKE) 或 make 命令直接调用下层 Makefile。这种方法简单且灵活。

示例项目结构
project/
├── Makefile         # 上层 Makefile
├── module1/
│   ├── Makefile     # 下层 Makefile
│   └── *.c
├── module2/
│   ├── Makefile     # 下层 Makefile
│   └── *.c
└── main.c
上层 Makefile 示例
# 定义下层模块的路径
MODULE1 = module1
MODULE2 = module2

# 定义所有模块
MODULES = $(MODULE1) $(MODULE2)

# 默认目标
all: $(MODULES)

# 构建模块
$(MODULES):
    $(MAKE) -C $@

# 清理所有模块
clean:
    $(MAKE) -C $(MODULE1) clean
    $(MAKE) -C $(MODULE2) clean
    rm -f main

# 帮助信息
help:
    @echo "可用命令:"
    @echo "  make          编译所有模块"
    @echo "  make clean    清理所有模块"
    @echo "  make help     查看帮助信息"
下层 Makefile 示例(module1/Makefile
# 定义编译器
CC = gcc

# 定义目标文件
TARGET = module1.o

# 定义源文件
SRC = module1.c

# 编译选项
CFLAGS = -g -Wall

# 默认目标
all: $(TARGET)

# 生成目标文件
$(TARGET):
    $(CC) $(CFLAGS) -c $(SRC) -o $(TARGET)

# 清理
clean:
    rm -f $(TARGET)
使用说明
  1. 编译所有模块

                上层 Makefile 会依次调用 module1/Makefile 和 module2/Makefile 进行编译。

make
  1. 清理所有模块

    make clean

    上层 Makefile 会调用每个模块的 clean 目标,并清理上层生成的文件。

  2. 查看帮助

    make help

方法 2:传递变量给下层 Makefile

上层 Makefile 可以通过环境变量或命令行参数将变量传递给下层 Makefile

上层 Makefile 示例
# 定义构建类型
BUILD_TYPE ?= Debug

# 定义下层模块的路径
MODULE1 = module1
MODULE2 = module2

# 定义所有模块
MODULES = $(MODULE1) $(MODULE2)

# 默认目标
all: $(MODULES)

# 构建模块
$(MODULES):
    $(MAKE) -C $@ BUILD_TYPE=$(BUILD_TYPE)

# 清理所有模块
clean:
    $(MAKE) -C $(MODULE1) clean
    $(MAKE) -C $(MODULE2) clean
    rm -f main

# 帮助信息
help:
    @echo "可用命令:"
    @echo "  make          编译所有模块"
    @echo "  make clean    清理所有模块"
    @echo "  make help     查看帮助信息"
下层 Makefile 示例(module1/Makefile
# 定义编译器
CC = gcc

# 定义目标文件
TARGET = module1.o

# 定义源文件
SRC = module1.c

# 从环境变量中获取构建类型
ifeq ($(BUILD_TYPE), Debug)
    CFLAGS = -g -Wall
else
    CFLAGS = -O2
endif

# 默认目标
all: $(TARGET)

# 生成目标文件
$(TARGET):
    $(CC) $(CFLAGS) -c $(SRC) -o $(TARGET)

# 清理
clean:
    rm -f $(TARGET)
使用说明
  1. 编译所有模块(Debug 模式)

make
  1. 编译所有模块(Release 模式)

make BUILD_TYPE=Release
  1. 清理所有模块

make clean

方法 3:使用递归构建

上层 Makefile 可以通过递归调用 make 命令来构建所有下层模块。

上层 Makefile 示例
# 定义模块路径
MODULES = module1 module2

# 默认目标
all: $(MODULES)

# 构建模块
$(MODULES):
    @echo "构建模块: $@"
    $(MAKE) -C $@

# 清理
clean:
    @echo "清理模块..."
    $(MAKE) -C module1 clean
    $(MAKE) -C module2 clean
    rm -f main

# 帮助信息
help:
    @echo "可用命令:"
    @echo "  make          编译所有模块"
    @echo "  make clean    清理所有模块"
    @echo "  make help     查看帮助信息"
下层 Makefile 示例(module1/Makefile
# 定义编译器
CC = gcc

# 定义目标文件
TARGET = module1.o

# 定义源文件
SRC = module1.c

# 编译选项
CFLAGS = -g -Wall

# 默认目标
all: $(TARGET)

# 生成目标文件
$(TARGET):
    $(CC) $(CFLAGS) -c $(SRC) -o $(TARGET)

# 清理
clean:
    rm -f $(TARGET)
使用说明
  1. 编译所有模块

make
  1. 清理所有模块

make clean

方法 4:使用 include 导入下层 Makefile

上层 Makefile 可以通过 include 指令导入下层 Makefile 的规则和变量。

上层 Makefile 示例
# 定义模块路径
MODULES = module1 module2

# 导入下层 Makefile 的变量和规则
include $(MODULES:%=%.mk)

# 默认目标
all: $(MODULES:%=build_%)

# 构建模块
build_%:
    $(MAKE) -C $* all

# 清理
clean:
    $(MAKE) -C module1 clean
    $(MAKE) -C module2 clean
    rm -f main

# 帮助信息
help:
    @echo "可用命令:"
    @echo "  make          编译所有模块"
    @echo "  make clean    清理所有模块"
    @echo "  make help     查看帮助信息"
下层 Makefile 示例(module1/Makefile
# 定义编译器
CC = gcc

# 定义目标文件
TARGET = module1.o

# 定义源文件
SRC = module1.c

# 编译选项
CFLAGS = -g -Wall

# 默认目标
all: $(TARGET)

# 生成目标文件
$(TARGET):
    $(CC) $(CFLAGS) -c $(SRC) -o $(TARGET)

# 清理
clean:
    rm -f $(TARGET)
使用说明
  1. 编译所有模块

make
  1. 清理所有模块

make clean

总结

通过上述方法,上层 Makefile 可以灵活地控制下层 Makefile 的构建过程。以下是关键点的总结:

  1. 直接调用:通过 $(MAKE) 或 make 命令直接调用下层 Makefile
  2. 传递变量:通过环境变量或命令行参数将变量传递给下层 Makefile
  3. 递归构建:通过递归调用 make 命令构建所有模块。
  4. 导入规则:通过 include 指令导入下层 Makefile 的规则和变量。

相关文章:

  • 解释型语言和编译型语言的区别
  • 安全岗の夺命连环问:(第壹篇)从XSS到0day的灵魂拷问
  • 舵机、震动传感器、超声波使用代码
  • Qt 5.14.2 入门(四)菜单栏和工具栏的创建
  • 六、继承(三)
  • 如何用finallshell连接虚拟机
  • 前端下载文件时浏览器右上角没有保存弹窗及显示进度,下载完之后才会显示保存弹窗的问题定位及解决方案
  • PHP 拆词搜索(常用于搜索内容)
  • 从三次方程到复平面:复数概念的奇妙演进(一)
  • 多光谱相机:海洋管道漏油(溢油)监测
  • 2025蓝桥杯C++ A组省赛 题解
  • 用Python构建区块链身份认证:安全与信任的新篇章
  • ZYNQ笔记(七):程序固化(QSPI Flash)
  • OpenSSH版本的重大升级 :OpenSSH 10
  • 推流265视频,网页如何支持显示265的webrtc
  • [特殊字符] Hyperlane:为现代Web服务打造的高性能Rust文件上传解决方案
  • 天梯赛L2题目算法汇总(记录高频考点)
  • 智能指针之设计模式2
  • 笔试专题(八)
  • Python 的 collections 模块
  • 马云再次现身阿里打卡创业公寓“湖畔小屋”,鼓励员工坚持创业精神
  • 东方红资管官宣:41岁原国信资管董事长成飞出任新总经理
  • 时隔14个月北京怀柔区重启供地,北京建工以3.59亿元摘得
  • 王受文已任全国工商联党组成员
  • 印巴战火LIVE丨印巴互相发动无人机袭击,巴官员称两国已在国安层面接触
  • 美众议院通过法案将“墨西哥湾”更名为“美国湾”