Makefile用于多个源目录和一个目标目录

时间:2013-12-06 22:10:24

标签: c makefile

我尝试编写一个makefile,它在当前目录中搜索lib-directories,编译每个目录的源代码并将object-file放入一个单独的object-directory中。我不想拥有多个makefile。

这个makefile将执行此操作:

SRCDIR  := $(shell ls -d lib_*/)

CC      := gcc
DB      := gdb
OBJDIR  := obj
CFLAGS  := -Wall -Werror -Wextra -pedantic -O3
LDFLAGS := #

# Rules
all:
    @ # create object directory
    @mkdir -p  $(OBJDIR)/ ;
    @ # go through all source dirs
    @for dir in $(SRCDIR); do \
        echo $$dir && \
        cd $$dir && \
        for n in $$(ls *.c); do \
            m=$${n%%.c}; \
            $(CC) -c \
               $(CFLAGS) \
               $(LDFLAGS) \
               -o ../$(OBJDIR)/$$m.o $$n;\
        done; \
        cd ..; \
    done

但是:makefile编译每个运行所有源。这些来源也没有任何变化。如果makefile可能识别是否有更改,并且只编译更改的源?


这里是dirs的结构:

lib
 |-lib_one
 |  |-lib_one.c
 |  |-lib_one.h
 |
 |-lib_two
 |  |-lib_two.c
 |  |-lib_two.h
 |
 |-lib_n
 |  |-lib_n.c
 |  |-lib_n.h
 |
 |-obj
 |  |-lib_one.o
 |  |-lib_two.o
 |  |-
 |  |-lib_n.o
 |
 |-makefile

2 个答案:

答案 0 :(得分:1)

您可以使用以下内容:

SRCDIR  := $(shell ls -d lib_*/)

CC      := gcc
DB      := gdb
OBJDIR  := obj
CFLAGS  := -Wall -Werror -Wextra -pedantic -O3
LDFLAGS := #

# Rules
all:
    @ # create object directory
    @mkdir -p  $(OBJDIR)/ ;
    @ # go through all source dirs
    @for dir in $(SRCDIR); do \
        echo $$dir && \
        cd $$dir && \
        for n in $$(ls *.c); do \
            m=$${n%%.c}; \
            if [ ! -e ../$(OBJDIR)/$$m.o ] || \
                [ `stat -c %Y ../$(OBJDIR)/$$m.o` -lt `stat -c %Y $$n` ] || \
                ([ -e $$m.h ] && [ `stat -c %Y ../$(OBJDIR)/$$m.o` -lt `stat -c %Y $$m.h` ]); then \
                echo "Change detected, compiling $$n..."; \
                $(CC) -c \
                    $(CFLAGS) \
                    $(LDFLAGS) \
                    -o ../$(OBJDIR)/$$m.o $$n;\
            fi; \
        done; \
        cd ..; \
    done

以下行添加对目标文件的检查以查看它们是否存在,如果是,则将源修改时间与对象修改时间进行比较(重复make make内部工作的类型)。

 if [ ! -e ../$(OBJDIR)/$$m.o ] || [ `stat -c %Y ../$(OBJDIR)/$$m.o` -lt `stat -c %Y $$n` ] || ([ -e $$m.h ] && [ `stat -c %Y ../$(OBJDIR)/$$m.o` -lt `stat -c %Y $$m.h` ]); then 

答案 1 :(得分:1)

如果您不关心头文件,可以这样做:

SRCS := $(wildcard */*.c)

OBJDIR := obj

OBJS := $(patsubst %.c,$(OBJDIR)/%.o,$(notdir $(SRCS)))

all: $(OBJS)
    @:

$(OBJDIR)/%.o: %.c
    $(CC) -c $(CFLAGS) -o $@ $<

vpath %.c $(wildcard *)

如果您关心明显的标题文件(例如lib_one.c包含lib_one.h),那么您可以进行简单的调整:

$(OBJDIR)/%.o: %.c %.h
    $(CC) -c $(CFLAGS) -o $@ $<

vpath %.c $(wildcard *)
vpath %.h $(wildcard *)

如果您有其他依赖项(例如lib_n.c包含lib_one.h),您可以手动添加它们:

lib_n.o: lib_one.h

或者您可以使用Advanced Auto-Dependency Generation,但这是一种先进的技术,我建议您再离开一天。