0

I'm trying to make a Makefile for my program. It is so difficult because i've read a lot of guide but none is clear. I have 3 files : main.c , library.c , library.h . Main.c and library.c depend on library.h . The structure of my directory project is formed by : MyProject directory -> Build directory and Exercise1 directory -> all of my files . In compiler I wrote make and it compiled ; then when I write make execute command, it gives me this error:

cd ../build; ./test
Error: No such file or directory
makefile:23: recipe for target 'execute' failed
make: *** [execute] Error 1

MAKEFILE

CC=gcc
CFLAGS=-Wall
ODIR=../build
DIR = build

.PHONY: all

all: main.o library.o test

$(ODIR)/%.o: %.c $(DEPS)
    $(CC) -std=c99 -c -o $@ $< $(CFLAGS)

library.o: library.c library.h
    $(CC) -std=c99 -c -o $(ODIR)/$@ $< $(CFLAGS)

main.o: main.c library.h
    $(CC) -std=c99 -c -o $(ODIR)/$@ $< $(CFLAGS)

test: $(ODIR)/library.o $(ODIR)/main.o
    $(CC) -std=c99 -o $(ODIR)/$@ $^ $(CFLAGS)

execute:
    cd $(ODIR); ./test

clean:
    rm -f $(ODIR)/*.o
Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
cocoricò
  • 51
  • 4

1 Answers1

0

These lines:

execute:
    cd $(ODIR); ./test

tell make that, when you give the command make execute, it should change the working directory to $(ODIR) and then execute ./test, which means to execute the file test in the current working directory. However, there is no file test in the $(ODIR) directory because you have not built it yet.

You can make that file by executing make test, but that is a bad way to do it. It is better to tell make that the execute target depends on $(ODIR)/test:

execute: $(ODIR)/test
    cd $(ODIR); ./test

Then we should change the rule for test to $(ODIR)/test:

$(ODIR)/test: $(ODIR)/library.o $(ODIR)/main.o
    $(CC) -std=c99 -o $(ODIR)/$@ $^ $(CFLAGS)

Next, delete the rule for all and the .PHONY rule. A rule for all should be used when a makefile can make several different final targets, like ProgramA, ProgramB, and ProgramC, and you want one target that makes all of them. It should not be used to make all of the intermediate object files for a target. The intermediate files should arise out of the rules for building a final target.

Then delete the rules for library.o and main.o. Those are names for files in the current directory, but you are building in $(ODIR). We will let the pattern rule for $(ODIR)/%.o build those.

But we need to fix the pattern rule. It uses DEPS, but that is not defined. Add a line above that says what all the object files depend on:

DEPS=library.h

Nothing in the makefile uses DIR, so delete the line DIR = build.

Finally, you might want to put the execute target first, so that it is the default. Then your makefile is:

CC=gcc
CFLAGS=-Wall
ODIR=../build
DEPS=library.h

execute: $(ODIR)/test
    cd $(ODIR); ./test

$(ODIR)/%.o: %.c $(DEPS)
    $(CC) -std=c99 -c -o $@ $< $(CFLAGS)

$(ODIR)/test: $(ODIR)/library.o $(ODIR)/main.o
    $(CC) -std=c99 -o $(ODIR)/$@ $^ $(CFLAGS)

clean:
    rm -f $(ODIR)/*.o

You might also change the command for clean to remove test:

    rm -f $(ODIR)/*.o $(ODIR)/test
Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
  • using your `code` it gives me the same error of before: `cd ../build; ./test Error: No such file or directory makefile:7: recipe for target 'execute' failed make: *** [execute] Error 1 ` – cocoricò Dec 12 '20 at 17:48
  • @cocoricò: Make the `../build` directory first. There are ways to incorporate that into the makefile, but they involve further complications. – Eric Postpischil Dec 12 '20 at 17:51
  • i've already created build directory. When I use make command , it inserts in build directory library.o main.o and test.exe but then it gives me that error. – cocoricò Dec 12 '20 at 17:55
  • my folders are: MyProject , in which there are 'build' directory and 'exercise1', in exercise1 there are all my files. – cocoricò Dec 12 '20 at 18:04