Makefile实现子目录编译

代码目录结构

top

         Makefile

       subdir1

                   Makefile

                   inc/src/obj

        subdir2

                   Makefile

                   obj

                   bottom1

                              inc/src

                   bottom2

                              inc/src

        subdirx

           ......

顶级Makefile

exclude_dirs:=include bin

#commom must be compiled before any other modules
dirs:=common

subdir=$(shell find . -maxdepth 1 -type d)
dirs+=$(filter-out ./common,$(subdir))
dirs:=$(basename $(patsubst ./%,%,$(dirs)))
dirs:=$(filter-out $(exclude_dirs),$(dirs))

.PHONY: $(dirs) clean

$(dirs):
        @for dir in $(dirs); do \
                $(MAKE) -C $$dir; \
        done

clean:
        @for dir in $(dirs); do \
                $(MAKE) -C $$dir clean; \
        done

子目录结构I    

子目录包含inc/src/obj,将子目录下的源文件的.o文件编译到obj目录

CC=g++

ROOT=.
PROJDIR=$(ROOT)/..
OBJDIR=$(ROOT)/obj
SRCDIR=$(ROOT)/src

TARGET=MFClient
SRCS=$(wildcard $(SRCDIR)/*.cpp)
srcs=$(notdir $(SRCS))
OBJS=$(patsubst %.cpp,$(OBJDIR)/%.o,$(srcs))

ifeq ($(DEBUG),1)
        CFLAGS=-Wall -DDBUG
else
        CFLAGS=-Wall -DRELEASE
endif

ifeq ($(FAKE_SOCKET),1)
CFLAGS+=-D_FAKE_SOCKET
endif

ifeq ($(TEST),1)
CFLAGS+=-D_TEST
endif

INCS=-I$(PROJDIR)/common/inc
INCS+=-I$(PROJDIR)/drivers

LIBS=-lCommon -lDrivers -lTest
LDFLAGS=-L$(PROJDIR)/common/obj
LDFLAGS+=-L$(PROJDIR)/test/obj
LDFLAGS+=-L$(PROJDIR)/drivers/obj

CFLAGS+=$(INCS)

.PHONY: all clean

all:$(TARGET) $(PROJDIR)/common/obj/libCommon.a $(PROJDIR)/drivers/obj/libDrivers.a $(PROJDIR)/test/obj/libTest.a

$(TARGET):$(OBJS)
        $(CC) -o $@ $(OBJS) $(LDFLAGS) $(LIBS)

$(OBJS):$(SRCS)
        
        $(CC) $(CFLAGS) -c $(patsubst %.o,$(SRCDIR)/%.cpp,$(notdir $@)) -o $@

clean:
        @echo "make" $(TARGET) "clean"
        rm -f $(ROOT)/$(TARGET) $(OBJDIR)/*.o

子目录结构II

子目录下包含一个obj和多个二级子目录,二级子目录下包含inc/src,所有源文件编译到统一的obj目录

CC=g++

ROOT=.
PROJDIR=$(ROOT)/..
OBJDIR=$(ROOT)/obj
TARGET=$(OBJDIR)/libDrivers.a

exclude_dirs:=obj
SUBDIR:=$(filter-out $(exclude_dirs),$(basename $(patsubst ./%,%,$(shell find . -maxdepth 1 -type d))))
incs:=$(foreach dir,$(SUBDIR),$(shell ls $(dir)/inc/*.h))
SRCS:=$(foreach dir,$(SUBDIR),$(shell ls $(dir)/src/*.cpp))
file:=$(notdir $(SRCS))
OBJS:=$(patsubst %.cpp,$(OBJDIR)/%.o,$(file))
temp:=$(filter %BusUart.cpp,$(SRCS))

ifeq ($(DEBUG),1)
        CFLAGS=-Wall -DDBUG
else
        CFLAGS=-Wall -DRELEASE
endif

INCS=-I$(PROJDIR)/common/inc
LDFLAGS=
LIBS=

ifeq ($(FAKE_SOCKET),1)
CFLAGS+=-D_FAKE_SOCKET
endif

ifeq ($(FAKE_BUS),1)
CFLAGS+=-D_FAKE_BUS
endif

ifeq ($(TEST),1)
CFLAGS+=-D_TEST
endif

CFLAGS+=$(INCS)

.PHONY: all clean

all:$(TARGET) $(SRCS) $(PROJDIR)/common/obj/libCommon.a

$(TARGET):$(OBJS)
        $(AR) crv $@ $(OBJS) $(LDFLAGS) $(LIBS)

$(OBJS):$(SRCS)
        $(CC) $(CFLAGS) -c $(filter %$(patsubst %o,%cpp,$(notdir $@)),$(SRCS)) -o $@
        
clean:
        @echo "make" $(TARGET) "clean"
        rm -f $(OBJDIR)/*.a $(OBJDIR)/*.o



### 回答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、付费专栏及课程。

余额充值