This is your simple make file for hello program.
CC = gcc
CFLAGS = -g
RM = rm -f
default: all
all: Hello
Hello: Hello.c
(CFLAGS) -o Hello Hello.c
clean veryclean:
$(RM) Hello
Suppose you have two makefiles in one directory named makefile.m1 and makefile.m2 and if you want build both make file then please use following commands
make -f makefile.m1
make -f makefile.m2
or use single Makefile that contains:
m1:
make -f makefile.m1
m2:
make -f makefile.m2
and use make m1 or make m2
Now lets clear your doubt about name of make file must not require Makefile
You can name makefile whatever you want. suppose i would like to give name myfirstmakefile.mk. To use it later you need to tell make what makefile you want. Use -f option for this:
make -f myfirstmakefile.mk
And again extantion .mk is also not manadatory you can use whatever you want but never forgot to use -f option.
so may this help make sense to you.
Answer from Jayesh Bhoi on Stack Overflowunix - How to write a Makefile to compile a simple C program - Stack Overflow
Creating A Basic Make File for Compiling C Code
A good makefiles for dummies tutorial. Is there any?
Makefiles Tutorial
Videos
(This post is about building C-projects, which is an important part of coding in C. I hope that counts as "on topic" :^) )
When I started coding small C and C++ programs in my free time, I either created imperfect makefiles by blindly copying Stackoverflow answers, or replaced make with other programs such as CMake because I thought make was inadequate.
Now I know a little about make, and find that it is perfectly adequate for small hobby projects, and probably for large ones as well, though I couldn't speak from experience there.
What should the makefile do?
-
Compile each translation unit if, and only if, it changed or one of the user-defined header files it depends on did
-
Combine the translation units' object files into an executable, linking with libraries if necessary
-
Distinguish between compiling 'debug' executables, including debug symbols and assertions, and 'release' executables, without those, which are optimized
-
Install the executable
Our example
We are looking at a simple program which has two different source files and headers:
main.c:
#include "message.h"
int main(void)
{
message();
return 0;
}message.c:
#include <stdio.h>
#include "message.h"
#include "answer.h"
void message(void)
{
printf("%s %d\n", MSG, ANSWER);
}message.h:
#define MSG "The answer is" void message(void);
answer.h:
#define ANSWER 42
Building object files
First we tell make what compiler to use and how:
CC=gcc CFLAGS=-MMD -Wall -Wextra -pedantic -std=c11
Then we make a list of all source files and object files we are looking at:
SRC=$(wildcard src/*.c) OBJ=$(SRC:%.c=%.o)
The first line grabs all files in the folder src that end in .c, and the second makes another list by copying the first and replacing the final .c with .o.
Then we make the rule to compile any given object file:
%.o: %.c $(CC) $(CFLAGS) -c -o $@ $<
Source file dependencies
I used to think setting up make so that it would compile a translation unit when one of the included header files changed was too complicated a thing to do, which led me to use CMake for a lot of projects. Turns out, after doing some more research, it is actually incredibly easy.
This ignorance of mine led me to use CMake, which is a turing-complete programming language disguised as a build system, to build programs with six or seven .c-files---effectively aiming a Tsar Bomba at a farm in Missouri. FYI, cloc tells me that CMake (version 3.31.0-rc3) has 291081 lines of code, while GNU make (version 4.4) has 27947. Keep in mind that CMake, after all those lines of code, doesn't even build the project but spits out a makefile itself, which does it.
(That is not to say that you are wrong for using CMake, or that it is not better for large programs. This is about using a small tool for a small task.)
It turns out that the C-compiler can generate a make-compatible list of dependencies for a C-file. That is a program we are already using, and it can do that as a side task while compiling the object file, so we might as well have it do that.
Looking at src/main.c, running the the compiler as follows…
$ gcc -MMD -c -o src/main.o src/main.c
…does not only give me the object file, but also a file called src/main.d, which looks like this:
$ cat src/main.d src/main.o: src/main.c src/message.h
If you have worked with makefiles before, you'll recognize that is exactly what we'd put into it if we were giving it the dependencies by hand.
Let's first grab a list of all those .d files:
DEP=$(OBJ:%.o=%.d)
Now, before we tell the makefile how to build the object files, we'll tell it to -include $(DEP). include works the same as it does in the C-preprocessor: it treats the content of the given file(s) as if they were typed into the makefile. Prepending a minus to include tells make not to complain if the file(s) do not exist, which would be the case when we are first compiling our project.
Now, after adding a compiler flag, and adding two further lines, our object files are compiled whenever one of their dependencies changes.
(That we get the .d files only after we have compiled the translation unit is fine, because if we change the source file, we need to recompile it that time anyway. If we later change one of the headers, we have the .d file ready.)
Compiling the executable
We add to our makefile's header:
EXE=msg LIBS=$(addprefix -l,)
If we did need libraries, we would say something like:
LIBS=$(addprefix -l,m pthread)
Then we tell make how to compile msg:
$(EXE): $(OBJ) $(CC) -o $@ $^ $(LIBS)
($^, as opposed to $<, expands to all dependencies instead of just the first.)
Other targets
We are done with step one and two, but we still need to distinguish between debug and release builds, and install the executable.
debug: CFLAGS += -g debug: $(EXE)
The first line says that, if we want to make the target debug, CFLAGS is expanded by the -g flag.
Similarly:
release: CFLAGS += -O3 -DNDEBUG release: $(EXE)
Since make defaults to the first target, we could either put debug at the top or use the usual default target, all:
all: debug
(Cleaning up)
Sometimes, for example after changing the makefile itself, you want to rebuild the project even though none of the source files have changed. For that we would first introduce a target to get rid of the old output files:
clean: rm -f $(OBJ) $(DEP) $(EXE)
Which we can then use to build again from scratch:
remake: clean debug .NOTPARALLEL: remake
Adding remake to the .NOTPARALLEL pseudo-target tells make not to do clean and debug simultaneously, if something like -j4 was passed. We obviously don't want to start building and then have files deleted.
Since we would usually want to switch to release after having tested the debug build, we can also use clean there:
release: CFLAGS += -O3 -DNDEBUG release: clean $(EXE) .NOTPARALLEL: release
Installing
I simply use:
TARGET=/usr/local install: all cp $(EXE) $(TARGET)/bin
You could also make it depend on release but that would rebuild an executable you probably just built. This way the usual paradigm of…
$ make release $ sudo make install
…is followed, but that is simply a matter of preference.
Conclusion
The final makefile looks like this:
CC=gcc CFLAGS=-MMD -Wall -Wextra -pedantic -std=c11 SRC=$(wildcard src/*.c) OBJ=$(SRC:%.c=%.o) DEP=$(OBJ:%.o=%.d) EXE=msg LIBS=$(addprefix -l,) TARGET=/usr/local all: debug debug: CFLAGS += -g debug: $(EXE) remake: clean debug .NOTPARALLEL: remake release: CFLAGS += -O3 -DNDEBUG release: clean $(EXE) .NOTPARALLEL: release clean: rm -f $(OBJ) $(DEP) $(EXE) install: all cp $(EXE) $(TARGET)/bin $(EXE): $(OBJ) $(CC) -o $@ $^ $(LIBS) -include $(DEP) %.o: %.c $(CC) $(CFLAGS) -c -o $@ $<
It can be used like this:
$ make gcc -MMD -Wall -Wextra -pedantic -std=c11 -g -c -o src/main.o src/main.c gcc -MMD -Wall -Wextra -pedantic -std=c11 -g -c -o src/message.o src/message.c gcc -o msg src/main.o src/message.o $ touch src/answer.h $ make gcc -MMD -Wall -Wextra -pedantic -std=c11 -g -c -o src/message.o src/message.c gcc -o msg src/main.o src/message.o $ ./msg The answer is 42
So we solved not only building C-projects but also 'calculated' the Answer to the Ultimate Question of Life, the Universe, and Everything. If you happen to write a program to calculate the Ultimate Question, though, I'm afraid you'd need CMake.
This is your simple make file for hello program.
CC = gcc
CFLAGS = -g
RM = rm -f
default: all
all: Hello
Hello: Hello.c
(CFLAGS) -o Hello Hello.c
clean veryclean:
$(RM) Hello
Suppose you have two makefiles in one directory named makefile.m1 and makefile.m2 and if you want build both make file then please use following commands
make -f makefile.m1
make -f makefile.m2
or use single Makefile that contains:
m1:
make -f makefile.m1
m2:
make -f makefile.m2
and use make m1 or make m2
Now lets clear your doubt about name of make file must not require Makefile
You can name makefile whatever you want. suppose i would like to give name myfirstmakefile.mk. To use it later you need to tell make what makefile you want. Use -f option for this:
make -f myfirstmakefile.mk
And again extantion .mk is also not manadatory you can use whatever you want but never forgot to use -f option.
so may this help make sense to you.
A makefile is a recipe for the make utility how to create some file (called a target) from some other files (called dependencies) using a set of commands run by the shell. A makefile typically looks like this:
target: dependency [...]
command1
command2
Try running man make for details.
Now for your task, really there is no need for a Makefile, since make has built-in rules that know how to compile a simple program. All you need to do is place your C source in a file named after the executable name (Hello) and with a .c extension, i.e. Hello.c.
Then a simple
$ make Hello
cc Hello.c -o Hello
does everything. If you want to use gcc instead of cc, you can run
$ rm Hello
$ make CC=gcc Hello
gcc Hello.c -o Hello
If you tell your instructor/teacher/prof that an empty makefile is all you need since you know the built-in rules do the right thing, you'll get some extra credit and maybe your instructor has learnt something new :-) If you are asked for a reference, you could quote the relevant parts of the make manual, or, do it like a pro, quote from the POSIX Standard for the make utility, section Default Rules.