Makefileの浅い分析(3)
6179 ワード
今日、複雑なプロジェクトを行いました.まず、プロジェクトの構造を見てみましょう.
make.rule:これはmakeの主なルールです.つまり、各makefileの共通点を合併し、その時に直接includeすればいいです. Makefile:プロジェクト全体をコンパイルするMakefileは、小さなプロジェクトごとに便利であるだけで、そのプロジェクト自体のmakefileを実行する.
この部分は簡単です.ただinclude makeです.ruleを使用して、独自の変数/異なる変数を構成します.
プロセスは次のようになります.
[1]ジェーン・リー雲まで.Makefile(準完全版)2009.08.25を制御する
├── build //
│ ├── exes
│ │ └── huge.exe
│ ├── libs
│ │ ├── libbar.a
│ │ └── libfoo.a
│ ├── Makefile
│ └── make.rule
└── source //
├── bar // 1
│ ├── inc
│ │ └── bar.h
│ └── src
│ ├── bar.c
│ ├── deps
│ │ └── bar.dep
│ ├── makefile
│ └── objs
│ └── bar.o
├── foo // 2
│ ├── inc
│ │ └── foo.h
│ └── src
│ ├── deps
│ │ └── foo.dep
│ ├── foo.c
│ ├── makefile
│ └── objs
│ └── foo.o
└── huge // 3
└── src
├── deps
│ └── main.dep
├── main.c
├── makefile
└── objs
└── main.o
1.まず、ディレクトリを直接作成できます
[root@ test]# mkdir -p build source/foo/src source/foo/inc source/huge/src
2.その後、リソースファイルを適切なフォルダに配置します。
├── build
│ ├── Makefile
│ └── make.rule
└── source
├── bar
│ ├── inc
│ │ └── bar.h
│ └── src
│ ├── bar.c
│ ├── makefile
├── foo
│ ├── inc
│ │ └── foo.h
│ └── src
│ ├── foo.c
│ ├── makefile
└── huge
└── src
├── main.c
└── makefile
3.ビルドディレクトリから見る
# : make.rule
.PHONY: all test clean
CC = gcc
AR = ar
ARFLAGS = crs
MKDIR = mkdir
RM = rm
RMFLAGS = -rf
ROOT_DIR ?= /home/XXX
DIR_OBJS = objs
DIR_EXES = $(ROOT)/build/exes
DIR_DEPS = deps
DIR_LIBS = $(ROOT)/build/libs
ifeq ("$(wildcard $(DIR_DEPS))", "")
DIR_DEPS_PRE := $(DIR_DEPS)
endif
ifeq ("$(wildcard $(DIR_OBJS))", "")
DIR_OBJS_PRE := $(DIR_OBJS)
endif
DIRS = $(DIR_OBJS) $(DIR_EXES) $(DIR_DEPS) $(DIR_LIBS)
RMS = $(DIR_OBJS) $(DIR_DEPS)
# EXE =
ifneq ($(EXE), "")
EXE := $(addprefix $(DIR_EXES)/, $(EXE))
RMS += $(EXE)
endif
# LIB = libfoo.a
ifneq ($(LIB), "")
LIB := $(addprefix $(DIR_LIBS)/, $(LIB))
RMS += $(LIB)
endif
SRCS = $(wildcard *.c)
OBJS = $(patsubst %.c, %.o, $(SRCS))
OBJS := $(addprefix $(DIR_OBJS)/, $(OBJS))
DEPS = $(SRCS:.c=.dep)
DEPS := $(addprefix $(DIR_DEPS)/, $(DEPS))
ifneq ($(EXE), "")
all: $(EXE)
endif
ifneq ($(LIB), "")
all: $(LIB)
endif
ifneq ($(MAKECMDGOALS), clean)
include $(DEPS)
endif
# include
ifneq ($(INC_DIRS), "")
INC_DIRS := $(strip $(INC_DIRS))
INC_DIRS := $(addprefix -I, $(INC_DIRS))
endif
ifneq ($(LINK_LIBS), "")
LINK_LIBS := $(strip $(LINK_LIBS))
LINK_LIBS := $(addprefix -l, $(LINK_LIBS))
endif
$(DIRS):
$(MKDIR) $@
$(EXE): $(DIR_EXES) $(OBJS)
$(CC) -L$(DIR_LIBS) -o $@ $(filter %.o, $^) $(LINK_LIBS)
$(LIB): $(DIR_LIBS) $(OBJS)
$(AR) $(ARFLAGS) $@ $(filter %.o, $^)
$(DIR_OBJS)/%.o: $(DIR_OBJS_PRE) %.c
$(CC) $(INC_DIRS) -o $@ -c $(filter %.c, $^)
$(DIR_DEPS)/%.dep: $(DIR_DEPS_PRE) %.c
@echo "Making $@ ..."
@set -e; \
$(CC) $(INC_DIRS) -E -MM $(filter %.c, $^) | sed 's,\(.*\)\.o[ :]* ,$(DIR_OBJS)/\1.o $@: ,g' > $@
clean:
$(RM) $(RMFLAGS) $(RMS)
# : Makefile
.PHONY: all clean
DIRS = $(ROOT_DIR)/source/foo/src \
$(ROOT_DIR)/source/bar/src \
$(ROOT_DIR)/source/huge/src
RM = rm
RMFLAGS = -rf
RMS = $(ROOT_DIR)/build/exes \
$(ROOT_DIR)/build/libs
all:
@set -e; \
for dir in $(DIRS); \
do \
cd $$dir && $(MAKE); \
done
@echo ""
@echo ":-) Completed !"
@echo ""
clean:
@set -e; \
for dir in $(DIRS); \
do \
cd $$dir && $(MAKE) clean; \
done
$(RM) $(RMFLAGS) $(RMS)
@echo ""
@echo ":-) Completed !"
@echo ""
4.そしてソースの中にあるディレクトリのMakefile
この部分は簡単です.ただinclude makeです.ruleを使用して、独自の変数/異なる変数を構成します.
# : bar/src/makefile
EXE =
LIB = libbar.a
INC_DIRS = $(ROOT_DIR)/source/bar/inc
LINK_LIBS =
include $(ROOT_DIR)/build/make.rule
# : foo/src/makefile
EXE =
LIB = libfoo.a
#
INC_DIRS = $(ROOT_DIR)/source/foo/inc
LINK_LIBS =
# ROOT buid .
include $(ROOT_DIR)/build/make.rule
# : huge/src/makefile
EXE = huge.exe
LIB =
INC_DIRS = $(ROOT_DIR)/source/foo/inc \
$(ROOT_DIR)/source/bar/inc
LINK_LIBS = foo bar
include $(ROOT_DIR)/build/make.rule
5.最後に、buildディレクトリmakeでは、build/Makefileのルールを実行し、sourceのすべてのソースファイルをコンパイルします。
プロセスは次のようになります.
make[1]: Entering directory '/home/XXX/source/foo/src'
mkdir deps
Making deps/foo.dep ...
mkdir /home/XXX/build/libs
mkdir objs
gcc -I/home/XXX/source/foo/inc -o objs/foo.o -c foo.c
ar crs /home/XXX/build/libs/libfoo.a objs/foo.o
make[1]: Leaving directory '/home/XXX/source/foo/src'
make[1]: Entering directory '/home/XXX/source/bar/src'
/home/XXX/build/make.rule:52: deps/bar.dep:
mkdir deps
Making deps/bar.dep ...
mkdir objs
gcc -I/home/XXX/source/bar/inc -o objs/bar.o -c bar.c
ar crs /home/XXX/build/libs/libbar.a objs/bar.o
make[1]: Leaving directory '/home/XXX/source/bar/src'
make[1]: Entering directory '/home/XXX/source/huge/src'
/home/XXX/build/make.rule:52: deps/main.dep:
mkdir deps
Making deps/main.dep ...
mkdir /home/XXX/build/exes
mkdir objs
gcc -I/home/XXX/source/foo/inc -I/home/XXX/source/bar/inc -o objs/main.o -c main.c
gcc -L/home/XXX/build/libs -o /home/XXX/build/exes/huge.exe objs/main.o -lfoo -lbar
make[1]: Leaving directory '/home/XXX/source/huge/src'
:-) Completed !
[1]ジェーン・リー雲まで.Makefile(準完全版)2009.08.25を制御する