quickblueblur
quickblueblur

Reputation: 286

My Makefile always builds all files

This is running on FreeBSD which uses PMake instead of GMake.

This is my first Makefile. I used Google a lot to help create this as well as sources such as 'PMake — A Tutorial'. The only problem I can't solve is that every time I run the Makefile, it will compile every file even when there are no changes.

I have four directories. src for my source files, include for my headers, obj for the output and bin for the executable.

What I'm doing is scanning the source folder and creating a list of files to use for both the source and object as well as the headers. Typically I run 'make debug' for debugging and 'make myservice' otherwise.

If I run 'make clean', 'make debug', and 'make debug' it will clean my folders, make all files and then proceed to remake all files instead of doing nothing.

Based on my searching, I'm leaning towards the $(OBJ) rule being the problem, but I don't quite get that. In order for my target and debug rules to build they need to know how to build the 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)

edit - New Makefile

New Makefile. Doesn't rebuild if no changes. Has no debug, still issues figuring out debug.

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)

edit - Working Makefile

Added if conditional for debugging purposes.

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)

Upvotes: 2

Views: 594

Answers (1)

chqrlie
chqrlie

Reputation: 144550

The second make debug cannot do nothing, debug is phony target, not an actual output file, at least the link phase will be re-run.

Furthermore, re-running the link phase with -g -O0 would not recompile you source files with debug information and no optimizations.

Incidentally, the $(TARGET) rule is a phony rule too, it produces $(BINDIR)/$(TARGET), not $(TARGET).

You should rewrite your makefile with different rules to make object and binary output files in different directories for debug and release modes. gmake patterns make this easy to write, I don't know about pmake or cmake for this purpose.

Upvotes: 1

Related Questions