Makefile 实践

Table of Contents

1 递归编译子文件夹

1.1 使用搜索路径1

该方法使用了 VPATH 变量,路径以英文冒号分割:

    VPATH=path1:path2:...
    CFLAGS = -Iadd -Isub
    OBJSDIR = .objs
    VPATH = subdir1:subdir2:.
    OBJS = add_int.o add_float.o sub_int.o sub_float.o main.o

    $(OBJSDIR):
        mkdir -p ./$@
    $(TARGET):$(OBJSDIR) $(OBJS)
        $(CC) -o $(TARGET) $(OBJSDIR)/*.o $(CFLAGS)
    $(OBJS):%.o:%.c
        $(CC) -c $(CFLAGS) $< -o $(OBJSDIR)/$@
    clean:
        -$(RM) $(TARGET)
        -$(RM) $(OBJSDIR)/*.o

1.2 递归式

为了实现每个目录下的代码具有独立的 makefile,且根目录下的 makefile 可以一次执行子目录下的 makefile,就有了递归式的方法来写父目录下的 makefile 了,该方法的实现是使用的 $(MAKE) 变量,使用格式如下:

    subdir:
        $(MAKE)  -C subdir

subdir1 makefile

    OBJS = app1
    CFLAGS = -O2
    all:$(OBJS)
    $(OBJS):%:%.c
        $(CC) $(CFLAGS) $< -o $(OBJSDIR)/$@
    clean:
        $(RM) $(OBJS)

subdir2 makefile

    OBJS = app2
    CFLAGS = -O2
    all: $(OBJS)
    $(OBJS):%:%.c
        $(CC) $(CFLAGS) $< -o $(OBJSDIR)/$@
    clean:
        $(RM) $(OBJS)

接下来就是写主目录下面的 makefile 文件了,使用前面递归调用格式,makefile 文件如下:

    CC = gcc
    CFLAGS = -O2
    TARGET = main
    export OBJSDIR = ${shell pwd}/.objs
    $(TARGET):$(OBJSDIR) main.o
        $(MAKE) -C add
        $(MAKE) -C sub
        $(CC) -o $(TARGET) $(OBJSDIR)/*.o
    main.o:%.o:%.c
        $(CC) -c $< -o $(OBJSDIR)/$@ $(CFLAGS) -Iadd -Isub
    $(OBJSDIR):
        mkdir -p $(OBJSDIR)
    clean:
        -$(RM) $(TARGET)
        -$(RM) $(OBJSDIR)/*.o

  “\((MAKE) -C add” “\)(MAKE) -C sub”这两句实现的就是在执行下面的命令前先执行子目录下的 makefile 文件

1.3 使用纯粹的 makefile 语法2

此种方法子目录层数多时遍历很慢。

    .PHONY : all

    # arg1 dir
    define EXPAND_temp
    FILES := $(wildcard $(1)*)
    DIRS :=
    $$(foreach e, $$(FILES), $$(if $$(wildcard $$(e)/*), $$(eval DIRS := $$(DIRS) $$(e))))
    FILES := $$(filter-out $$(DIRS),$$(FILES))

    ALLDIRS := $$(ALLDIRS) $$(DIRS)
    ALLFILES := $$(ALLFILES) $$(FILES)
    $$(foreach e,$$(DIRS),$$(eval $$(call EXPAND_temp,$$(e)/)))
    endef

    $(eval $(call EXPAND_temp))

    all :
        @for subdir in $(ALLDIRS); do \
            echo $$subdir; \
        done

Footnotes:

Author: lsl

Created: 2016-08-07 Sun 19:10

Validate