7

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!

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
ThreaderSlash
  • 1,313
  • 3
  • 27
  • 43

3 Answers3

14

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').

Kristina
  • 883
  • 1
  • 9
  • 24
  • Hello Ryan. You are right.. the files were missing in the "src/". I also delete ".." as you suggested. But one error is left: make: *** No rule to make target `/include/hellomake.h', needed by `obj/hellomake.o'. – ThreaderSlash Oct 04 '12 at 15:10
  • Remove the beginning / from include. That / tells the Makefile to look in the root directory of the filesystem instead of your project folder. – Kristina Oct 04 '12 at 16:39
  • Ryan thanks again! I took off the "/". The one remaining error is gone. Then in (gdb) run ... gives: {{ (gdb) run Starting program: No executable file specified. Use the "file" or "exec-file" command.}} – ThreaderSlash Oct 04 '12 at 19:07
  • No problem! I think you better make a new post about your gdb problem though. – Kristina Oct 04 '12 at 20:15
-1

Ok. Now I am trying another example found here [ How can I create a Makefile for C projects with SRC, OBJ, and BIN subdirectories? ] and here it goes:

TARGET   = hi.sh
CC       = gcc
# compiling flags here
CFLAGS   = -std=c99 -ggdb -Wall -I./src
TARGET   = bin/hi.sh

LINKER   = gcc -o
# linking flags here
LFLAGS   = -Wall -I. -lm

# change these to set the proper directories where each files shoould be
SRCDIR   = src
OBJDIR   = obj
BINDIR   = bin

SOURCES  := $(wildcard $(SRCDIR)/*.c)
INCLUDES := $(wildcard $(SRCDIR)/*.h)
OBJECTS  := $(SOURCES:$(SRCDIR)/%.c=$(OBJDIR)/%.o)
rm       = rm -f


$(BINDIR)/$(TARGET): $(OBJECTS)
    @$(LINKER) $(TARGETPATH)/$(TARGET) $(LFLAGS) $(OBJECTS)
    @echo "Linking complete!"

OBJECTS  := $(SOURCES:$(SRCDIR)/%.c=$(OBJDIR)/%.o)

$(OBJECTS): $(OBJDIR)/%.o : $(SRCDIR)/%.c
    $(CC) $(CFLAGS) -c $< -o $@
    @echo "Compiled "$<" successfully!"

.PHONEY: clean
clean:
    @$(rm) $(OBJECTS)
    @echo "Cleanup complete!"

.PHONEY: remove
remove: clean
    @$(rm) $(BINDIR)/$(TARGET)
    @echo "Executable removed!"

The files are organized as:

./project/bin/ executable
./project/ojb/*.0
./project/src/*.c and *.h
./project/Makefile

The compiler persists giving only one complaint:

make -k 
/usr/bin/ld: cannot open output file /bin/hi.sh: Permission denied
collect2: ld returned 1 exit status
make: *** [bin/bin/hi.sh] Error 1

Thanks a lot for all comments and suggestions!

Community
  • 1
  • 1
ThreaderSlash
  • 1,313
  • 3
  • 27
  • 43
  • Even if this is years old, your problem simply is that `TARGETPATH` is not defined and therefore `$(TARGETPATH)/$(TARGET)` in the linker will resolve to `/bin`. – xtra Jul 14 '17 at 18:38
-1

I think you should change this line

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

change to

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

add a Space after %.o.

qian
  • 7
  • 4
  • 3
    Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-ask). – Community Sep 16 '21 at 10:14