Makefileの浅い分析(3)

6179 ワード

今日、複雑なプロジェクトを行いました.まず、プロジェクトの構造を見てみましょう.
├── 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:これはmakeの主なルールです.つまり、各makefileの共通点を合併し、その時に直接includeすればいいです.
  • Makefile:プロジェクト全体をコンパイルするMakefileは、小さなプロジェクトごとに便利であるだけで、そのプロジェクト自体のmakefileを実行する.
  • #  : 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を制御する