Homunculus Reticulli
Homunculus Reticulli

Reputation: 68366

Specifying build directory in a make file

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

Answers (1)

Beta
Beta

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

Related Questions