C, Refactoring Makefile - c

My makefile works however if I erase debutliste.o lecturefichier.o statistiques.o tri.o
from the target compile, it still works I imagine bc they are done in the other .o targets.
Make: link
compile: listechainee.o debutliste.o lecturefichier.o statistiques.o tri.o
listechainee.o: listechainee.c listechainee.h debutliste.o
gcc -g -Wall -Wextra -std=c11 -c listechainee.c
debutliste.o: debutliste.c debutliste.h lecturefichier.o
gcc -g -Wall -Wextra -std=c11 -c debutliste.c
lecturefichier.o: lecturefichier.c lecturefichier.h statistiques.o
gcc -g -Wall -Wextra -std=c11 -c lecturefichier.c
statistiques.o: statistiques.c statistiques.h tri.o
gcc -g -Wall -Wextra -std=c11 -c statistiques.c
tri.o: tri.c
gcc -g -Wall -Wextra -std=c11 -c tri.c
clean:
rm -rf *.o
link: compile
gcc *.o -o tri
If I understand correctly I should delete the debutliste.o lecturefichier.o statistiques.o tri.o that are inside the .o targets bc they will be executed as dependencies from the target compile and it should look like this?
Make: link
compile: listechainee.o debutliste.o lecturefichier.o statistiques.o tri.o
listechainee.o: listechainee.c listechainee.h
gcc -g -Wall -Wextra -std=c11 -c listechainee.c
debutliste.o: debutliste.c debutliste.h
gcc -g -Wall -Wextra -std=c11 -c debutliste.c
lecturefichier.o: lecturefichier.c lecturefichier.h
gcc -g -Wall -Wextra -std=c11 -c lecturefichier.c
statistiques.o: statistiques.c statistiques.h
gcc -g -Wall -Wextra -std=c11 -c statistiques.c
tri.o: tri.c
gcc -g -Wall -Wextra -std=c11 -c tri.c
clean:
rm -rf *.o
link: compile
gcc *.o -o tri

Yes. If you are using GNU Make, you can simplify your makefile (per above) by relying on the fact it already has a catalog of rules. Those rules tells make how to compile c files into object files and how to link object files into a binary. The recursive flag -r for rm makes me nervous so I removed it. You probably don't need a separate link step so I use the standard all target instead of compile:
.PHONY: all clean
CFLAGS:=-g -Wall -Wextra -std=c11
all: tri
clean:
rm -f *.o ./tri
tri: listechainee.o debutliste.o lecturefichier.o statistiques.o tri.o
debutliste.o: debutliste.c debutliste.h
lecturefichier.o: lecturefichier.c lecturefichier.h
listechainee.o: listechainee.c listechainee.h
statistiques.o: statistiques.c statistiques.h
If you want to be fancy you can use a pattern rule %.o: %.c %h that says a given file .o depends on it's corresponding .c and .h files which makes the makefile quite compact:
.PHONY: all clean
CFLAGS:=-g -Wall -Wextra -std=c11
all: tri
clean:
rm -f *.o ./tri
tri: listechainee.o debutliste.o lecturefichier.o statistiques.o tri.o
%.o: %.c %h
$(CC) $(CFLAGS) $(LDFLAGS) -o $# $<
The list of object files is probably just all your c files with a different name. You can write that as:
OBJECTS:=$(patsubst %.c,%.o,$(wildcard *.c))
tri: $(OBJECTS)
However, I don't usually do that step in my projects as the build now become sensitive to temporary .c files that I often create while working.

Related

Why is my makefile not making one of the targets?

I'm required to submit my program along with a makefile for an assignment but for some reason it is not making the target helper.o even though the command for that step (gcc -Wall -std=c99 -c helper.c) works when I type it into the command line manually. When I type the make command I get this error:
gcc -Wall -std=c99 -c createTweet.c
gcc -Wall -std=c99 -c displayTweets.c
gcc -Wall -std=c99 -c searchTweetsByKeyword.c
gcc -Wall -std=c99 -c countStopWords.c
gcc -Wall -std=c99 -c deleteTweet.c
gcc -Wall -std=c99 -c saveTweetsToFile.c
gcc -Wall -std=c99 -c loadTweetsFromFile.c
gcc -Wall -std=c99 -c sortID.c
gcc -Wall -std=c99 -c addNodeToList.c
cc -c -o mainA3.o mainA3.c
gcc -Wall -std=c99 createTweet.o displayTweets.o searchTweetsByKeyword.o countStopWords.o deleteTweet.o saveTweetsToFile.o loadTweetsFromFile.o sortID.o addNodeToList.o helper.o mainA3.o -o matiwosEyoelA3
gcc: error: helper.o: No such file or directory
make: *** [makefile:2: outputA3] Error 1 '''
Here: is my makefile:
outputA3: createTweet.o displayTweets.o searchTweetsByKeyword.o countStopWords.o deleteTweet.o saveTweetsToFile.o loadTweetsFromFile.o sortID.o addNodeToList.o mainA3.o
gcc -Wall -std=c99 createTweet.o displayTweets.o searchTweetsByKeyword.o countStopWords.o deleteTweet.o saveTweetsToFile.o loadTweetsFromFile.o sortID.o addNodeToList.o helper.o mainA3.o -o outputA3
helper.o: helper.h headerA3.h helper.c
gcc -Wall -std=c99 -c helper.c
createTweet.o: createTweet.c helper.h headerA3.h
gcc -Wall -std=c99 -c createTweet.c
displayTweets.o: displayTweets.c helper.h headerA3.h
gcc -Wall -std=c99 -c displayTweets.c
searchTweetsByKeyword.o: searchTweetsByKeyword.c helper.h headerA3.h
gcc -Wall -std=c99 -c searchTweetsByKeyword.c
countStopWords.o: countStopWords.c helper.h headerA3.h
gcc -Wall -std=c99 -c countStopWords.c
deleteTweet.o: deleteTweet.c helper.h headerA3.h
gcc -Wall -std=c99 -c deleteTweet.c
saveTweetsToFile.o: saveTweetsToFile.c helper.h headerA3.h
gcc -Wall -std=c99 -c saveTweetsToFile.c
loadTweetsFromFile.o: loadTweetsFromFile.c helper.h headerA3.h
gcc -Wall -std=c99 -c loadTweetsFromFile.c
sortID.o: sortID.c helper.h headerA3.h
gcc -Wall -std=c99 -c sortID.c
addNodeToList.o: addNodeToList.c helper.h headerA3.h
gcc -Wall -std=c99 -c addNodeToList.c
clean:
rm *.o outputA3
Why might this be happening?
Your matiwosEyoelA3: ... does not list helper.o as a dependency.
That's a problem because you repeat so many file names and violate the "don't write it twice" rule. Use variables and make's builtin variables like $^.
e.g.
OBJECTS = createTweet.o displayTweets.o searchTweetsByKeyword.o \
countStopWords.o deleteTweet.o saveTweetsToFile.o \
loadTweetsFromFile.o sortID.o addNodeToList.o \
mainA3.o helper.o
outputA3: $(OBJECTS)
gcc -Wall -std=c99 -o $# $^
Your target outputA3: does not depend on helper.o.
Change the first line to -
outputA3: createTweet.o displayTweets.o searchTweetsByKeyword.o countStopWords.o deleteTweet.o saveTweetsToFile.o loadTweetsFromFile.o sortID.o addNodeToList.o mainA3.o helper.o
gcc -Wall -std=c99 createTweet.o displayTweets.o searchTweetsByKeyword.o countStopWords.o deleteTweet.o saveTweetsToFile.o loadTweetsFromFile.o sortID.o addNodeToList.o helper.o mainA3.o -o outputA3
(notice the extra helper.o at the end)
One way to avoid such issues in the future is to use $^ to refer to all the dependencies instead of listing them.
So you can change the target to -
outputA3: createTweet.o displayTweets.o searchTweetsByKeyword.o countStopWords.o deleteTweet.o saveTweetsToFile.o loadTweetsFromFile.o sortID.o addNodeToList.o mainA3.o helper.o
gcc -Wall -std=c99 $^ -o $#
This way you don't have to write the dependencies again and if you miss something you get a linker error telling you which file is missing.
helper.o is not in the list of dependencies for outputA3 target, while it is in the linking list of requisites. This makes make not to compile it, but the linker blames at you because it is not found.
A good idea can be to create a make variable with the set of objects of outputA3, as in:
outputA3_objs = createTweet.o displayTweets.o searchTweetsByKeyword.o countStopWords.o deleteTweet.o saveTweetsToFile.o loadTweetsFromFile.o sortID.o addNodeToList.o helper.o mainA3.o
outputA3: $(outputA3_objs)
gcc -Wall -std=c99 $(outputA3_objs) -o $#
and this way, if you need to change the list, you have to do it in only one place, making your Makefile more robust to changes.
make is much more powerful than what you apparently think. Thanks to the other answers you fixed your Makefile. Here is a bit simpler and less error prone Makefile (for GNU make):
SRC := $(wildcard *.c)
OBJ := $(patsubst %.c,%.o,$(SRC))
CC := gcc
CFLAGS := -Wall -std=c99
outputA3: $(OBJ)
$(CC) $(CFLAGS) $^ -o $#
%.o: %.c helper.h headerA3.h
$(CC) $(CFLAGS) -c $< -o $#
.PHONY: clean
clean:
rm -f $(OBJ) outputA3
This assumes that the executable is outputA3 (as in your own Makefile) and not matiwosEyoelA3 (as in the error messages you show), and that all C files are part of the project. Adapt if needed.
Note: GNU make already knows how to compile and link. If you accept that your executable is named mainA3 instead of outputA3 or matiwosEyoelA3, the following should also work:
CC := gcc
CFLAGS := -Wall -std=c99
mainA3: $(patsubst %.c,%.o,$(wildcard *.c))
%.o: helper.h headerA3.h
.PHONY: clean
clean:
rm -f *.o mainA3

Why my Makefile works fine after deleting `%.o: %.c`?

I accidentally deleted the %.o: %.c section in my Makefile, but it still works fine; could somebody let me know WHY?
Here's my Makefile:
CC = gcc
CFLAGS = -std=gnu99 -pedantic -Wall -O3
SRCS = $(wildcard *.c)
OBJS = $(patsubst %.c,%.o,$(SRCS))
myProgram: $(OBJS)
$(CC) -o $# -O3 $^
.PHONY: clean
clean:
rm -f myProgram *.o *.c~ *.h~ *.swp
and here's the output of clean make:
$ make clean; make
rm -f myProgram *.o *.c~ *.h~ *.swp
gcc -std=gnu99 -pedantic -Wall -O3 -c -o anotherFile.o anotherFile.c
gcc -std=gnu99 -pedantic -Wall -O3 -c -o oneFile.o oneFile.c
gcc -o myProgram -O3 anotherFile.o oneFile.o

I've created a Makefile in c that should creates more than one executable, but it does not work

WHAT I NEED TO DO
I'm trying to create a Makefile in c that should create three executable from three different .c files.
I'll want to create Lez4Es1, Lez4Es1v2 and Lez4Es3 as my executable compiling and linking in two different stages.
Something as:
gcc -std=c99 -Wall -pedantic Lez4Es1.c -c
gcc -std=c99 -Wall -pedantic Lez4Es1.o -o Lez4Es1
gcc -std=c99 -Wall -pedantic Lez4Es1v2.c -c
gcc -std=c99 -Wall -pedantic Lez4Es1.v2 -o Lez4Es1v2
gcc -std=c99 -Wall -pedantic Lez4Es3.c -c
gcc -std=c99 -Wall -pedantic Lez4Es3.o -o Lez4Es3
MY SOLUTION
Assuming to have all .c files in the same directory i created this Makefile but it does not work:
CC = gcc
CFLAGS += -std=c99 -Wall -pedantic -g
TARGETS = Lez4Es1 \
Lez4Es1v2 \
Lez4Es3 \
.PHONY: all clean cleanall
% : %.o
$(CC) $(CFLAGS) $^ -o $#
%.o : %.c
$(CC) $(CFLAGS) -c $^
all : $(TARGETS)
clean :
-rm *.o *~ core
cleanall :
-rm *.o *.txt -f $(TARGETS) *~ core
PROBLEMS
When i run $ make it creates executable from .c file and not from .o, this is output of compiler:
$ make
gcc -std=c99 -Wall -pedantic -g Lez4Es1.c -o Lez4Es1
gcc -std=c99 -Wall -pedantic -g Lez4Es1v2.c -o Lez4Es1v2
gcc -std=c99 -Wall -pedantic -g Lez4Es3.c -o Lez4Es3
How to fix to let him do the things i want to do?
There is a method to give executable files a different name than .o files?
Sorry for my bad english and if i didn't explain it well i'm ready to edit it and give you more details, thank you.
Try deleting the built-in rule that creates executables from source files:
% : %.c
(a pattern rule with no recipe cancels that rule).

Make two c programs in one makefile

Is it possible to make two files in a single makefile? Essentially a program and a programtest. I have seen other answers, but their syntax went completely over my head. Right now my Makefile only makes one of the programs, and I cant figure out how to have it make both
Would it be possible for someone to provide a template for how a Makefile would be structured to compile two programs?
all: main test
test: objects/Math.o objects/Stack.o objects/Queue.o objects/myUnitTesting.o objects/test.o
gcc objects/test.o objects/Math.o objects/Stack.o objects/Queue.o objects/myUnitTesting -o test
main: objects/Stack.o objects/Queue.o objects/Math.o objects/Point.o objects/main.o
gcc objects/main.o objects/Stack.o objects/Queue.o objects/Point.o objects/Math.o -o main
objects/test.o: test.c
gcc -g -Wall -O -c -o objects/test.o test.c
objects/main.o: main.c
gcc -g -Wall -O -c -o objects/main.o main.c
objects/myUnitTesting.o: cs/myUnitTesting.c
gcc -g -Wall -O -c -o objects/myUnitTesting cs/myUnitTesting.c
objects/Math.o: cs/Math.c
gcc -g -Wall -O -c -o objects/Math.o cs/Math.c
objects/Stack.o: cs/Stack.c
gcc -g -Wall -O -c -o objects/Stack.o cs/Stack.c
objects/Queue.o: cs/Queue.c
gcc -g -Wall -O -c -o objects/Queue.o cs/Queue.c
objects/Point.o: cs/Point.c
gcc -g -Wall -O -c -o objects/Point.o cs/Point.c
clean:
rm -f objects/*o main
Then you only need to type:
make all
and it is going to compile your main.c and test.c files
You can multiple exes in one makefile, here is sample for building 2,
you need to do make all to build
prog1: prog1.o
gcc prog1.o -o prog1 2>>compile.log 1>&2
prog2: prog2.o
gcc prog2.o -o prog2 2>>compile.log 1>&2
all: prog1 prog2
.c.o:
gcc -o $# -c $*.c 2>>compile.log 1>&2
Here is a scenario where 2 targets are main1 and main2.
TARGET1 = main1
TARGET2 = main2
$(TARGET1): main1.o
gcc main1.o -o $#
$(TARGET2): main2.o
gcc main2.o -o $#
%.o: %.c
gcc -c $< -o $#
run1: $(TARGET1)
./$(TARGET1)
run2: $(TARGET2)
./$(TARGET2)
all: $(TARGET1) $(TARGET2)
./$(TARGET1)
./$(TARGET2)
Remember that the indentation is a <tab> character, not space characters.
The following command will compile and run main1 executable.
make run1
The following command will compile and run main2 executable.
make run2
The following command will compile and run main1 executable followed by main2 executable.
make all
It is possible.
Here is a simpler version of the Makefile:
all: program programtest
program:
gcc -o program program.c
programtest:
gcc -o programtest programtest.c
Then you just have to type make:
$ make
gcc -o program program.c
gcc -o programtest programtest.c

gcc builds with -o but not -o3?

My Makefile looks like this:
CC=gcc
CFLAGS=-Wall -Wextra -std=c99 -pedantic
OBJECTS=main.o Scene.o Matrix.o Vector.o Triangle.o Color.o Raster.o
render: $(OBJECTS)
$(CC) $(CFLAGS) -lm -o render -g $(OBJECTS)
rm $(OBJECTS)
clean:
rm -f render*
This builds my executable with no errors, but when I change -o to -o2 or -o3, I get the error:
gcc -Wall -Wextra -std=c99 -pedantic -c -o main.o main.c
gcc -Wall -Wextra -std=c99 -pedantic -c -o Scene.o Scene.c
gcc -Wall -Wextra -std=c99 -pedantic -c -o Matrix.o Matrix.c
gcc -Wall -Wextra -std=c99 -pedantic -c -o Vector.o Vector.c
gcc -Wall -Wextra -std=c99 -pedantic -c -o Triangle.o Triangle.c
gcc -Wall -Wextra -std=c99 -pedantic -c -o Color.o Color.c
gcc -Wall -Wextra -std=c99 -pedantic -c -o Raster.o Raster.c
gcc -Wall -Wextra -std=c99 -pedantic -lm -o3 render -g main.o Scene.o Matrix.o Vector.o Triangle.o Color.o Raster.o
gcc.exe: error: render: No such file or directory
make: *** [render] Error 1
There could be some error in my code detected by the optimization flags, but as I don't get any error messages before this it's hard to know what's going wrong. I'm using MinGW/MSYS on Windows 7.
-o render means create the output file with the name render.
Now you are changing this -o to -o3 which is incorrect. Instead you need to keep -o render as it is and add a -O3 flag for optimization. Note the capital letter O.
-o is the output file flag. You were thinking of -O (capital).

Resources