您的位置:首页 > 运维架构 > Linux

快速编写“专家级”makefile(4.打造更专业的编译环境——增进复用性)

2016-07-22 13:22 447 查看
    可以将共用部分放入一个独立的文件中——这就是 build 目录下的 make.rule 文件的作用

    那么,在 foo 模块的 Makefile 中,哪些是不能共用的呢?

变量 EXE 和 LIB 的定义对于每一个软件模块是不同的
DIR_EXES 变量和 DIR_LIBS 变量由于运用了相对路径,所以也是每个模块特有的。但是可以采用绝对路径的方式解决这个问题。比如,可以定义一个 ROOT 环境变量,其值设置为 huge 项目的根目录,这样的话,DIR_EXES 和 DIR_LIBS 就可以以 ROOT 为相对路径,而使对于所有的模块的相同
    在考虑复用的情形下,foo 模块的 Makefile 有两部分组成,分别是 build 的 make.rule 和 code / foo / src 的 Makefile:

    huge / build / make.rule

.PHONY : all clean


NKDIR = mkdir

RM = rm

RMFLAG = -rf

CC = gcc

AR = ar

ARFLAG = crs


DIR_OBJS = objs

DIR_EXES = $(ROOT)/build/exes

DIR_DEPS = deps

DIR_LIBS = $(ROOT)/build/libs

DIRS = $(DIR_OBJS) $(DIR_EXES) $(DIR_DEPS) $(DIR_LIBS)

RMS = $(DIR_OBJS) $(DIR_DEPS)


ifneq("$(EXE)", "")

EXE := $(addprefix $(DIR_EXES)/, $(EXE))

RMS += $(EXE)

endif


ifneq("$(LIB)", "")

LIB := $(addprefix $(DIR_LIBS)/, $(LIB))

RMS += $(LIB)

endif


SRCS = $(wildcard *.c)

OBJS = $(SRCS :.c = .o)

OBJS := $(addprefix $(DIR_OBJS)/, $(OBJS))

DEPS = $(SRCS :.c = .dep)

DEPS := $(addprefix $(DIR_DEPS)/, $(DEPS))


ifeq("$(wildcard $(DIR_OBJS))", "")

DEP_DIR_OBJS := $(DIR_OBJS)

endif

ifeq("$(wildcard $(DIR_EXES))", "")

DEP_DIR_EXES := $(DIR_EXES)

endif

ifeq("$(wildcard $(DIR_DEPS))", "")

DEP_DIR_DEPS := $(DIR_DEPS)

endif

ifeq("$(wildcard $(DIR_LIBS))", "")

DEP_DIR_LIBS := $(DIR_LIBS)

endif


all : $(EXE) $(LIB)


ifneq($MAKECMDGOALS, clean)

include $(DEPS)

endif


$(DIRS) :

$(MKDIR) $@


$(EXE) : $(DEP_DIR_EXE) $(OBJS)

$(CC) -o $@ $(filter %.o, $^)


$(LIB) : $(DEP_DIR_LIB) $(OBJS)

$(AR) $(ARFLAG) $@ $(filter %.o, $^)


$(DIR_OBJS) / %.o : $(DEP_DIR_OBJS) %.c

$(CC) -o $@ -c $(filter %.c, $^)


$(DIR_DEPS) / %.dep : $(DEP_DIR_DEPS) %.c

@echo "Creating $@ ..."

@set -e;\

$(RM) $(RMFLAG) $@.tmp;\

$(CC) -E -MM $(filter %.c, $^) > $@.tmp;\

sed 's,\(.*\)\.o[ :]*,objs/\1.o $@: ,g' < $@.tmp > $@;\

$(RM) $(RMFLAG) $@.tmp


clean :

$(RM) $(RMFLAG) $(RMS)


    huge / code / foo / src / Makefile

EXE =


LIB =libfoo.a


include $(ROOT)/build/make.rule


    这样 foo 模块的 Makefile 变得非常简单,因为大部分内容都被移到 make.rule 中。如果要运行 make ,必须先在 Shell 中导出所需的 ROOT 环境变量

/Makefile/huge

$ export ROOT = `pwd`

$ echo $ROOT

/Makefile/huge

$ cd code/foo/src

$ make

mkdir deps

Creating deps / foo.dep ...

mkdir objs

gcc -o objs / foo.o -c foo.c

ar crs /Makefile/huge/build/libs/libfoo.a  objs/foo.o

$ make clean

rm -rf objs deps  /Makefile/huge/build/libs/libfoo.a

    接下来需要考虑 code / huge / src 目录中的 Makefile 了,我们需要在此目录下放置一个 main.c 文件,生成一个可执行程序:

    huge / code / huge / src / main.c

#innclude <stdio.h>


int main()

{

return 0;

}


    huge / code / huge / src / Makefile

EXE =huge.exe


LIB =


include $(ROOT)/build/make.rule


    运行结果:

$ make

mkdir deps

Creating deps / main.dep ...

mkdir objs

gcc -o objs / main.o -c main.c

gcc -o /Makefile/huge/build/exes/huge.exe  objs/main.o

$ ls $ROOT/build/exes

huge.exe

$ make clean

rm -rf objs deps / Makefile / huge / build / exes / huge.exe

    参考文献:《专业嵌入式软件开发》李云·著                 
                           
  2016年7月5日,星期二

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息