IHazza IHazza - 15 days ago 8
C Question

Why doesn't this generic makefile work?

I'm playing around with writing generic makefiles for my project. What I want to be able to do is provide a list of objects, and have them all compiled automatically. Here is a simple makefile that does that:

OBJS=\
main.o \
more_stuff.o \
and_even_more_stuff.o \

all: $(OBJS)
ld $(OBJS) -o some_library.so

%.o: %.c
gcc $< -o $@


As you can see, all it does is go through all the objects, checks to see if the relevant source file exists, and then it compiles it.

This works, but once I try to put stuff In subdirectories, it works no longer:

OBJS=\
src/main.o \
src/foo/more_stuff.o \
src/bar/and_even_more_stuff.o \

all: $(OBJS)
ld $(OBJS) -o some_library.so

# These targets no longer exist?
%.o: %.c
gcc $< -o $@


In order to get this to work, I have to create a new target for every directory...

OBJS=\
src/main.o \
src/foo/more_stuff.o \
src/bar/and_even_more_stuff.o \

all: $(OBJS)
ld $(OBJS) -o some_library.so

src/%.o: src/%.c
gcc $< -o $@

src/foo/%.o: src/foo/%.c
gcc $< -o $@

src/bar/%.o: src/bar/%.c:
gcc %< -o $@


This works, but its ugly and annoying... how can I just define one target for all the objects (in every directory)?

Hope this made sense!

Answer

You could use recursive make by placing another Makefile in your src subdirectory and executing $(MAKE) -C src as the only rule for the src/%.o target.

You'd similarly need to have a rule for the src/bar/%.o and src/foo/%.o targets that functioned similarly, but without using something like CMake or Autotools, that's possibly the best option.

You could roll your own makefile generator that generates all of the ugly rules for you, but you'd be duplicating the effort of existing software if you generated your own; Autotools and CMake can already generate makefiles for you.

The ugly rules are required in your case. Sorry if you don't like the answer, but that's the truth.