2

I have the following Makefile:

SRC = $(wildcard *.s)
BIN = $(SRC:.s=)

all: $(BIN)
    echo 4

There is an assembler file (fizzbuzz.s) in the current directory. When I do make command it runs

cc fizzbuzz.s -o fizzbuzz

and I don't understand why it is happenning? What is wrong?

UPDATE:

The same happens when I use another Makefile:

.PHONY: clean all

AS = nasm
LNK = ld 
SRC = $(wildcard *.s)
BIN := $(SRC:.s=)

all: $(BIN)

%: %.o
    $(LNK) -melf_i386 $< -o $@
%.o: %.s
    $(AS) -f elf $< -o $@
clean:
    rm -f $(BIN)
TigerTV.ru
  • 1,058
  • 2
  • 16
  • 34
  • 2
    There are built-in default recipes, like using `cc` to compile `.s` – Barmar Jan 01 '19 at 01:51
  • @Barmar, how can I change the behavior? – TigerTV.ru Jan 01 '19 at 01:58
  • What do you want it to do instead? – Barmar Jan 01 '19 at 02:01
  • 1
    Your second makefile uses `nasm` for `.asm` files, not `.s` files. – Barmar Jan 01 '19 at 02:01
  • 2
    [Make gcc the default compiler of make](https://stackoverflow.com/questions/24051208/make-gcc-the-default-compiler-of-make) is not *quite* duplicative, but certainly relevant. – Charles Duffy Jan 01 '19 at 02:06
  • I suspect you'll get what you want if you simply change `%.asm` to `%.s`, or make the rule work with both suffixes. But since you haven't stated what the desired result is, it's not clear. – Barmar Jan 01 '19 at 02:10
  • Yes, it works with `*.asm`, but why it doesn't work with `*.s`? nasm can compile the file with the extension. PS. Happy New Year! – TigerTV.ru Jan 01 '19 at 02:12
  • I found the way to change the behavior https://stackoverflow.com/a/52603343/9210255 Thanks all! – TigerTV.ru Jan 01 '19 at 02:27
  • Consider adding that as an answer -- unless you're okay with the question just being marked as a duplicate. (Let me know if it's the latter -- both Barmar and I hold dupehammers for the linux tag and can do that singlehandedly). – Charles Duffy Jan 01 '19 at 02:28
  • @CharlesDuffy, OK, I will add the answer, but I need to understand why it is happening, so it takes some time. – TigerTV.ru Jan 01 '19 at 02:29
  • Also see [Using Implicit Rules](https://www.gnu.org/software/make/manual/html_node/Implicit-Rules.html) in the GNU Make manual. – jww Jan 01 '19 at 14:53

1 Answers1

3

A simple answer is make's behavior. But it doesn't give understanding how it works, so let's go deeper.

We begin with the first Makefile. Because my directory has only one file fizzbuzz.s, the variable BIN will be equal fizzbuzz. Make searches the fizzbuzz target, but there is no the target. For that reason make processes built-in rules. It searches files with extension added to fizzbuzz target and if it has searched the files it processes own rules. I tried to remove the Makefile and run command: make fizzbuzz and it runs another

cc fizzbuzz.s -o fizzbuzz.

It's equal to the first Makefile.

Now, we'll use the second Makefile. When I changed the .s extension on .asm it worked. Interesting behavior, it's because make doesn't have built-in rules for .asm extension. I wanted to get understanding so I returned .asm to .s back. My second Makefile has a rule for target without extension:

%: %.o
    $(LNK) -melf_i386 $< -o $@

But it doesn't work as expected and works like without Makefile. This happens, I suppose, because % has the last priority execution after built-in rules. We can change the behaviour by adding MAKEFLAGS += --no-builtin-rules in the Makefile, and everything works fine.

But I noted one weird thing without the option. I did the command make fizzbuzz.o and it has been built fizzbuzz.o(it processes command from my Makefile). So, OK. Let's run make again. I run it and it built me the final fizzbuzz target. Surprise!

So the rule

%: %.o
    $(LNK) -melf_i386 $< -o $@

is working when there are object files(.o) in the current directory. I don't know what it is, a bug or a feature(IMHO a weird feature), but it works so.

Finally, we have two solutions to make second Makefile working and they are the following:

  • omit built-in rules by replacing .s extension by .asm or any other which doesn't have built-in rules in make
  • disable built-in rules by adding to Makefile an option MAKEFLAGS += --no-builtin-rules or run with make -R or make -r
TigerTV.ru
  • 1,058
  • 2
  • 16
  • 34