簡體   English   中英

對子目錄使用GNU Make

[英]Using GNU Make with subdirectories

我想知道在帶有子目錄的項目中使用Make的不同方法是什么,它們的優點/缺點是什么,但是永遠看不到好的摘要或菜譜。

我在研究中主要看到“遞歸”和“單個makefile”方法,但是還有其他方法嗎?

我還假設不僅有一種“遞歸”或“單個makefile”方法,而且有幾種,那么有人可以總結一下嗎?

對於我的特殊情況,我想要一個目錄架構,如下所示:

.
├── build
│   ├── *.d
│   ├── *.o
|   ├── subdir1
|   │   ├── *.d
|   │   └── *.o
|   └── subdir2
|       ├── *.d
|       ├── *.o
|       └── subdir3
|           ├── *.d
|           └── *.o
├── include
│   ├── *.h
│   └── *.h
├── Makefile
└── src
    ├── *.c
    ├── *.h
    ├── subdir1
    │   ├── *.c
    │   └── *.h
    └── subdir2
        ├── *.c
        ├── *.h
        └── subdir3
            ├── *.c
            └── *.h

我應該選擇哪種解決方案? 可能允許源文件具有相同名稱的文件嗎?

您的項目設置實際上是基本的,因此應該是您的Makefile:

SRC_DIR := src
BLD_DIR := build

SRC := $(shell find $(SRC_DIR) -name "*.c")
OBJ := $(SRC:$(SRC_DIR)/%.c=$(BLD_DIR)/%.o)
DEP := $(OBJ:.o=.d)

CPPFLAGS := -MMD -MP # enable auto-dependency generation
CFLAGS   := -Wall -W -pedantic

.PHONY: all clean

all: $(OBJ)

clean:
    $(RM) -r $(BLD_DIR)

.SECONDEXPANSION:
$(BLD_DIR)/%.o: $(SRC_DIR)/%.c | $$(@D)/ # First check that the destination directory exists
    $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ -c $<

%/:
    mkdir -p $* # -p flag necessary for recursive directory creation

ifeq "$(MAKECMDGOALS)" ""
-include $(DEP)
endif

這里的想法是使用find命令遞歸列出源文件,為make提供適當的模式規則,以便在正確的位置進行編譯,並將正確的預處理程序文件傳遞給編譯器以啟用自動依賴項生成。


在Windows 8.1下使用GIT Bash shell和以下目錄結構在GNU Make 4.1上進行了測試:

.
├── Makefile
└── src
    ├── test.c
    ├── test1.c
    └── subdir1
        └── test.c

閱讀了“ 遞歸使被認為有害”之后 ,我想出了一種非常簡單且模塊化的方法,通過在所有子目錄中包含相互包含並包含在主makefile中的文件:

CXX         := gcc

SRCDIR          := src
OBJDIR          := build

# These lines are needed to set immediate evaluation for
# these variables, instead of deferred evaluation which is unsuitable.
SRCS            :=
SUBDIRS         :=
CFLAGS          :=
LDFLAGS         :=

include $(SRCDIR)/module.mk

OBJS            := $(addprefix $(OBJDIR)/, $(SRCS:.c=.o))

SRCS            := $(addprefix $(SRCDIR)/, $(SRCS))

DEPS            := $(OBJS:.o=.d)

TMPS            := $(OBJS) $(OBJS:.o=.d)

CFLAGS          += -MD
debug: CFLAGS   += -g -g3 -ggdb
CFLAGS          += $(addprefix -I./$(SRCDIR)/, $(SUBDIRS))

LDFLAGS         += -lsomelib
debug: LDFLAGS      += -g -g3 -ggdb

NAME            := yolo

all: $(NAME)

debug:  re

-include $(DEPS)

$(OBJDIR)/%.o: $(SRCDIR)/%.c
    $(COMPILE.c) $(OUTPUT_OPTION) $<

$(NAME): $(OBJS)
    @$(CXX) $(OBJS) -o $(NAME) $(LDFLAGS)

$(OBJS): | $(OBJDIR)

$(OBJDIR):
    @mkdir -p $(OBJDIR)
    @for dir in $(SUBDIRS);         \
    do                  \
        mkdir -p $(OBJDIR)/$$dir;   \
    done

clean:
    rm -rf $(TMPS)

fclean: clean
    rm -rf $(NAME)
    rm -rf $(OBJDIR)

re: fclean all

.PHONY: all clean fclean re

在每個子目錄中,都有一個module.mk文件(我可以給它起任何名字,但這看起來很酷)。

對於src:

SRCS        :=  main.c file1.c file2.c

SUBDIRS     +=  subdir1 subdir2

include $(SRCDIR)/subdir1/module.mk
include $(SRCDIR)/subdir2/module.mk

對於1級子目錄:

THIS_DIR_L0 := subdir1

MOD_SRC     :=  file3.c file4.c

SRCS        += $(addprefix $(THIS_DIR_L0)/, $(MOD_SRC))

SUBDIRS     += $(THIS_DIR_L0)/subdir3

include $(SRCDIR)/$(THIS_DIR_L0)/subdir3/module.mk

對於2級子目錄(更深一層):

THIS_DIR_L1 := subdir3

MOD_SRC     :=  file5.c file6.c

SRCS        += $(addprefix $(THIS_DIR_L0)/$(THIS_DIR_L1)/, $(MOD_SRC))

等等...

設置非常簡單,我發現它非常模塊化,並且不使用遞歸的makefile。 在目錄結構中進行庫和東西也不會很復雜。

有更好的主意的人請告訴我。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM