简体   繁体   English

如何编写良好而高效的makefile

[英]How to write a good and efficient makefile

I have following folder structure: 我有以下文件夹结构:

TOPDIR
|
├── a
│   ├── a.c
│   ├── a.h
│   └── a.mk
├── b
│   ├── b.c
│   ├── b.h
│   └── b.mk
├── c
│   ├── c.c
│   ├── c.h
│   └── c.mk
├── include
│   └── common.h
├── root
│    ├── main.c
│    └── root.mk
└── Makefile

per-condition 每个条件

My target is to write main Makefile under TOPDIR and sub-makefile, *.mk in sub folder, the include folder contain some common defines. 我的目标是在子文件夹中的TOPDIR和子Makefile, *.mk下写入主Makefileinclude文件夹包含一些通用定义。 root folder contain my main file( main function located here). root文件夹包含我的主文件( main功能位于此处)。 Meanwhile, in main.c , it will call function from ac and bc , cc is driver related, and will be called from ac and bc 同时,在main.c ,它将从acbc调用函数, cc与驱动程序相关,并且将从acbc调用

Problem 问题

I wrote sub-makefile like(I use one a.mk for example, others are same, ONLY root.mk has little different): 我写了一个子makefile文件(例如,我使用一个a.mk ,其他相同,只有root.mk几乎没有什么不同):

#MODULE will be modified for each sub folder
MODULE = a
LIB = $(MAKE_DIR)/libs/lib$(MODULE).a
SRCS = $(wildcard *.c)
OBJS = $(patsubst %.c, %.o, $(SRCS))

#generate lib file from obj file
$(LIB): $(OBJS)
    @mkdir -p ../libs
    @$(AR) cr $@ $^
    @echo "    Archive    $(notdir $@)"

#compile obj file from source file
$(OBJS): $(SRCS)
    @$(CC) $(CFLAGS) -c $^
    @echo "    CC        $(OBJS)"

.PHONY: clean
clean:
    @$(RM) -f $(LIB) $(OBJS)
    @$(RM) -f *.expand
    @echo "    Remove Objects:   $(OBJS)"
    @echo "    Remove Libraries:  $(notdir $(LIB))"

I wrote root.mk like: 我写的root.mk像这样:

PROG = ../prog/DEMO

SRCS = $(wildcard *.c)
OBJS = $(patsubst %.c, %.o, $(SRCS))

#generate finial target file for run
$(PROG): $(SRCS)
    @mkdir -p ../prog
    @$(CC) $^ $(CFLAGS) -Wl,-Map=$(PROG).map $(LIBS) -o $@
    @echo "    Generate Program $(notdir $(PROG)) from $^"

.PHONY: clean
clean:
    @$(RM) -f $(OBJS) $(PROG)
    @$(RM) -f *.expand
    @$(RM) -rf ../prog ../libs
    @echo "    Remove Objects:   $(OBJS)"
    @echo "    Remove Libraries:  $(notdir $(PROG))"

I wrote main Makefile like: 我写了主要的Makefile像:

MAKE_DIR = $(PWD)

ROOT_DIR    := $(MAKE_DIR)/root 
DRV_DIR     := $(MAKE_DIR)/driver
INCLUDE_DIR := $(MAKE_DIR)/include
DEBUG_DIR   := $(MAKE_DIR)/debug

INC_SRCH_PATH := 
INC_SRCH_PATH += -I$(ROOT_DIR)
INC_SRCH_PATH += -I$(DRV_DIR) 
INC_SRCH_PATH += -I$(INCLUDE_DIR)
INC_SRCH_PATH += -I$(DEBUG_DIR)

LIB_SRCH_PATH :=
LIB_SRCH_PATH += -L$(MAKE_DIR)/libs

CC = gcc
LD = ld

#problem happan here, if I change the sequence of LIB, 
#during the finial link, it will find some function un-referenced, 
#why can I put liba first?
LIBS := -lc -lb -la

CFLAGS :=
CFLAGS += $(INC_SRCH_PATH) $(LIB_SRCH_PATH) 
CFLAGS += -Wall -O -ggdb
CFLAGS += -DDEBUG -D_REENTRANT

LDFLAGS :=

export MAKE_DIR CC LD CFLAGS LDFLAGS LIBS LINT INC_SRCH_PATH

all:
    @$(MAKE) -C a -f a.mk
    @$(MAKE) -C b -f b.mk
    @$(MAKE) -C c -f c.mk
    @$(MAKE) -C root -f root.mk

.PHONY: clean
clean:
    @$(MAKE) -C debug -f debug.mk clean
    @$(MAKE) -C driver -f driver.mk clean
    @$(MAKE) -C mw -f mw.mk clean
    @$(MAKE) -C root -f root.mk clean

Question

  1. In main Makefile , I define which LIB file I will use, if need move it to root.mk for better? 在主Makefile ,我定义了将使用的LIB文件,是否需要将其移至root.mk更好?

  2. In sub-makefile, I did NOT use -MM to generate depend file, if this cause the problem I can NOT change the sequence of my lib* , which I also described in Makefile comments. 在子makefile中,我没有使用-MM来生成依赖文件,如果这引起了问题,那么我将无法更改lib*的序列,我在Makefile注释中也对此进行了描述。

  3. Seems my makefile system can NOT detect I update some head file, for example, I first compiled whole code, and then, I modified one head file, when I try to re-compile, none of source is compiled 似乎我的makefile系统无法检测到我更新了一些头文件,例如,我先编译了整个代码,然后修改了一个头文件,当我尝试重新编译时,没有源代码被编译

if: 如果:

#Automatic dependency magic:
%.d: src/%.c
   $(CC) -MM -o$@ $<

-include (MYPROG_OBJECTS:%.o=%.d)

need add into each sub-makefile? 需要添加到每个子makefile中?

This rule is definitely wrong: 这条规则绝对是错误的:

$(OBJS): $(SRCS)
        @$(CC) $(CFLAGS) -c $^
        @echo "    CC        $(OBJS)"

The target line will expand to something like: 目标行将扩展为:

a.o b.o c.o d.o : a.c b.c c.c d.c

That's not right. 那是不对的。 It is identical to writing this: 等同于编写此代码:

a.o : a.c b.c c.c d.c
        ...
b.o : a.c b.c c.c d.c
        ...
c.o : a.c b.c c.c d.c
        ...
d.o : a.c b.c c.c d.c
        ...

This means that whenever you change any source file, ALL the object files will be rebuilt. 这意味着无论何时更改任何源文件,都将重建所有目标文件。 You should use a pattern rule here: 您应该在此处使用模式规则:

%.o : %.c
        @$(CC) $(CFLAGS) -o $@ -c $<
        @echo "    CC        $@"

to compile the object files one at a time. 一次编译一个目标文件。

As far as your questions go, I don't understand question #1. 就您的问题而言,我不理解第一个问题。

Questions #2 and #3 (if I understand correctly) are the same thing: the reason for #3 (no files are recompiled when you change a header file) is that you're not declaring any prerequisites on header files. 问题2和问题3(如果我理解正确)是同一回事:问题3(更改头文件时没有重新编译文件)的原因是,您没有在头文件上声明任何先决条件。 Make doesn't have any built-in support for this, so you either have to do it by hand (add ao : ac bh ch gh to your makefiles) or else automatically generate the dependencies. Make对此没有任何内置支持,因此您必须手工完成(将ao : ac bh ch gh到您的makefile中)或自动生成依赖项。

The dependency generation will typically use the -MM or similar flags, assuming your compiler supports these flags. 假设您的编译器支持这些标志,则依赖项生成通常将使用-MM或类似的标志。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM