antigravityguy
antigravityguy

Reputation: 157

Compile any C Program using just "make" (From a Makefile)



I'm learning C Programming through "Learn C the Hard Way." I am currently (for quite a long time) on Exercise 2, which can be found here: http://c.learncodethehardway.org/book/ex2.html

In the extra credit section, there is a challenge which asks us to edit the Makefile so we can compile the .c file (ex1.c) using just the command "make". This is what the challenge exactly says:

Create an all: ex1 target that will build ex1 with just the command make.

Through looking here and a bunch of other places, this is the code I think is correct:

CFLAGS="-Wall" -g

all: ex1
    CFLAGS="-Wall" -g

clean:
    rm -f ex1

However, when I try to run this, I get the compiled file and keep getting an error:

cc "-Wall" -g    ex1.c   -o ex1
CFLAGS="-Wall" -g
/bin/sh: 1: -g: not found
make: *** [all] Error 127

What is happening here? What is the reason behind the error message? How can I fix this?

Thanks guys.

Upvotes: 8

Views: 3315

Answers (3)

Jens
Jens

Reputation: 72639

CFLAGS = -Wall -g

all: ex1

clean:
    rm -f ex1

Should be all you need since make has a built-in default rule to compile a .c file to an executable.

Your mistake is to use a variable assignment as a command. The part with

 CFLAGS="-Wall" -g

tries to run the command -g with a one-shot variable assignment CFLAGS="-Wall".

Upvotes: 4

AMR
AMR

Reputation: 604

I would like to suggest one adjustment so that you can build ex1 just by entering make, regardless if this is the first compilation or a recompilaiton of the source code.

Source: ex1.c

Makefile:

CFLAGS=-Wall -g

all : clean ex1

clean:
    rm -rf ex1 ex1.dSYM

.PHONY: all clean

By adding the clean Phony Target as the first prerequisite for all, it will execute the rm -rf ex1 ex1.dSYM command prior to executing the implied cc command with the ex1 prerequisite.

Also, on Mac OS-X using .PHONY all clean is not necessary for make to execute the commands in the Makefile, however, it is probably good precedent to set so that anyone reading the code later on realizes that all and clean are not actual target files.

Oh and a big thank you to Zed A. Shaw for making Learn the Hard Way free to read at his site Learn C the Hard Way.

Upvotes: 0

Tuxdude
Tuxdude

Reputation: 49473

  • If all is the first target in your makefile (I'm making a wild guess here since you've not showed the entire Makefile), make would choose that as the first target to build, when you do not pass an explicit target from the command line (i.e. mere make)

  • ex1 is a pre-requisite for all, so it builds it first and hence you see the following line:

    cc "-Wall" -g    ex1.c   -o ex1
    
  • After ex1 is built, make tries to execute the recipe for all, where it executes the following command:

    CFLAGS="-Wall" -g
    
  • Since -g by itself is not a valid command or application that can be executed in the shell, you get this error:

    /bin/sh: 1: -g: not found
    

Solution:

  • You've already defined CFLAGS in the beginning of the makefile, so no need to define it once again in the recipe. Even if you wish to override the variable CFLAGS, you should not be using it directly as part of the recipe.

  • Define all and clean as PHONY targets, if you've not already done so. The target all and clean do not create a file named all or clean after the recipe is executed, so it is a good practice to classify these targets as PHONY.

  • You don't need double quotes around -Wall

The following Makefile has all these corrections:

CFLAGS = -Wall -g

all: ex1

clean:
    rm -f ex1

.PHONY: all clean

Upvotes: 10

Related Questions