-1

Here is my simple Makefile:

    #create an exe file
    run: link
            gcc link.o -o run
    
    #sketch link.o
    link.o: main.o sum.o
            ld -r main.o sum.o -o link.o
    
    #sketch main.o
    main.o: main.c
            gcc -c main.c -o main.o
    
    #sketch sum.o
    sum.o: sum.c
            gcc -c sum.c -o sum.o
    
    #make clean recipie
    clean:
            rm *.o
            rm run

This makefile may be something kind of immature or weak one.But my real concern is all about the process the target are being hit. Before telling actual question, let's first look its output.

gcc -c main.c -o main.o
gcc -c sum.c -o sum.o
ld -r main.o sum.o -o link.o
cc   link.o   -o link
gcc link.o -o run

My question is: is this because of link the dependency of run or because of link.o mention in command section of run, make command seeks for link.o and again it is because of main.o sum.o the dependencies of link.o it looks for mention dependencies or because of main.o sum.o in command section and then first command in target main.o is encountered and sum.o and link.o respectively? Is it because of file mentioned in dependencies or file mention on the command??

Anup Adhikari
  • 49
  • 1
  • 7

1 Answers1

3

This is probably a duplicate of your earlier question, What actually is causing `The System Can not find the file specified` problem in make?, but let’s use this one to explain in detail what’s going on.

Make takes your Makefile declarations literally:

  1. run: link tells it that run needs link, and the associated recipe tells it that to create run, it should execute gcc link.o -o run
  2. link.o: main.o sum.o tells it that link.o needs main.o and sum.o, and the associated recipe tells it that to create link.o, it should execute ld -r main.o sum.o -o link.o
  3. main.o: main.c tells it that main.o needs main.c, and the associated recipe tells it that to create main.o, it should execute gcc -c main.c -o main.o
  4. sum.o: sum.c does the same for sum.c and sum.o

When you run

make

Make tries to satisfy the first target in the Makefile, run. It sees that there is no link file, and there is no rule in your Makefile which specifies how to build link. However Make “knows” how to build an extensionless file from a .o file, so it uses that built-in rule to build link; that resolves to

cc link.o -o link

which is where the cc command comes from (strictly speaking, it’s the default value of the $(CC) Make variable).

Once link is available, Make considers that the prerequisites for run are satisfied, and it runs the corresponding recipe:

gcc link.o -o run

Note that link isn’t actually used here. It only confuses things; you should write the first rule as

run: link.o

In detail, Make resolves run as follows:

  • run needs link
  • link has no explicit rule, but can be built using the built-in rule from link.o
  • link.o needs main.o and sum.o
  • main.o needs main.c, which exists
  • sum.o needs sum.c, which exists

The prequisites are now resolved, and Make can run the recipes:

  • gcc -c main.o -o main.o to build main.o
  • gcc -c sum.c -o sum.o to build sum.o
  • ld -r main.o sum.o -o link.o to build link.o
  • cc link.o -o link to build link
  • gcc link.o -o run to build run

If you rewrite the run rule as run: link.o, the resolution changes to

  • run needs link.o
  • link.o needs main.o and sum.o
  • main.o needs main.c, which exists
  • sum.o needs sum.c, which exists

and the build to

  • gcc -c main.o -o main.o to build main.o
  • gcc -c sum.c -o sum.o to build sum.o
  • ld -r main.o sum.o -o link.o to build link.o
  • gcc link.o -o run to build run
Stephen Kitt
  • 411,918
  • 54
  • 1,065
  • 1,164