GNU Makefile, c programming - c

my current makefile looks likes this
all: hello
hello: hello.o
clang -o hello hello.o
hello.o: hello.c
clang -Wall -std=c99 -c -o hello.o hello.c -lpthread
clean:
rm -f *.o *exe hello
How can I modify it to compile with the following:
clang -std=gnu99 -Wall -o hello hello.c -lpthread

Use
hello: hello.c
clang -std=gnu99 -Wall -o hello hello.c -lpthread
instead of the two rules you have for hello and hello.o now.
When your program gets bigger, however, the separation of compilation to object files and linking may at some point be faster than compiling and linking everything in one go. With separated compilation and linking compilation units that are unmodified do not need to be recompiled every time.

Try this - usually best to do the compiling is a few steps.
all: hello
hello: hello.o
clang -o hello hello.o -lpthread
hello.o: hello.c
clang -Wall -std=c99 -c -o hello.o hello.c
clean:
rm -f *.o hello

Your modification requires just changing a single line; but instead, you should use some variables to make it cleaner:
# C compiler
CC = clang
# Additional libraries
LIBS = -lpthread
# Compiler flags
CCFLAGS = -std=gnu99 -Wall $(LIBS)
# Output executable
OUT = hello
all: hello
hello: hello.o
$(CC) $(CCFLAGS) -o $(OUT) hello.o
hello.o: hello.c
clang $(CCFLAGS) -c -o hello.o hello.c
clean:
rm -f *.o $(OUT)

Related

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).

Writing a Makefile to generate the modified, assembly, relocatable and executable file from a C program

I'm using CentOS to write a Makefile to generate these files from a C program:
hello.i (Modified source program, text)
hello.s (Assembly program, text)
hello.o (Relocatable object program, binary)
hello (Executable object program, binary)
The idea is to open each file to see its content.
C program (called hello.c)
#include <stdio.h>
int main() {
printf("Hello, World!");
return 0;
}
Makefile
all: hello
hello:
gcc -I hello.c -o hello.i
hello.o:
gcc -c hello.c -o hello.o
hello.s:
gcc -S hello.i -o hello.s
hello.i:
gcc ???
clean:
rm -rf *.o hello
Also, a clean command to delete all.
Error that I receive when I do: make all
compilation terminated. make: *** [hello] Error 4
I know that there is a single command to generate all at once, but, I want to do it by steps. This is my first Makefile that I try to do and I'm not 100% familiar yet.
What I'm doing wrong, maybe a wrong flag?
My goal is to generate all the files mentioned above to open them and see their content.
Without the hello.i, which is for me unclear what is should be, your make file should look like that:
all: hello hello.s
hello: hello.c hello.o
gcc hello.o -o hello
hello.o: hello.c
gcc -c hello.c -o hello.o
hello.s: hello.c
gcc -S hello.c -o hello.s
clean:
rm -rf *.o
You issue is that in Makefile, after the semicolon you should indicate the dependencies (the files the current output will need to be produced).
In you case, all declares that helloand hello.s are required. Then make looks to produce them using the given commands. Hello declares that hello.o is required, so it also look to the given command to produce it.
hello.o and hello.o declare that hello.c is required, so make will check if it finds the file and in yes it will run the gcc command. Now that hello.o is produced, it will go back to produce hello.
The commands should be indented with proper tabs, so if you copy paste check that you have tabs and no multiple spaces.
Well, you did not declare a recipe for hello.i, and you did not declare the appropriate dependencies for the other recipes. Additionally, the command line option to create hello.i is -E, not -I.
Let's see:
hello needs the file hello.o
hello.i needs the file hello.c
hello.o needs the file hello.c
hello.s needs the file hello.i
This would be the correct makefile:
all: hello
hello: hello.o
gcc hello.o -o hello
hello.i: hello.c
gcc -E hello.c -o hello.i
hello.o: hello.c
gcc -c hello.c -o hello.o
hello.s: hello.i
gcc -S hello.i -o hello.s
clean:
rm -rf *.o hello
Additionally, taking advantage of Make special variables, you can use $# to indicate the current recipe, and $< to indicate the first dependency, making it less verbose, like this:
all: hello
hello: hello.o
gcc $< -o $#
hello.i: hello.c
gcc -E $< -o $#
hello.o: hello.c
gcc -c $< -o $#
hello.s: hello.i
gcc -S $< -o $#
clean:
rm -rf *.o hello

What is the correct or efficient form to write a Makefile when you need two executables that use the same library?

I'm trying to write a Makefile to compile two programs that include the same .h (also mine), but with my actual Makefile if I type "make" in command line twice in a row, I don't get "bla bla is up to date", it recompile part of the stuff when it's not necessary. Any way to do this in a more efficient form?
Context
producer.c and consumer.c #include random_numbers.h in order to generate random numbers to its functions.
My Makefile
CC = gcc
FLAGS = -Wall -g
LIBS = -lrt -lpthread
HEADER_FILES_DIR = .
INCLUDES = -I $(HEADER_FILES_DIR)
SRCS = e1_producer.c e1_consumer.c $(HEADER_FILES_DIR)/random_num.c
OBJ = $(SRC:.c=.co)
DEPS = $(HEADER_FILES_DIR)/random_num.h
all: e1_producer e1_consumer
random_num.o: random_num.c random_num.h
$(CC) $(FLAGS) -c random_num.c
e1_producer: e1_producer.o random_num.o
$(CC) $(FLAGS) -o producer e1_producer.o random_num.o $(LIBS)
e1_producer.o: e1_producer.c
$(CC) $(FLAGS) -c e1_producer.c $(LIBS)
e1_consumer: e1_consumer.o random_num.o
$(CC) $(FLAGS) -o consumer e1_consumer.o random_num.o $(LIBS)
e1_consumer.o: e1_consumer.c
$(CC) $(FLAGS) -c e1_consumer.c $(LIBS)
clean:
rm producer consumer *.o
Output after two consecutive "make" in the command line
$ make
$ gcc -Wall -g -c e1_producer.c -lrt -lpthread
$ gcc -Wall -g -c random_num.c
$ gcc -Wall -g -o producer e1_producer.o random_num.o -lrt -lpthread
$ gcc -Wall -g -c e1_consumer.c -lrt -lpthread
$ gcc -Wall -g -o consumer e1_consumer.o random_num.o -lrt -lpthread
$ make
gcc -Wall -g -o producer e1_producer.o random_num.o -lrt -lpthread
gcc -Wall -g -o consumer e1_consumer.o random_num.o -lrt -lpthread
Why is this happening? When I do the same with another single program the second $ make returns me "nothing to do, bla bla is up to date"

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

How to clean object files without using command 'make clean' when compiling with makefile?

What I want to know is how to write a makefile that compiles a program and then removes the object files created in the process with just using command 'make' so I don't have to run command 'make clean' afterwards. Here's my current makefile:
prog: prog.o prog_func.o
gcc prog.o prog_func.o -o prog -Wall -std=c99
prog.o: prog.c prog_func.h
gcc prog.c -c -Wall -std=c99
prog_func.o: prog_func.c prog_func.h
gcc prog_func.c -c -Wall -std=c99
clean:
rm prog.o prog_func.o
EDIT:
And this is how it's done:
prog: prog.o prog_func.o
gcc prog.o prog_func.o -o prog -Wall -std=c99
rm prog.o prog_func.o
prog.o: prog.c prog_func.h
gcc prog.c -c -Wall -std=c99
prog_func.o: prog_func.c prog_func.h
gcc prog_func.c -c -Wall -std=c99
It works now. Thanks for quick responses.
After building executable, you just give the same command (rm command) after the executable command
How about compile without making f files like this
gcc -Wall -o prog prog.c
this command will not produce o files.
I have just taken a sample example.
makebuild: clean prog
prog:
gcc a.c -o a.o
clean:
rm a.o
Running 'make' from command line will first 'rm' a.o file and then run 'gcc a.c -o a.o'. The only problem here is that it will not work for first time as makebuild is calling clean first and it will throw an error as it will not find a.o file. You have to put check that 'rm' only when a.o file is present.
something like this:
clean:
if a.o exist
rm a.o

Resources