如何写一个良好的,高效的makefile [英] How to write a good and efficient makefile

查看:209
本文介绍了如何写一个良好的,高效的makefile的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下文件夹结构:

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

每个条件

我的目标是写主的Makefile TOPDIR 和子生成文件, * .mk 在子文件夹,将包含文件夹中包含一些常见的定义。 文件夹中包含我的主文件(功能设在这里)。同时,在的main.c ,它会调用函数从 AC BC CC 是驱动程序有关,并将从 AC名为 BC

My target is to write main Makefile under TOPDIR and sub-makefile, *.mk in sub folder, the include folder contain some common defines. root folder contain my main file(main function located here). Meanwhile, in main.c, it will call function from a.c and b.c, c.c is driver related, and will be called from a.c and b.c

问题

我写的子样的makefile(我使用一个 a.mk 例如,其他都是一样的,只是 root.mk 有一点不同):

I wrote sub-makefile like(I use one a.mk for example, others are same, ONLY root.mk has little different):

#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))"

我写了 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))"

我写的主的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


  1. 在主的Makefile ,我定义它 LIB 文件我会用,如果需要将它移到 root.mk 更好?

  1. In main Makefile, I define which LIB file I will use, if need move it to root.mk for better?

在子Makefile中,我没有使用 -MM 来生成依赖文件,如果这导致问题我不能改变我的<$序列C $ C> LIB * ,这也是我在的Makefile 的意见。

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文件系统不能检测我更新了一些头文件,例如,我先编译整个code,然后,我修改一个脑袋的文件,当我试图重新编译,没有源编译

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

如果

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

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

需要加入到每个子makefile文件?

need add into each sub-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.

至于你的问题去,我不明白的问题#1。

As far as your questions go, I don't understand question #1.

问题#2,#3(如果我理解正确)是同一件事:为#3的原因(当你改变一个头文件没有文件被重新编译)是你不上宣布任何prerequisites头文件。让没有任何内置的这种支持,所以你要么必须手工做(添加 AO:AC BH CH GH 你的makefile文件),否则自动生成的依赖关系。

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. Make doesn't have any built-in support for this, so you either have to do it by hand (add a.o : a.c b.h c.h g.h to your makefiles) or else automatically generate the dependencies.

的依赖代通常会使用 -MM 或类似的标志,假设你的编译器支持这些标志。

The dependency generation will typically use the -MM or similar flags, assuming your compiler supports these flags.

这篇关于如何写一个良好的,高效的makefile的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆