user3826752
user3826752

Reputation: 53

How to Compile all C file into Object and place it in subdirectories

How to compile all C files into object files and place them in subdirectories?

I have three directories:

  1. usr - where main.c is located
  2. sources1 - where init_var1.c and init_var2.c are located
  3. include - where the header files are located
  4. obj - this directory should contain the object files made from the C source files in directories listed under 1 and 2.

I wrote this Makefile:

CC=gcc

O_DIR = ./../obj
I_DIR = ./../include

SOURCES := $(wildcard *.c)
OBJECTS := $(SOURCES:.c=.o)

OBJECTS := $(addprefix $(O_DIR)/,$(OBJECTS))

all: $(OBJECTS)

$(OBJECTS): $(SOURCES)
    $(CC) -c -I$(I_DIR) $< -o $@

but the output is

make[1]: enter directory «/home/alexey/exercise/ex_makefile/source»
gcc -c -I./../include init_var1.c -o ../obj/init_var1.o
gcc -c -I./../include init_var1.c -o ../obj/init_var2.o
make[1]: out from directory «/home/alexey/exercise/ex_makefile/source»

However, I need

make[1]: enter directory «/home/alexey/exercise/ex_makefile/source»
gcc -c -I./../include init_var1.c -o ../obj/init_var1.o
gcc -c -I./../include init_var2.c -o ../obj/init_var2.o
make[1]: out from directory «/home/alexey/exercise/ex_makefile/source»

Please help, how can this be done?

Upvotes: 1

Views: 2507

Answers (1)

dkasak
dkasak

Reputation: 2703

You are setting SOURCES to equal the wildcard expansion of *.c. This expands to a list of all your .c files and therefore, the line

$(OBJECTS): $(SOURCES)

expands to something like

a.o b.o c.o ... : a.c b.c c.c ...

Note that this is wrong semantically since each of your object files shouldn't depend on all the source files.

Since the automatic variable $< denotes the name of the first prerequisite, each of the object files a.o, b.o, c.o and so forth gets created using the source file a.c.


What you want instead is a pattern rule:

You define an implicit rule by writing a pattern rule. A pattern rule looks like an ordinary rule, except that its target contains the character ‘%’ (exactly one of them). The target is considered a pattern for matching file names; the ‘%’ can match any nonempty substring, while other characters match only themselves.

This will allow you to make each of your object files depend only on their corresponding source file (and it will also make $< expand to the correct file since the first prerequisite will be the only prerequisite). Therefore, your rule should look like this:

%.o : %.c
    $(CC) -c -I$(I_DIR) $< -o $(O_DIR)/$@

In fact, the examples page for pattern rules of the GNU make manual has an example very similar to your rule.

Upvotes: 2

Related Questions