多文件目录下makefile文件递归执行编译所有c文件

首先说说本次嵌套执行makefile文件的目的:只需make根目录下的makefile文件,即可编译所有c文件,包括子目录下的。

意义:自动化编译行为,以后编译自己的c文件时可把这些makefile文件直接复制到相应目录即可方便编译出所有文件。这些makefile文件是通用的,只需根据自己的工程情况改动少许内容即可。下面会说。

总体思路是:把目标文件放在debug文件夹下的obj目录下,把最终的二进制文件放在debug文件夹下的bin目录下;如何递归编译所有除了debug目录下的makefile文件呢:获得当前目录下的所有子目录,执行子目录下的makefile文件;获取当前目录下的所有c文件,编译c文件并放到指定的目标文件夹下。最后再执行debug目录下的makefile文件生成bin文件。

注意:除了debug文件夹比较特殊外,其他的子目录下都需要有Makefile文件,而且这些Makefile是相同的,除了根目录下的makefile文件有些不同外。即除了bin和obj目录以外的其他目录都需要Makefile文件,即使目录下没有c文件或者其他目录。

过程:首先在根目录下新建一个debug文件夹,debug文件夹下有bin目录和obj目录和一个Makefile文件,结构如下图。(这个debug文件里的makefile文件需要最后执行)(tree工具需要自己安装的,ubuntu下直接输入sudo apt-get install tree即可,但有时可能需要先sudo apt-get update才行)

整个目录结果如下图:

然后在根目录下新建Makefile文件,根目录下也可能会有c文件,故也需处理根目录下的c文件,内容如下:

复制代码
#设置编译器
CC=gcc
#debug文件夹里的makefile文件需要最后执行,所以这里需要执行的子目录要排除debug文件夹,这里使用awk排除了debug文件夹,读取剩下的文件夹
SUBDIRS=$(shell ls -l | grep ^d | awk '{if($$9 != "debug") print $$9}')
#无需下一行的注释代码,因为我们已经知道debug里的makefile是最后执行的,所以最后直接去debug目录下执行指定的makefile文件就行,具体下面有注释
#DEBUG=$(shell ls -l | grep ^d | awk '{if($$9 == "debug") print $$9}')
#记住当前工程的根目录路径
ROOT_DIR=$(shell pwd)
#最终bin文件的名字,可以更改为自己需要的
BIN=myapp
#目标文件所在的目录
OBJS_DIR=debug/obj
#bin文件所在的目录
BIN_DIR=debug/bin
#获取当前目录下的c文件集,放在变量CUR_SOURCE中
CUR_SOURCE=${wildcard *.c}
#将对应的c文件名转为o文件后放在下面的CUR_OBJS变量中
CUR_OBJS=${patsubst %.c, %.o, $(CUR_SOURCE)}
#将以下变量导出到子shell中,本次相当于导出到子目录下的makefile中
export CC BIN OBJS_DIR BIN_DIR ROOT_DIR
#注意这里的顺序,需要先执行SUBDIRS最后才能是DEBUG
all:$(SUBDIRS) $(CUR_OBJS) DEBUG
#递归执行子目录下的makefile文件,这是递归执行的关键
$(SUBDIRS):ECHO
    make -C $@
DEBUG:ECHO
    #直接去debug目录下执行makefile文件
    make -C debug
ECHO:
    @echo $(SUBDIRS)
#将c文件编译为o文件,并放在指定放置目标文件的目录中即OBJS_DIR
$(CUR_OBJS):%.o:%.c
    $(CC) -c $^ -o $(ROOT_DIR)/$(OBJS_DIR)/$@
CLEAN:
    @rm $(OBJS_DIR)/*.o
    @rm -rf $(BIN_DIR)/*
复制代码

上面的注释很详细了,具体的命令如果不清楚,自己可以google一下,譬如:wildcard patsubst awk等

读者可以根据自己的需要更改自己的debug目录和目标文件目录和bin文件目录

其他子目录下的Makefile文件的内容如下:

复制代码
 1 #子目录的Makefile直接读取其子目录就行
 2 SUBDIRS=$(shell ls -l | grep ^d | awk '{print $$9}')
 3 #以下同根目录下的makefile的相同代码的解释
 4 CUR_SOURCE=${wildcard *.c}
 5 CUR_OBJS=${patsubst %.c, %.o, $(CUR_SOURCE)}
 6 all:$(SUBDIRS) $(CUR_OBJS)
 7 $(SUBDIRS):ECHO
 8     make -C $@
 9 $(CUR_OBJS):%.o:%.c
10     $(CC) -c $^ -o $(ROOT_DIR)/$(OBJS_DIR)/$@
11 ECHO:
12     @echo $(SUBDIRS)
复制代码

debug目录下的Makefile文件如下:

1 OBJS=*.o
2 ODIR=obj
3 $(ROOT_DIR)/$(BIN_DIR)/$(BIN):$(ODIR)/$(OBJS)
4     $(CC) -o $@ $^

最后只需在根目录下,我的是我的根目录makefile目录下,执行make命令即可:

结果目录结果为:

然后执行". debug/bin/myapp"即可;最后可以执行make CLEAN清楚掉所有的目标文件和bin文件。

参考资料为:http://blog.csdn.net/zplove003/article/details/7066595

关于makefile文件的编写,见一下链接:跟我一起写makefile和http://wiki.ubuntu.org.cn/index.php?title=%E8%B7%9F%E6%88%91%E4%B8%80%E8%B5%B7%E5%86%99Makefile&variant=zh-cn

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Makefile多级目录编译是指在项目中存在多级目录的情况下,通过Makefile来进行编译管理。以下是一个简单的示例: 假设项目结构如下: ``` project/ ├── src/ │ ├── dir1/ │ │ ├── file1.c │ │ └── file2.c │ └── dir2/ │ ├── file3.c │ └── file4.c ├── include/ │ ├── dir1/ │ │ ├── file1.h │ │ └── file2.h │ └── dir2/ │ ├── file3.h │ └── file4.h └── Makefile ``` Makefile的书写如下: ``` # 定义变量 CC = gcc CFLAGS = -Iinclude # 获取项目中所有的.c文件和.o文件 SRCS = $(shell find src -name '*.c') OBJS = $(subst .c,.o,$(SRCS)) # 定义规则,规定如何将.c文件编译成.o文件 %.o: %.c $(CC) $(CFLAGS) -o $@ -c $< # 定义默认目标,需要编译的目标为所有.o文件 all: $(OBJS) # 清理临时文件 clean: rm -f $(OBJS) ``` 如果要编译整个项目,只需要在终端中执行`make`命令即可。Makefile会按照规则将所有.c文件编译成.o文件,并将生成的.o文件放在相应的目录下。 需要注意的是,这个示例是一个简单的Makefile,如果项目更复杂,则需要进一步扩展规则和变量的定义。 ### 回答2: Makefile是一个用于管理和自动化编译程序的工具,它可以帮助我们在多级目录结构中进行编译。 要在多级目录中使用Makefile进行编译,我们需要在每个子目录下创建一个Makefile文件。这个Makefile文件将指定子目录下的文件以及需要编译的规则和依赖关系。 为了在多级目录编译程序,我们可以使用Makefile中的变量和规则来指定多级目录结构。我们可以使用变量来指定源代码文件和目标文件的路径。例如,我们可以创建一个变量来指定源代码文件的路径,并使用这个变量在规则中编译源代码文件。 除此之外,我们还可以使用Makefile中的规则来指定依赖关系。这样,当我们修改了某个源文件时,只会编译与之相关的文件,而不是整个程序。这可以提高编译的效率。 为了在多级目录中正确地编译程序,我们还需要使用Makefile中的一些特殊规则,例如all,clean和install。这些规则可以帮助我们批量编译、清理和安装程序。 总的来说,要在多级目录中使用Makefile进行编译,我们需要在每个子目录下创建一个Makefile文件,并在文件中指定源代码文件的路径、目标文件的路径和编译规则。同时,我们还需要使用特殊规则来批量处理编译、清理和安装操作。这样,我们就可以通过Makefile来管理和自动化编译整个多级目录结构的程序。 ### 回答3: 在makefile中进行多级目录编译,可以采用递归的方式来处理。首先,需要定义一个变量来表示当前目录下的源文件和目标文件,例如在根目录下定义一个变量SRCS表示所有的源文件,然后将每个目录下的源文件添加到SRCS中。 接着,定义另一个变量来表示当前目录下的所有目标文件,例如在根目录下定义一个变量OBJS表示所有的目标文件,可以通过将SRCS中的源文件替换为相应的目标文件来实现,例如可以用OBJS := $(SRCS:.c=.o)将.c文件替换为.o文件。 然后,再定义一个变量来表示当前目录下的依赖关系,例如在根目录下定义一个变量DEPS表示所有的依赖关系,可以通过将SRCS中的源文件替换为相应的依赖文件来实现,例如可以用DEPS := $(SRCS:.c=.d)将.c文件替换为.d文件。 接下来,编写一个目标依赖规则,用来将源文件编译生成目标文件,例如在根目录下编写一个规则如下: $(OBJS) : %.o : %.c $(CC) $(CFLAGS) -c $< -o $@ 然后,编写一个目标依赖规则,用来生成依赖文件,例如在根目录下编写一个规则如下: $(DEPS) : %.d : %.c $(CC) -M $(CFLAGS) $< > $@ 最后,在最上层的makefile中调用子目录makefile,例如在根目录makefile中编写规则如下: .PHONY : subdirs $(SUBDIRS) subdirs: $(foreach subdir,$(SUBDIRS),make -C $(subdir);) 其中,SUBDIRS表示所有的子目录。 这样,当执行make命令时,会顺序执行每个子目录下的makefile,实现了多级目录编译

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值