我的 Makefile 总是构建所有文件

My Makefile always builds all files

这是 运行ning on FreeBSD,它使用 PMake 而不是 GMake。

这是我的第一个 Makefile。我经常使用 Google 来帮助创建这个以及 'PMake — A Tutorial' 等来源。我唯一无法解决的问题是,每次我 运行 Makefile 时,即使没有任何更改,它也会编译每个文件。

我有四个目录。我的源文件的 src,我的 headers 的 include,输出的 obj 和可执行文件的 bin。

我正在做的是扫描源文件夹并创建一个文件列表以用于源和 object 以及 headers。通常我 运行 'make debug' 用于调试,'make myservice' 否则。

如果我 运行 'make clean'、'make debug' 和 'make debug' 它将清理我的文件夹,制作所有文件,然后继续重新制作所有文件,而不是什么都不做.

根据我的搜索,我倾向于 $(OBJ) 规则是问题所在,但我不太明白。为了构建我的目标和调试规则,他们需要知道如何构建 objects.

CC  = clang

BINDIR = $(.CURDIR)/bin
OBJDIR = $(.CURDIR)/obj
SRCDIR = $(.CURDIR)/src
INCDIR = $(.CURDIR)/include

CFLAGS  = -Wall -I/usr/local/include -I$(INCDIR)
LFLAGS  = -lm -lpq -lpthread
LIBDIR  = -L/usr/local/lib

_SRC    != ls $(SRCDIR)/*.c
SRC = ${_SRC:T}
INC != ls $(INCDIR)/*.h
OBJ = ${SRC:S/src/obj/g:.c=.o}

TARGET = myservice

$(TARGET): $(OBJ)
    $(CC) -o $(BINDIR)/$@ $(OBJ) $(CFLAGS) $(LIBDIR) $(LFLAGS)

debug: $(OBJ)
    $(CC) -g -O0 -o $(BINDIR)/$(TARGET) $(OBJ) $(CFLAGS) $(LIBDIR) $(LFLAGS)

$(OBJ) : $(SRCDIR)/$(.PREFIX).c $(INCDIR)/$(.PREFIX).h
    $(CC) -c $< $(CFLAGS)

.PHONY: clean
clean:
    rm -rf $(OBJDIR)/*.o $(BINDIR)/$(TARGET)

编辑 - 新建 Makefile

新的生成文件。如果没有更改,则不会重建。没有调试,仍然无法解决调试问题。

CC      = clang

BINDIR = $(.CURDIR)/bin
OBJDIR = $(.CURDIR)/obj
SRCDIR = $(.CURDIR)/src
INCDIR = $(.CURDIR)/include

CFLAGS  = -Wall -I/usr/local/include -I$(INCDIR)
LFLAGS  = -lm -lpq -lpthread
LIBDIR  = -L/usr/local/lib

TARGET = $(BINDIR)/myservice

_SRC    != ls $(SRCDIR)/*.c
SRC     = ${_SRC:T}
INC     != ls $(INCDIR)/*.h
OBJ     = ${SRC:S/src/obj/g:.c=.o}

$(TARGET): $(OBJ)
        $(CC) -o $(TARGET) $(OBJ) $(CFLAGS) $(LIBDIR) $(LFLAGS)

$(OBJ) : $(SRCDIR)/$(.PREFIX).c $(INCDIR)/$(.PREFIX).h
        $(CC) $(CFLAGS) -c $< -o $@

.PHONY: clean
clean:
        rm -rf $(OBJDIR)/*.o $(TARGET)

编辑 - 工作 Makefile

为调试目的添加条件。

CC  = clang

BINDIR = $(.CURDIR)/bin
OBJDIR = $(.CURDIR)/obj
SRCDIR = $(.CURDIR)/src
INCDIR = $(.CURDIR)/include

CFLAGS  = -Wall -I/usr/local/include -I$(INCDIR)
.if make(debug)
CFLAGS += -g -O0
.endif
LFLAGS  = -lm -lpq -lpthread
LIBDIR  = -L/usr/local/lib

TARGET = $(BINDIR)/myservice

_SRC    != ls $(SRCDIR)/*.c
SRC = ${_SRC:T}
INC != ls $(INCDIR)/*.h
OBJ = ${SRC:S/src/obj/g:.c=.o}

all: $(TARGET)

debug: $(TARGET)

$(TARGET): $(OBJ)
    $(CC) -o $(TARGET) $(OBJ) $(CFLAGS) $(LIBDIR) $(LFLAGS)

$(OBJ): $(SRCDIR)/$(.PREFIX).c $(INCDIR)/$(.PREFIX).h
    $(CC) $(CFLAGS) -c $< -o $@

.PHONY: clean
clean:
    rm -rf $(OBJDIR)/*.o $(TARGET)

第二个make debug不能什么都不做,debug是假目标,不是真正的输出文件,至少link阶段会重新运行。

此外,使用 -g -O0 重新 运行 调整 link 阶段不会重新编译带有调试信息且没有优化的源文件。

顺便说一下,$(TARGET) 规则也是一个伪规则,它生成 $(BINDIR)/$(TARGET),而不是 $(TARGET)

您应该使用不同的规则重写您的 makefile,以便在不同的目录中为调试和发布模式生成对象和二进制输出文件。 gmake 模式使这很容易写,我不知道 pmakecmake 用于此目的。