Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Makefile C subdirectory rule to make obj

I am running a simple Makefile with no problems:

CC=gcc
CFLAGS= -std=c99 -ggdb -Wall -I.
DEPS = hellomake.h
OBJ = hellomake.o hellofunc.o 

%.o: %.c $(DEPS)
    $(CC) -c -o $@ $< $(CFLAGS)

hellomake: $(OBJ)
    gcc -o $@ $^ $(CFLAGS)

The files are in the main project's directory:

./project/Makefile
./project/hellomake.c
./project/hellomake.h

Then I tried to organized the files, and put things like:

./project/Makefile
./project/src/hellomake.c
./project/include/hellomake.h

and extra subdirectories directories:

./project/lib
./project/obj

Then the new version of the Makefile:

IDIR =include
CC=gcc
CFLAGS= -std=c99 -ggdb -Wall -I$(IDIR)

ODIR=obj
LDIR =lib

LIBS=-lm

_DEPS = hellomake.h
DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS))

_OBJ = hellomake.o hellofunc.o 
OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))


$(ODIR)/%.o: %.c $(DEPS)
    $(CC) -c -o $@ $< $(CFLAGS)

hellomake: $(OBJ)
    gcc -o $@ $^ $(CFLAGS) $(LIBS)

.PHONY: clean

clean:
    rm -f $(ODIR)/*.o *~ core $(INCDIR)/*~ 

I am compiling on Linux using Emacs with the gcc compiler:

$ gcc --version
gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3

Then, I run on Emacs:

<Esc> 
x
compile
make

And it gives the message:

"./project/src/" -*-
make: *** No rule to make target `obj/hellomake.o', needed by `hellomake'.  Stop.
Compilation exited abnormally with code 2 at Wed Oct  3 17:10:01

What rule should be missing to be included in the Makefile file?

All comments and suggestions are highly appreciated.


Thanks for your suggestion, it is added to the code. Then the compiler complains:

make -k 
make: *** No rule to make target `src/hellomake.c', needed by `obj/hellomake.o'.
make: *** No rule to make target `../include/hellomake.h', needed by `obj/hellomake.o'.
make: Target `obj/hellomake.o' not remade because of errors

Some other suggestion?

Thanks in advance!

like image 414
ThreaderSlash Avatar asked Oct 03 '12 14:10

ThreaderSlash


1 Answers

To fix the error make: *** No rule to make target 'obj/hellomake.o', needed by 'hellomake'. Stop.

Change this line:

$(ODIR)/%.o: %.c $(DEPS) 

To:

$(OBJ): $(ODIR)/%.o: src/%.c $(DEPS)

This creates a rule for all objects in the $(OBJ) variable. The second parameter ('$(ODIR)/%.o') extracts the file name from the full path in order to pass just the file name to the third parameter ('src/%.c').

like image 85
Kristina Avatar answered Oct 20 '22 07:10

Kristina