makefile将中间文件生成到临时目录

本文介绍了一个具体的Makefile配置案例,展示了如何设置编译环境、管理源文件及依赖,并生成目标文件。通过递归遍历目录、自动化创建所需目录等方式提高编译效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

TARGET := test

CC := g++ 

#注意每行后面不要有空格,否则会算到目录名里面,导致问题
SRC_DIR = src
BUILD_DIR = tmp
OBJ_DIR = $(BUILD_DIR)/obj
DEPS_DIR  = $(BUILD_DIR)/deps

#这里添加其他头文件路径
INC_DIR = \
	-I./include \
	-I./src \
	
#这里添加编译参数
CC_FLAGS := $(INC_DIR) -g -std=c++11
LNK_FLAGS := \
	-L/usr/local/lib 

#这里递归遍历3级子目录
DIRS := $(shell find $(SRC_DIR) -maxdepth 3 -type d)

#将每个子目录添加到搜索路径
VPATH = $(DIRS)

#查找src_dir下面包含子目录的所有cpp文件
SOURCES   = $(foreach dir, $(DIRS), $(wildcard $(dir)/*.cpp))  
OBJS   = $(addprefix $(OBJ_DIR)/,$(patsubst %.cpp,%.o,$(notdir $(SOURCES))))  
DEPS  = $(addprefix $(DEPS_DIR)/, $(patsubst %.cpp,%.d,$(notdir $(SOURCES))))  

$(TARGET):$(OBJS)
	$(CC) $^ $(LNK_FLAGS) -o $@

#编译之前要创建OBJ目录,确保目录存在
$(OBJ_DIR)/%.o:%.cpp
	if [ ! -d $(OBJ_DIR) ]; then mkdir -p $(OBJ_DIR); fi;\
	$(CC) -c $(CC_FLAGS) -o $@ $<

#编译之前要创建DEPS目录,确保目录存在
#前面加@表示隐藏命令的执行打印
$(DEPS_DIR)/%.d:%.cpp
	@if [ ! -d $(DEPS_DIR) ]; then mkdir -p $(DEPS_DIR); fi;\
	set -e; rm -f $@;\
	$(CC) -MM $(CC_FLAGS) $< > $@.$$$$;\
	sed 's,\($*\)\.o[ :]*,$(OBJ_DIR)/\1.o $@ : ,g' < $@.$$$$ > $@;\
	rm -f $@.$$$$

#前面加-表示忽略错误
-include $(DEPS)

.PHONY : clean
clean:
	rm -rf $(BUILD_DIR) $(TARGET)

 

最终目录结构是这个样子,tmp存放了所有中间文件, 源码在src目录。

直接在根目录执行make就可以了。

root@ubuntu:~/projects/MakeFileProject1# tree .
.
├── makefile
├── src
│   └── main.cpp
├── test
└── tmp
    ├── deps
    │   └── main.d
    └── obj
        └── main.o

<think>我们正在讨论Makefile编译C/C++项目时是否可以跳过生成.o文件(目标文件)而直接生成可执行文件。 实际上,在Makefile中,通常的步骤是将源文件(.c/.cpp)编译成目标文件(.o),然后将这些目标文件链接成可执行文件。 但是,我们也可以跳过显式生成.o文件这一步,直接编译链接成可执行文件。不过,这样做有一些优缺点。 回答重点: 1. 可以跳过生成.o文件,直接生成可执行文件。 2. 如何实现(在Makefile中直接编译链接)。 3. 这样做的优缺点。 步骤: 在Makefile中,我们可以为可执行文件写一个规则,直接将源文件编译链接成可执行文件,而不必先产生.o文件。 例如: target: source1.c source2.c gcc -o target source1.c source2.c 但是,这种方法在项目较大时效率低下,因为每次修改一个文件都需要重新编译所有源文件。 而传统的分步编译(先编译成.o再链接)则只重新编译修改过的文件,然后再链接,这样更高效。 因此,虽然技术上可以跳过.o文件,但在实际项目中,尤其是大型项目中,不推荐这样做。 另外,我们也可以使用模式规则来避免每个.o文件都写一条规则,但这里的问题是不生成.o文件,所以我们可以讨论直接编译链接的方式。 注意:在Makefile中,我们也可以使用“空”的规则来避免生成.o文件,但实际上还是需要编译步骤,只不过我们将其合并到可执行文件的规则中。 结论:可以,但不推荐(除非项目很小)。 同时,我们还需要注意,即使我们不显式生成.o文件,编译过程中也会在临时目录生成临时文件(类似于.o文件),只是不会保留在项目目录中。 因此,回答如下:</think>### Makefile生成可执行文件时能否跳过.o文件? **可以,但需权衡效率与实用性**。以下是具体分析和实现方法: --- ### ✅ 直接生成执行文件(不产生.o) 1. **单命令编译链接** 在Makefile规则中合并编译与链接步骤,跳过显式.o生成: ```makefile # 直接生成可执行文件(无.o) myapp: main.c utils.c gcc -o myapp main.c utils.c ``` 2. **使用通配符简化** 自动捕获所有.c文件直接编译: ```makefile SRCS = $(wildcard *.c) myapp: $(SRCS) gcc -o $@ $^ ``` --- ### ⚠️ 跳过.o的**缺点**(不推荐长期使用) 1. **编译效率低下** 每次修改任意文件都会触发**全量重新编译**,大型项目耗时剧增(传统分步编译仅重编改动文件)。 2. **无法利用中间产物** 调试时无法单独检查.o文件内容,也不能复用已编译的稳定模块。 3. **依赖管理失效** Makefile的自动依赖检测(如`gcc -MM`)需要基于.o规则实现,跳过后将失去增量编译能力。 --- ### 💡 实用建议 | 场景 | 方案 | |------|------| | 微型项目/快速测试 | 直接编译链接(跳过.o) | | 正式项目开发 | **保留.o生成**,通过模式规则优化:<br>```makefile<br>OBJ = $(patsubst %.c,%.o,$(wildcard *.c))<br>myapp: $(OBJ)<br> gcc -o $@ $^<br><br>%.o: %.c<br> gcc -c $< -o $@<br>``` | --- ### 🔧 特殊需求解决方案 若需**物理上不生成.o文件**(如磁盘空间紧张): 1. 使用内存文件系统(如`tmpfs`)存放中间文件 2. 添加清理规则自动删除.o: ```makefile .PHONY: clean clean: rm -f *.o myapp ``` ---
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值