Reputation: 68366
I am relatively new to hand crafted make files. I have put together a basic make file for building a library. I want to keep all the temporary .o files in a build directory and have the built executable stored in a bin directory.
My directory structure looks like this:
root
src/
include/
build/
bin/
Makefile
and this is what my make file looks like:
SHLIB = pg_extlib
SRC = src/file1.c \
src/file2.c
OBJS = build/file1.o \
build/file2.o
debug_build:
gcc -g -fPIC -c $(SRC) -I`pg_config --includedir` -I`pg_config --includedir-server` -I/some/required/path/include -Iinclude
gcc -shared -o bin/$(SHLIB).so $(OBJS) -lm -lpq -lmylib_core
clean:
rm -f $(SHLIB) $(OBJS)
The .o files are placed correctly in the build folder, but they also appear in the root folder (where the Makefile resides). How do I fix this?
Upvotes: 4
Views: 14430
Reputation: 99084
I see how you're getting object (.o
) files in the root folder, but I have no idea how you're getting them in the build folder.
Let's take this in stages. First we'll give the object files their own rules:
# Note the use of "-o ..."
build/file1.o:
gcc -g -fPIC -c src/file1.c -I`pg_config --includedir` -I`pg_config --includedir-server` -I/some/required/path/include -Iinclude -o build/file1.o
build/file2.o:
gcc -g -fPIC -c src/file2.c -I`pg_config --includedir` -I`pg_config --includedir-server` -I/some/required/path/include -Iinclude -o build/file2.o
debug_build: $(OBJS)
gcc -shared -o bin/$(SHLIB).so $(OBJS) -lm -lpq -lmylib_core
This is effective, but crude. The object files now go into build/
, but there's lots of redundancy, no dependency handling. So we put in prerequisites, and assuming you're using GNUMake (which you should), we can use Automatic Variables (and I'll abbreviate the -I string just for readability):
build/file1.o: src/file1.c
gcc -g -fPIC -c $< -I... -o $@
build/file2.o: src/file2.c
gcc -g -fPIC -c $< -I... -o $@
debug_build: $(OBJS)
gcc -shared -o bin/$(SHLIB).so $^ -lm -lpq -lmylib_core
Notice that the commands in the object rules are now exactly the same. So we can combine those two rules a couple of different ways. The simplest is:
build/file1.o: src/file1.c
build/file2.o: src/file2.c
build/file1.o build/file2.o:
gcc -g -fPIC -c $< -I... -o $@
Now one or two more little tweaks and we're good to go:
build/file1.o: src/file1.c
build/file2.o: src/file2.c
build/file1.o build/file2.o:
gcc -g -fPIC -c $< -I`pg_config --includedir` -I`pg_config --includedir-server` -I/some/required/path/include -Iinclude -o $@
debug_build: $(OBJS)
gcc -shared -o bin/$(SHLIB).so $^ -lm -lpq -lmylib_core
There are more sophisticated tricks, but that should be plenty for now.
Upvotes: 5