4

For unknown reason, GNU Make doesn't do the job for me. I have this MAKE file, I did ensure for every recipe, I use tab, not space. however I look at it, I just couldn't spot anywhere that would cause the error message.

OS: Ubuntu 17.10 / GNU Make: 4.1 / GCC: Cross compile to i686-elf-gcc.

Running it with: make (in the same directory) give me

make: *** No rule to make target '%.o', needed by 'kernel.elf'.  Stop.

I have a bash script that does exactly the same thing and it works like charm. Can any one tell what am I doing wrong?

Makefile:

NASM=nasm
QEMU=qemu-system-i386
GCC=~/opt/cross/bin/i686-elf-gcc
CFLAGS=-std=c11 -ffreestanding -Wall -Wextra -Werror -masm=intel -g -O0
ASFLAGS=-felf32 -g

.PHONY: all clean
all:boot.iso

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

%.so : %.asm
    $(NASM) $(ASFLAGS) -o $@ $<

kernel.elf : %.o
    $(GCC) -T link.ld -o $@ -ffreestanding -O0 -nostdlib -lgcc --verbose $^
    grub-file --is-x86-multiboot2 kernel.elf

boot.iso : kernel.elf grub.cfg
    mkdir -p ./iso/boot/grub
    cp kernel.elf ./iso/boot
    cp grub.cfg ./iso/boot/grub
    grub-mkrescue -o $@ ./iso

run: boot.iso
    $(QEMU) -cdrom $< -D log/qemu.log -d guest_errors -m 2048M -daemonize -serial file:log/boot.log

debug: boot.iso
    $(QEMU) -cdrom $< -D log/qemu.log -d guest_errors -m 2048M -daemonize -serial file:log/boot.log -s -S
    gdb ./kernel.elf -ex "target remote :1234" --tui

clean:
    rm -f ./*.o
    rm -f ./kernel.elf
    rm -rf ./iso

Running make with -d option output this:

GNU Make 4.1
Built for x86_64-pc-linux-gnu
Copyright (C) 1988-2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Reading makefiles...
Reading makefile 'Makefile'...
Updating makefiles....
 Considering target file 'Makefile'.
  Looking for an implicit rule for 'Makefile'.

  ... a bunch of ...
  Trying pattern rule with stem 'Makefile'.
  Trying implicit prerequisite 'Makefile.o'. <-- last line
  ... end a bunch of ...

  Looking for a rule with intermediate file 'Makefile.o'.
   Avoiding implicit rule recursion.

   ... a bunch of ...
   Trying pattern rule with stem 'Makefile'.
   Trying implicit prerequisite 'Makefile.c'. <--- last line
   ... end a bunch of ...

   Looking for a rule with intermediate file 'Makefile.c'.
    Avoiding implicit rule recursion.
    Avoiding implicit rule recursion.

    ... a bunch of ...
    Trying pattern rule with stem 'Makefile'.
    Trying implicit prerequisite 'Makefile.y'.
    ... end a bunch of ...

    Looking for a rule with intermediate file 'Makefile.y'.
     Avoiding implicit rule recursion.
     Avoiding implicit rule recursion.
     Avoiding implicit rule recursion.

     ... a bunch of ...
     Trying pattern rule with stem 'Makefile.y'.
     Trying implicit prerequisite 'SCCS/s.Makefile.y'. <-- last line
     ... end a bunch of ...
     ... I'm too tired to clean it up ....
     ... is all the same thing for Makefile

Updating goal targets....
Considering target file 'all'.
 File 'all' does not exist.
  Considering target file 'boot.iso'.
   File 'boot.iso' does not exist.
    Considering target file 'kernel.elf'.
     File 'kernel.elf' does not exist.
      Considering target file '%.o'.
       File '%.o' does not exist.
       Looking for an implicit rule for '%.o'.
       Trying pattern rule with stem '%'.
       Trying rule prerequisite '%.c'.
       Trying pattern rule with stem '%'.
       Trying rule prerequisite '%.cc'.
       Trying pattern rule with stem '%'.
       Trying rule prerequisite '%.C'.
       Trying pattern rule with stem '%'.
       Trying rule prerequisite '%.cpp'.
       Trying pattern rule with stem '%'.
       Trying rule prerequisite '%.p'.
       Trying pattern rule with stem '%'.
       Trying rule prerequisite '%.f'.
       Trying pattern rule with stem '%'.
       Trying rule prerequisite '%.F'.
       Trying pattern rule with stem '%'.
       Trying rule prerequisite '%.m'.
       Trying pattern rule with stem '%'.
       Trying rule prerequisite '%.r'.
       Trying pattern rule with stem '%'.
       Trying rule prerequisite '%.s'.
       Trying pattern rule with stem '%'.
       Trying rule prerequisite '%.S'.
       Trying pattern rule with stem '%'.
       Trying rule prerequisite '%.mod'.
       Trying pattern rule with stem '%.o'.
       Trying implicit prerequisite '%.o,v'.
       Trying pattern rule with stem '%.o'.
       Trying implicit prerequisite 'RCS/%.o,v'.
       Trying pattern rule with stem '%.o'.
       Trying implicit prerequisite 'RCS/%.o'.
       Trying pattern rule with stem '%.o'.
       Trying implicit prerequisite 's.%.o'.
       Trying pattern rule with stem '%.o'.
       Trying implicit prerequisite 'SCCS/s.%.o'.
       Trying pattern rule with stem '%'.
       Trying rule prerequisite '%.c'.
       Looking for a rule with intermediate file '%.c'.
        Avoiding implicit rule recursion.
        Trying pattern rule with stem '%'.
        Trying rule prerequisite '%.y'.
        Trying pattern rule with stem '%'.
        Trying rule prerequisite '%.l'.
        Trying pattern rule with stem '%'.
        Trying rule prerequisite '%.w'.
        Trying pattern rule with stem '%'.
        Trying rule prerequisite '%.w'.
        Trying pattern rule with stem '%.c'.
        Trying implicit prerequisite '%.c,v'.
        Trying pattern rule with stem '%.c'.
        Trying implicit prerequisite 'RCS/%.c,v'.
        Trying pattern rule with stem '%.c'.
        Trying implicit prerequisite 'RCS/%.c'.
        Trying pattern rule with stem '%.c'.
        Trying implicit prerequisite 's.%.c'.
        Trying pattern rule with stem '%.c'.
        Trying implicit prerequisite 'SCCS/s.%.c'.
        Trying pattern rule with stem '%'.
        Trying rule prerequisite '%.y'.
        Looking for a rule with intermediate file '%.y'.
         Avoiding implicit rule recursion.
         Avoiding implicit rule recursion.
         Trying pattern rule with stem '%.y'.
         Trying implicit prerequisite '%.y,v'.
         Trying pattern rule with stem '%.y'.
         Trying implicit prerequisite 'RCS/%.y,v'.
         Trying pattern rule with stem '%.y'.
         Trying implicit prerequisite 'RCS/%.y'.
         Trying pattern rule with stem '%.y'.
         Trying implicit prerequisite 's.%.y'.
         Trying pattern rule with stem '%.y'.
         Trying implicit prerequisite 'SCCS/s.%.y'.
        Trying pattern rule with stem '%'.
        Trying rule prerequisite '%.l'.
        Looking for a rule with intermediate file '%.l'.
         Avoiding implicit rule recursion.
         Avoiding implicit rule recursion.
         Trying pattern rule with stem '%.l'.
         Trying implicit prerequisite '%.l,v'.
         Trying pattern rule with stem '%.l'.
         Trying implicit prerequisite 'RCS/%.l,v'.
         Trying pattern rule with stem '%.l'.
         Trying implicit prerequisite 'RCS/%.l'.
         Trying pattern rule with stem '%.l'.
         Trying implicit prerequisite 's.%.l'.
         Trying pattern rule with stem '%.l'.
         Trying implicit prerequisite 'SCCS/s.%.l'.
        Trying pattern rule with stem '%'.
        Trying rule prerequisite '%.w'.
        Looking for a rule with intermediate file '%.w'.
         Avoiding implicit rule recursion.
         Avoiding implicit rule recursion.
         Trying pattern rule with stem '%.w'.
         Trying implicit prerequisite '%.w,v'.
         Trying pattern rule with stem '%.w'.
         Trying implicit prerequisite 'RCS/%.w,v'.
         Trying pattern rule with stem '%.w'.
         Trying implicit prerequisite 'RCS/%.w'.
         Trying pattern rule with stem '%.w'.
         Trying implicit prerequisite 's.%.w'.
         Trying pattern rule with stem '%.w'.
         Trying implicit prerequisite 'SCCS/s.%.w'.
        Trying pattern rule with stem '%'.
        Rejecting impossible rule prerequisite '%.w'.
       Trying pattern rule with stem '%'.
       Trying rule prerequisite '%.cc'.
       Looking for a rule with intermediate file '%.cc'.
        Avoiding implicit rule recursion.
        Trying pattern rule with stem '%.cc'.
        Trying implicit prerequisite '%.cc,v'.
        Trying pattern rule with stem '%.cc'.
        Trying implicit prerequisite 'RCS/%.cc,v'.
        Trying pattern rule with stem '%.cc'.
        Trying implicit prerequisite 'RCS/%.cc'.
        Trying pattern rule with stem '%.cc'.
        Trying implicit prerequisite 's.%.cc'.
        Trying pattern rule with stem '%.cc'.
        Trying implicit prerequisite 'SCCS/s.%.cc'.
       Trying pattern rule with stem '%'.
       Trying rule prerequisite '%.C'.
       Looking for a rule with intermediate file '%.C'.
        Avoiding implicit rule recursion.
        Trying pattern rule with stem '%.C'.
        Trying implicit prerequisite '%.C,v'.
        Trying pattern rule with stem '%.C'.
        Trying implicit prerequisite 'RCS/%.C,v'.
        Trying pattern rule with stem '%.C'.
        Trying implicit prerequisite 'RCS/%.C'.
        Trying pattern rule with stem '%.C'.
        Trying implicit prerequisite 's.%.C'.
        Trying pattern rule with stem '%.C'.
        Trying implicit prerequisite 'SCCS/s.%.C'.
       Trying pattern rule with stem '%'.
       Trying rule prerequisite '%.cpp'.
       Looking for a rule with intermediate file '%.cpp'.
        Avoiding implicit rule recursion.
        Trying pattern rule with stem '%.cpp'.
        Trying implicit prerequisite '%.cpp,v'.
        Trying pattern rule with stem '%.cpp'.
        Trying implicit prerequisite 'RCS/%.cpp,v'.
        Trying pattern rule with stem '%.cpp'.
        Trying implicit prerequisite 'RCS/%.cpp'.
        Trying pattern rule with stem '%.cpp'.
        Trying implicit prerequisite 's.%.cpp'.
        Trying pattern rule with stem '%.cpp'.
        Trying implicit prerequisite 'SCCS/s.%.cpp'.
       Trying pattern rule with stem '%'.
       Trying rule prerequisite '%.p'.
       Looking for a rule with intermediate file '%.p'.
        Avoiding implicit rule recursion.
        Trying pattern rule with stem '%'.
        Trying rule prerequisite '%.web'.
        Trying pattern rule with stem '%.p'.
        Trying implicit prerequisite '%.p,v'.
        Trying pattern rule with stem '%.p'.
        Trying implicit prerequisite 'RCS/%.p,v'.
        Trying pattern rule with stem '%.p'.
        Trying implicit prerequisite 'RCS/%.p'.
        Trying pattern rule with stem '%.p'.
        Trying implicit prerequisite 's.%.p'.
        Trying pattern rule with stem '%.p'.
        Trying implicit prerequisite 'SCCS/s.%.p'.
        Trying pattern rule with stem '%'.
        Trying rule prerequisite '%.web'.
        Looking for a rule with intermediate file '%.web'.
         Avoiding implicit rule recursion.
         Avoiding implicit rule recursion.
         Trying pattern rule with stem '%.web'.
         Trying implicit prerequisite '%.web,v'.
         Trying pattern rule with stem '%.web'.
         Trying implicit prerequisite 'RCS/%.web,v'.
         Trying pattern rule with stem '%.web'.
         Trying implicit prerequisite 'RCS/%.web'.
         Trying pattern rule with stem '%.web'.
         Trying implicit prerequisite 's.%.web'.
         Trying pattern rule with stem '%.web'.
         Trying implicit prerequisite 'SCCS/s.%.web'.
       Trying pattern rule with stem '%'.
       Trying rule prerequisite '%.f'.
       Looking for a rule with intermediate file '%.f'.
        Avoiding implicit rule recursion.
        Trying pattern rule with stem '%'.
        Trying rule prerequisite '%.F'.
        Trying pattern rule with stem '%'.
        Trying rule prerequisite '%.r'.
        Trying pattern rule with stem '%.f'.
        Trying implicit prerequisite '%.f,v'.
        Trying pattern rule with stem '%.f'.
        Trying implicit prerequisite 'RCS/%.f,v'.
        Trying pattern rule with stem '%.f'.
        Trying implicit prerequisite 'RCS/%.f'.
        Trying pattern rule with stem '%.f'.
        Trying implicit prerequisite 's.%.f'.
        Trying pattern rule with stem '%.f'.
        Trying implicit prerequisite 'SCCS/s.%.f'.
        Trying pattern rule with stem '%'.
        Trying rule prerequisite '%.F'.
        Looking for a rule with intermediate file '%.F'.
         Avoiding implicit rule recursion.
         Avoiding implicit rule recursion.
         Trying pattern rule with stem '%.F'.
         Trying implicit prerequisite '%.F,v'.
         Trying pattern rule with stem '%.F'.
         Trying implicit prerequisite 'RCS/%.F,v'.
         Trying pattern rule with stem '%.F'.
         Trying implicit prerequisite 'RCS/%.F'.
         Trying pattern rule with stem '%.F'.
         Trying implicit prerequisite 's.%.F'.
         Trying pattern rule with stem '%.F'.
         Trying implicit prerequisite 'SCCS/s.%.F'.
        Trying pattern rule with stem '%'.
        Trying rule prerequisite '%.r'.
        Looking for a rule with intermediate file '%.r'.
         Avoiding implicit rule recursion.
         Avoiding implicit rule recursion.
         Trying pattern rule with stem '%'.
         Rejecting impossible rule prerequisite '%.l'.
         Trying pattern rule with stem '%.r'.
         Trying implicit prerequisite '%.r,v'.
         Trying pattern rule with stem '%.r'.
         Trying implicit prerequisite 'RCS/%.r,v'.
         Trying pattern rule with stem '%.r'.
         Trying implicit prerequisite 'RCS/%.r'.
         Trying pattern rule with stem '%.r'.
         Trying implicit prerequisite 's.%.r'.
         Trying pattern rule with stem '%.r'.
         Trying implicit prerequisite 'SCCS/s.%.r'.
       Trying pattern rule with stem '%'.
       Rejecting impossible rule prerequisite '%.F'.
       Trying pattern rule with stem '%'.
       Trying rule prerequisite '%.m'.
       Looking for a rule with intermediate file '%.m'.
        Avoiding implicit rule recursion.
        Trying pattern rule with stem '%'.
        Trying rule prerequisite '%.ym'.
        Trying pattern rule with stem '%.m'.
        Trying implicit prerequisite '%.m,v'.
        Trying pattern rule with stem '%.m'.
        Trying implicit prerequisite 'RCS/%.m,v'.
        Trying pattern rule with stem '%.m'.
        Trying implicit prerequisite 'RCS/%.m'.
        Trying pattern rule with stem '%.m'.
        Trying implicit prerequisite 's.%.m'.
        Trying pattern rule with stem '%.m'.
        Trying implicit prerequisite 'SCCS/s.%.m'.
        Trying pattern rule with stem '%'.
        Trying rule prerequisite '%.ym'.
        Looking for a rule with intermediate file '%.ym'.
         Avoiding implicit rule recursion.
         Avoiding implicit rule recursion.
         Trying pattern rule with stem '%.ym'.
         Trying implicit prerequisite '%.ym,v'.
         Trying pattern rule with stem '%.ym'.
         Trying implicit prerequisite 'RCS/%.ym,v'.
         Trying pattern rule with stem '%.ym'.
         Trying implicit prerequisite 'RCS/%.ym'.
         Trying pattern rule with stem '%.ym'.
         Trying implicit prerequisite 's.%.ym'.
         Trying pattern rule with stem '%.ym'.
         Trying implicit prerequisite 'SCCS/s.%.ym'.
       Trying pattern rule with stem '%'.
       Rejecting impossible rule prerequisite '%.r'.
       Trying pattern rule with stem '%'.
       Trying rule prerequisite '%.s'.
       Looking for a rule with intermediate file '%.s'.
        Avoiding implicit rule recursion.
        Trying pattern rule with stem '%'.
        Trying rule prerequisite '%.S'.
        Trying pattern rule with stem '%.s'.
        Trying implicit prerequisite '%.s,v'.
        Trying pattern rule with stem '%.s'.
        Trying implicit prerequisite 'RCS/%.s,v'.
        Trying pattern rule with stem '%.s'.
        Trying implicit prerequisite 'RCS/%.s'.
        Trying pattern rule with stem '%.s'.
        Trying implicit prerequisite 's.%.s'.
        Trying pattern rule with stem '%.s'.
        Trying implicit prerequisite 'SCCS/s.%.s'.
        Trying pattern rule with stem '%'.
        Trying rule prerequisite '%.S'.
        Looking for a rule with intermediate file '%.S'.
         Avoiding implicit rule recursion.
         Avoiding implicit rule recursion.
         Trying pattern rule with stem '%.S'.
         Trying implicit prerequisite '%.S,v'.
         Trying pattern rule with stem '%.S'.
         Trying implicit prerequisite 'RCS/%.S,v'.
         Trying pattern rule with stem '%.S'.
         Trying implicit prerequisite 'RCS/%.S'.
         Trying pattern rule with stem '%.S'.
         Trying implicit prerequisite 's.%.S'.
         Trying pattern rule with stem '%.S'.
         Trying implicit prerequisite 'SCCS/s.%.S'.
       Trying pattern rule with stem '%'.
       Rejecting impossible rule prerequisite '%.S'.
       Trying pattern rule with stem '%'.
       Trying rule prerequisite '%.mod'.
       Looking for a rule with intermediate file '%.mod'.
        Avoiding implicit rule recursion.
        Trying pattern rule with stem '%.mod'.
        Trying implicit prerequisite '%.mod,v'.
        Trying pattern rule with stem '%.mod'.
        Trying implicit prerequisite 'RCS/%.mod,v'.
        Trying pattern rule with stem '%.mod'.
        Trying implicit prerequisite 'RCS/%.mod'.
        Trying pattern rule with stem '%.mod'.
        Trying implicit prerequisite 's.%.mod'.
        Trying pattern rule with stem '%.mod'.
        Trying implicit prerequisite 'SCCS/s.%.mod'.
       No implicit rule found for '%.o'.
       Finished prerequisites of target file '%.o'.
      Must remake target '%.o'.
make: *** No rule to make target '%.o', needed by 'kernel.elf'.  Stop.
jww
  • 97,681
  • 90
  • 411
  • 885
tongko
  • 139
  • 2
  • 10
  • `$(GCC) -c $< $(CFLAGS) -o $@` -->> `$(GCC) $(CFLAGS) $< -o $@` – Gaurav Pathak Nov 29 '17 at 11:55
  • I think you need to remove the spaces before your colons. Not sure though. – fuz Nov 29 '17 at 11:56
  • @Gaurav, I tried your suggestion but with no luck... – tongko Nov 29 '17 at 12:12
  • @fuz, that doesn't work either. – tongko Nov 29 '17 at 12:13
  • 2
    I think the issue lies in the line `kernel.elf : %.o`, the rule to make `kernel.elf`. Make looks for a target `%.o` but since it is genereic it does not know what files to use. If you use `kernel.elf : kernel.o` or whatever `.o`-files you actually need to make the kernel, it should work. (answered at the same time below) – Hans Petter Taugbøl Kragset Nov 29 '17 at 12:20
  • 1
    Also see [How to place object files in separate subdirectory](https://stackoverflow.com/q/5178125/608639) and [How to make specific binary from specific object file?](https://stackoverflow.com/q/15873011/608639), where the answers seems to tell you to use a wildcard for object files. Maybe GNU Make is not understanding the `*.elf` extension in `kernel.elf`. – jww Nov 29 '17 at 12:33

1 Answers1

10

The problem is in the following rule:

kernel.elf : %.o

GNU Make is actually treating %.o as a prerequisite, and not a pattern.

I would suggest you to define an obj variable which includes the names of the object files and rewrite the rule as:

kernel.elf: $(obj)

A definition of such an obj variable could be:

obj := $(patsubst %.c,%.o,$(wildcard *.c))
obj += $(patsubst %.asm,%.so,$(wildcard *.asm))
JFMR
  • 23,265
  • 4
  • 52
  • 76
  • 1
    It works! Thank you so much! I've been scratching my head whole night! – tongko Nov 29 '17 at 12:40
  • Shouldn't it be a prerequisite though? Otherwise when %.c is updated how will it know to compile the appropriate .o target? – Assimilater Jun 01 '18 at 00:17
  • @Assimilater What I meant is that the original prerequisite is literally `%.o` (i.e., a file called `%.o`, **not** a *pattern* for `.o` files). With my approach, the list of files resulting from the expansion of `$(obj)` becomes the prerequisite of `kernel.elf`. This list consists of `.o` files and, when their corresponding `.c` is updated, the OP's rule `%.o: %.c` is used. – JFMR Jun 02 '18 at 07:21