I have a large project with a lot of headers and source files. What I want is the following but automatically
Makefile
INCLUDE = -Iinc
CFLAGS = -g
LIB = lib/foo_bar.a
all: obj/foo_print_hello.o\
obj/foo_print_goodbye.o\
obj/bar_print_goodbye.o\
obj/bar_print_hello.o\
obj/main.o\
lib/foo_bar.a\
bin/main\
obj/foo_print_hello.o: src/foo_print_hello.c inc/foo.h
$(CC) $(INCLUDE) -c $(CFLAGS) -o $@ $<
obj/foo_print_goodbye.o: src/foo_print_goodbye.c inc/foo.h
$(CC) $(INCLUDE) -c $(CFLAGS) -o $@ $<
obj/bar_print_goodbye.o: src/bar_print_goodbye.c inc/bar.h
$(CC) $(INCLUDE) -c $(CFLAGS) -o $@ $<
obj/bar_print_hello.o: src/bar_print_hello.c inc/bar.h
$(CC) $(INCLUDE) -c $(CFLAGS) -o $@ $<
obj/main.o: src/main.c inc/foo.h inc/bar.h
$(CC) $(INCLUDE) -c $(CFLAGS) -o $@ $<
lib/foo_bar.a: obj/bar_print_hello.o obj/bar_print_goodbye.o obj/foo_print_goodbye.o obj/foo_print_hello.o inc/bar.h inc/foo.h
ar -crv $@ $^
bin/main: obj/main.o
$(CC) -o $@ $< $(LIB)
The file architecture is as follows
.
├── bin
│ └── main
├── inc
│ ├── bar.h
│ └── foo.h
├── lib
│ └── foo_bar.a
├── makefile
├── obj
│ ├── bar_print_goodbye.o
│ ├── bar_print_hello.o
│ ├── foo_print_goodbye.o
│ ├── foo_print_hello.o
│ └── main.o
└── src
├── bar_print_goodbye.c
├── bar_print_hello.c
├── foo_print_goodbye.c
├── foo_print_hello.c
└── main.c
I want this exact compiling structure where it compiles them all into object files then the library function then the compiling with main. I've seen lots of templates on GNU and around the internet but nothing quite worked. How would I make my makefile automatically make the obj (placing them in the obj dir) then compiling into the archive?
What compiles
cc -Iinc -c -g -o obj/foo_print_hello.o src/foo_print_hello.c
cc -Iinc -c -g -o obj/foo_print_goodbye.o src/foo_print_goodbye.c
cc -Iinc -c -g -o obj/bar_print_goodbye.o src/bar_print_goodbye.c
cc -Iinc -c -g -o obj/bar_print_hello.o src/bar_print_hello.c
cc -Iinc -c -g -o obj/main.o src/main.c
ar -crv lib/foo_bar.a obj/bar_print_hello.o obj/bar_print_goodbye.o obj/foo_print_goodbye.o obj/foo_print_hello.o inc/bar.h inc/foo.h
r - obj/bar_print_hello.o
r - obj/bar_print_goodbye.o
r - obj/foo_print_goodbye.o
r - obj/foo_print_hello.o
r - inc/bar.h
r - inc/foo.h
cc -o bin/main obj/main.o lib/foo_bar.a
Main's output
Hello
Goodbye
Hello
Goodbye
Repo for code:
git@github.com:tlplayer/dummy_makefile_question.git
Follow-Up
So I tried the following makefile
SRCS := $(wildcard src/*.c)
OBJS := $(patsubt src/%.c, obj/%.o, $(SRCS))
LIB := lib/foo_bar.a
all: bin/main
obj/%.o: src/%.c
$(CC) $(INCLUDE) -c $(CFLAGS) -o $@ $<
$(LIB): obj/%.o
ar -crv $@ $^
bin/main: obj/main.o $(LIB)
$(CC) -o $@ $< $(LIB)
The problem is it doesn't know what I want it to. with or without adding the headers to the makefile (foo.h bar.h in the dependencies)
make: *** No rule to make target `obj/%.o', needed by `lib/foo_bar.a'. Stop.
Follow Up 2
Current makefile
INCLUDE = -Iinc
CFLAGS = -g
LIB = lib/foo_bar.a
SRCS := $(wildcard src/*.c)
OBJS := $(patsubt src/%.c, obj/%.o, $(SRCS))
OBJS := $(filter-out obj/main.o, $(OBJS))
all: bin/main\
obj/%.o: src/%.c
$(CC) $(INCLUDE) -c $(CFLAGS) -o $@ $<
$(LIB): $(OBJS)
ar -crv $@ $^
bin/main: obj/main.o $(LIB)
$(CC) -o $@ $^
What the error is
cc -Iinc -c -g -o obj/main.o src/main.c
ar -crv lib/foo_bar.a
cc -o bin/main obj/main.o lib/foo_bar.a
obj/main.o: In function `main':
test/src/main.c:6: undefined reference to `foo_print_hello'
test/src/main.c:7: undefined reference to `foo_print_goodbye'
test/src/main.c:8: undefined reference to `bar_print_hello'
test/src/main.c:9: undefined reference to `bar_print_goodbye'
collect2: error: ld returned 1 exit status
make: *** [bin/main] Error 1
For some reason it compiles main.o then the archive file. But the archive is missing all object files. So why doesn't it include the objects?
Solution
Thanks MadScientist and Topology
INCLUDE = -Iinc
CFLAGS = -g
LIB = lib/foo_bar.a
SRCS := $(wildcard src/*.c)
OBJS := $(patsubst src/%.c, obj/%.o, $(SRCS))
OBJS := $(filter-out obj/main.o, $(OBJS))
all:bin/main\
clean:
rm -f obj/* bin/* lib/*
obj/%.o: src/%.c
$(CC) $(INCLUDE) -c $(CFLAGS) -o $@ $<
lib/foo_bar.a: $(OBJS)
ar -crv $@ $^
bin/main: obj/main.o $(LIB)
$(CC) -o $@ $^