Skip to content

Instantly share code, notes, and snippets.

@ohmree
Last active December 23, 2019 22:05
Show Gist options
  • Save ohmree/06a450225217a11e9f8404dd1dcacd20 to your computer and use it in GitHub Desktop.
Save ohmree/06a450225217a11e9f8404dd1dcacd20 to your computer and use it in GitHub Desktop.
Makefile trouble

Here's the output of make (which is the debug target by default):

cc -Wall -Wpedantic -Wextra -Og -ggdb -DDEBUG  -c -o main.o main.c
cc -Wall -Wpedantic -Wextra -Og -ggdb -DDEBUG  -c -o test.o test.c
OBJS = out/debug/main.o out/debug/test.o
Compiling executable test:
cc -DDEBUG -Wall -Wpedantic -Wextra -Og -ggdb  out/debug/main.o out/debug/test.o -o o
ut/debug/test
cc: error: out/debug/main.o: No such file or directory
cc: error: out/debug/test.o: No such file or directory
cc: fatal error: no input files
compilation terminated.
make: *** [Makefile:36: executable] Error 1

And make release, pretty much the same:

OBJS = out/release/main.o out/release/test.o
Compiling executable test:
cc -DNDEBUG -Wall -Wpedantic -Wextra -Os -flto out/release/main.o out/release/test.o
-o out/release/test
cc: error: out/release/main.o: No such file or directory
cc: error: out/release/test.o: No such file or directory
cc: fatal error: no input files
compilation terminated.
make: *** [Makefile:36: executable] Error 1

The problem seems to be in the pattern on line 39 of the makefile.

It doesn't echo "Compiling $@ from $<:", therefore the object files must be compiled by some sort of automatic rule.

I think it doesn't even reach the "%.o from %.c" pattern because it doesn't have a name, so the debug and release targets can't depend on it.

#include <stdio.h>
#include "test.h"
int main(void) {
int a = 8, b = 42;
printf("%d + %d = %d\n", a, b, add(a, b));
return 0;
}
SRCS = main.c test.c
OBJS = $(SRCS:.c=.o)
EXENAME = test
CFLAGS = -Wall -Wpedantic -Wextra
all: debug
# Debug settings
debug: CPPFLAGS += -DDEBUG
debug: CFLAGS += -Og -ggdb
debug: OUTDIR = out/debug
debug: EXE = $(OUTDIR)/$(EXENAME)
debug: OBJS := $(addprefix $(OUTDIR)/, $(OBJS))
# Debug build
debug: prep
debug: executable
# Release settings
release: CPPFLAGS += -DNDEBUG
release: CFLAGS += -Os
release: LDFLAGS += -flto
release: OUTDIR = out/release
release: EXE = $(OUTDIR)/$(EXENAME)
release: OBJS := $(addprefix $(OUTDIR)/, $(OBJS))
# Release build
release: prep
release: executable
executable: $(OBJS)
@echo "OBJS = $(OBJS)"
@echo "Compiling executable $(EXENAME):"
$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) $(OBJS) -o $(EXE)
### Make seems to never reach this pattern ###
$(OUTDIR)/%.o: %.c
@echo "Compiling $@ from $<"
$(CC) -c $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) $< -o $(OUTDIR)/$@
prep:
@mkdir -p $(OUTDIR)
clean:
@rm -f out/debug/*.o 2&>/dev/null || true
@rm -f out/debug/$(EXENAME) 2&>/dev/null || true
@rm -f out/release/*.o 2&>/dev/null || true
@rm -f out/release/$(EXENAME) 2&>/dev/null || true
remake: clean all
#include "test.h"
int add(int a, int b) {
return a + b;
}
#ifndef TEST_H
#define TEST_H
int add(int a, int b);
#endif /* TEST_H */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment