Building binary with not default target 'all' in Makefile - c

I have simple Makefile below. That runs clear when using default target all.
objects = foo.o bar.o all.o
all: $(objects)
all2: $(objects)
# These files compile via implicit rules
foo.o: foo.c
bar.o: bar.c
all.o: all.c
all.c:
echo "int main() { return 0; }" > all.c
%.c:
touch $#
clean:
rm -f *.c *.o all2
But when I execute make all2 I got:
touch foo.c
cc -c -o foo.o foo.c
touch bar.c
cc -c -o bar.o bar.c
echo "int main() { return 0; }" > all.c
cc -c -o all.o all.c
touch all2.c
cc -c -o all2.o all2.c
cc all2.o foo.o bar.o all.o -o all2
rm all2.o all2.c
all2 target depends on foo.o bar.o all.o, but why it trying to get all2.c ?
Why it executes clean target at he end? Line rm all2.o all2.c

The reason is that make has a built-in rule that knows how to build a binary file from an object file that has the same prefix; that is, given a binary file foo make has a built-in rule that knows how to build it from foo.o.
You have a target all2 and normally that doesn't matter because you don't have an all2.c and so make can't find a way to build all2.o and so it decides there's no rule to build all2.
But in your makefile, you've created a rule to build any .c file, so when make tries to find a way to build all2.o it discovers it can be built from all2.c and there is a rule to build all2.c, so the rule matches.
Of course, you won't have a rule like %.c : ; touch $# in your non-test makefile so you won't see this problem in any real makefile.
If you want to make this work for your test environment you can, as #Cheatah says, declare the all2 rule to be phony which will prevent make from trying to look up any rules to build it.

Related

Makefile: Trying to understand sequence of execution

I have the following Makefile.
objects = foo.o bar.o all.o -- line 1
all: $(objects)
# These files compile via implicit rules
foo.o: foo.c
bar.o: bar.c
all.o: all.c
all.c:
echo "int main() { return 0; }" > all.c
%.c:
touch $#
clean:
rm -f *.c *.o all
When i run make, i get the below output.
echo "int main() { return 0; }" > all.c
cc -c -o all.o all.c
touch foo.c
cc -c -o foo.o foo.c
touch bar.c
cc -c -o bar.o bar.c
cc all.o foo.o bar.o -o all
Question:
Line 1 of the Makefile shows foo.o is the first dependency. So why all.o which depends on all.c are executed first?
You are confusing things by having the file all.c (and object file all.o) and the target all. Conventionally, the all target is a pseudo-target (.PHONY in GNU Make) for 'all the things that are (normally) built by this makefile. This isn't enforced — it is merely convention.
However, here, make is trying to use all.c to build a program all. And it knows it can build all by compiling all.c, so it generates that first.
You could clarify things by either using any.c instead of all.c and building any.o and program any, and having the all: target read:
all: any
That would build the program any

rule to call another Makefile from inside a Makefile

I have a Makefile from which I run the command of another Makefile if some objects file do not exist already.
The rule is the following:
$(OBJDIRCOMMON)/%.o: $(COMMONDIR)/%.c $(COMMONDIR)/Makefile | $(OBJDIRCOMMON)
+$(MAKE) -C $(COMMONDIR)
where the variables are defined as follows in the same Makefile:
COMMONDIR := ../common
SOURCESCOMMON := $(wildcard $(COMMONDIR)/*.c)
OBJDIRCOMMON := $(COMMONDIR)/obj
OBJECTSCOMMON := $(patsubst $(COMMONDIR)/%.c,$(OBJDIRCOMMON)/%.o, $(SOURCESCOMMON))
DEPENDSCOMMON := $(patsubst $(COMMONDIR)/%.c,$(OBJDIRCOMMON)/%.d, $(SOURCESCOMMON))
This rule works fine but at the end of the day the only real input required by the rule is the other Makefile so I tried:
$(OBJDIRCOMMON)/%.o: $(COMMONDIR)/Makefile | $(OBJDIRCOMMON)
+$(MAKE) -C $(COMMONDIR)
but this does not work, why is that?
For completeness here is the complete Makefile
CC = gcc
INC_PATH = -I../common/
SOURCEDIR := ./
SOURCES := $(wildcard $(SOURCEDIR)/*.c)
OBJDIR :=./obj
OBJECTS := $(patsubst $(SOURCEDIR)/%.c,$(OBJDIR)/%.o, $(SOURCES))
DEPENDS := $(patsubst $(SOURCEDIR)/%.c,$(OBJDIR)/%.d, $(SOURCES))
COMMONDIR := ../common
SOURCESCOMMON := $(wildcard $(COMMONDIR)/*.c)
OBJDIRCOMMON := $(COMMONDIR)/obj
OBJECTSCOMMON := $(patsubst $(COMMONDIR)/%.c,$(OBJDIRCOMMON)/%.o, $(SOURCESCOMMON))
DEPENDSCOMMON := $(patsubst $(COMMONDIR)/%.c,$(OBJDIRCOMMON)/%.d, $(SOURCESCOMMON))
# ADD MORE WARNINGS!
WARNING := -Wall -Wextra
# OBJS_LOC is in current working directory,
EXECUTABLE := ../server
# .PHONY means these rules get executed even if
# files of those names exist.
.PHONY: all clean
# The first rule is the default, ie. "make",
# "make all" and "make parking" mean the same
all: $(EXECUTABLE)
clean:
$(RM) $(OBJECTS) $(DEPENDS) $(EXECUTABLE)
# Linking the executable from the object files
# $^ # "src.c src.h" (all prerequisites)
$(EXECUTABLE): $(OBJECTS) $(OBJECTSCOMMON)
$(CC) $(WARNING) $^ -o $#
-include $(DEPENDS) $(DEPENDSCOMMON)
$(OBJDIR):
mkdir -p $(OBJDIR)
$(OBJDIR)/%.o: $(SOURCEDIR)/%.c Makefile | $(OBJDIR)
$(CC) $(WARNING) -MMD -MP -c $(INC_PATH) $< -o $#
$(OBJDIRCOMMON):
mkdir -p $(OBJDIRCOMMON)
$(OBJDIRCOMMON)/%.o: $(COMMONDIR)/%.c $(COMMONDIR)/Makefile | $(OBJDIRCOMMON)
+$(MAKE) -C $(COMMONDIR)
EDIT
The error I get is like this:
Entering directory '/home/user/Documents/UnixSystem/network/common'
gcc -Wall -Wextra -MMD -MP -c utilities.c -o obj/utilities.o
gcc -Wall -Wextra -MMD -MP -c error.c -o obj/error.o
make[2]: Leaving directory '/home/user/Documents/UnixSystem/network/common'
gcc ../common/obj/error.d.o -o ../common/obj/error.d
gcc: error: ../common/obj/error.d.o: No such file or directory
gcc: fatal error: no input files
compilation terminated.
From which I understand the execution of the other Makefile was successful. However after that it is trying to execute this command gcc ../common/obj/error.d.o -o ../common/obj/error.d which is wrong but I do not know which rule and why it's generating it.
Why what you did was wrong
Recipe A:
$(OBJDIRCOMMON)/%.o: $(COMMONDIR)/%.c $(COMMONDIR)/Makefile | $(OBJDIRCOMMON)
+$(MAKE) -C $(COMMONDIR)
and recipe B:
$(OBJDIRCOMMON)/%.o: $(COMMONDIR)/Makefile | $(OBJDIRCOMMON)
+$(MAKE) -C $(COMMONDIR)
have essentially different meanings and will certainly not yield the same behaviour.
Recipe A says:
Any target $(OBJDIRCOMMON)/file.o must be made up-to-date if does not exist
or is older than either $(COMMONDIR)/file.c or $(COMMONDIR)/Makefile.
If a target $(OBJDIRCOMMON)/file.o must be made up-to-date, then $(OBJDIRCOMMON)
must be made up-to-date first.
To make a target $(OBJDIRCOMMON)/file.o up-to-date, run the expansion of $(MAKE) -C $(COMMONDIR) in a shell.
Recipe B says:
Any target $(OBJDIRCOMMON)/file.o must be made up-to-date if does not exist
or is older than $(COMMONDIR)/Makefile.
If a target $(OBJDIRCOMMON)/file.o must be made up-to-date, then $(OBJDIRCOMMON)
must be made up-to-date first.
To make a target $(OBJDIRCOMMON)/file.o up-to-date, execute the expansion of $(MAKE) -C $(COMMONDIR) in a shell.
Notice that criterion A.1 is different from criterion B.1. Recipe A will execute
if $(OBJDIRCOMMON)/file.o is older than $(OBJDIRCOMMON)/file.c. Recipe B will not.
Recipe B discards the dependency of the object files on the corresponding source files,
and tells Make that $(OBJDIRCOMMON)/file.o is only ever to be remade if it
is older than $(COMMONDIR)/Makefile.
at the end of the day the only real input required by the rule is the other Makefile
What you mean by "the rule" here is actually the commandline (expanded from) $(MAKE) -C $(COMMONDIR).
The inputs of this command are one thing; the criteria for executing it are another.
How what you did caused the error you see.
This is thornier. Let's reproduce it.
Here's a playpen:
$ ls -R
.:
app common
./app:
foo.c main.c Makefile
./common:
bar.c Makefile
Here, ./app/Makefile is exactly your Makefile with recipe A. ./common/Makefile,
which you didn't post, is just:
obj/bar.o: bar.c
gcc -MMD -MP -c -I. $< -o $#
because that will do for illustration.
We build in ./app:
$ cd app
$ make
mkdir -p ./obj
gcc -Wall -Wextra -MMD -MP -c -I../common/ foo.c -o obj/foo.o
gcc -Wall -Wextra -MMD -MP -c -I../common/ main.c -o obj/main.o
mkdir -p ../common/obj
make -C ../common
make[1]: Entering directory '/home/imk/develop/so/make_prob/common'
gcc -MMD -MP -c -I. bar.c -o obj/bar.o
make[1]: Leaving directory '/home/imk/develop/so/make_prob/common'
gcc -Wall -Wextra obj/foo.o obj/main.o ../common/obj/bar.o -o ../server
which is fine.
Now I change ./app/Makefile as you did, to use recipe B, and rebuild.
$ make
gcc -Wall -Wextra -MMD -MP -c -I../common/ foo.c -o obj/foo.o
gcc -Wall -Wextra -MMD -MP -c -I../common/ main.c -o obj/main.o
gcc -Wall -Wextra obj/foo.o obj/main.o ../common/obj/bar.o -o ../server
Still fine... But wait a minute! That one didn't invoke the ./common make
at all, which is the one that the change might affect. Better clean:
$ make clean
rm -f ./obj/foo.o ./obj/main.o ./obj/foo.d ./obj/main.d ../server
and try again:
$ make
gcc -Wall -Wextra -MMD -MP -c -I../common/ foo.c -o obj/foo.o
gcc -Wall -Wextra -MMD -MP -c -I../common/ main.c -o obj/main.o
gcc -Wall -Wextra obj/foo.o obj/main.o ../common/obj/bar.o -o ../server
No difference? Ah, that's because this Makefile's clean fails to delete all
the files that make builds: it leaves out ../common/obj/bar.o. So I'll just:
$ rm ../common/obj/*
And have another go:
$ make
make -C ../common
make[1]: Entering directory '/home/imk/develop/so/make_prob/common'
gcc -MMD -MP -c -I. bar.c -o obj/bar.o
make[1]: Leaving directory '/home/imk/develop/so/make_prob/common'
gcc ../common/obj/bar.d.o -o ../common/obj/bar.d
gcc: error: ../common/obj/bar.d.o: No such file or directory
gcc: fatal error: no input files
compilation terminated.
which is your mystery.
When I zapped the ../common/obj files, I deleted not only all the object files therein
but also the dependency file ../common/obj/bar.d. And now Make is trying to remake it by running:
gcc ../common/obj/bar.d.o -o ../common/obj/bar.d
How come? To answer that, we'll first change ./app/Makefile back to use recipe A
- consider it done - and then do:
$ make --print-data-base > out.txt
which dumps in out.txt all the information that Make gleans from reading all
the makefiles (Makefile and all the makefiles that it recursively include-s,
in this case just the auto-generated .d files).
Let's see what the database has to say about ../common/obj/bar.d. It says:
# Not a target:
../common/obj/bar.d:
# Implicit rule search has been done.
# Last modified 2019-01-11 16:01:33.199263608
# File has been updated.
# Successfully updated.
Certainly we don't want ../common/obj/bar.d to be a target, and it isn't a
target because, having read all the makefiles, and considered all its builtin rules,
and all of the files it can actually find, Make can't see any way in which ../common/obj/bar.d
has to be made up-to-date with respect to any of those files. Good.
Now let's revert to recipe B in ./app/Makefile again - consider it done -
and again do:
$ make --print-data-base > out.txt
and again look in out.txt concerning ../common/obj/bar.d. This time we find:
../common/obj/bar.d: ../common/obj/bar.d.o
# Implicit rule search has been done.
# Implicit/static pattern stem: '../common/obj/bar.d'
# Last modified 2019-01-11 16:01:33.199263608
# File has been updated.
# Successfully updated.
# recipe to execute (built-in):
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $#
So this time ../common/obj/bar.d is a target! And it depends on ../common/obj/bar.d.o!
And the recipe to make it is:
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $#
which will expand, of course, to:
gcc ../common/obj/bar.d.o -o ../common/obj/bar.d
How was Make able to work that out, thanks to recipe B?
Well first it considered whether any of the rules in the makefiles or any of the
builtin rules gave it direct way to make ../common/obj/bar.d from any existing files,
and drew a blank.
Next it considered whether any of those rules gave it a way to
make ../common/obj/bar.d from an intermediate file. An intermediate file being a file that doesn't exist but itself can be made
from existing files, by any of the rules it has read or its builtin-rules. This
time it saw a way.
One of Make's builtin pattern rules is:
%: %.o
# recipe to execute (built-in):
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $#
You can find it in right there in out.txt. And you can see this is the pattern rule that
it matches with:
../common/obj/bar.d: ../common/obj/bar.d.o
The recipe there is a recipe to link a program called ../common/obj/bar.d given
an object file ../common/obj/bar.d.o.
There is no object file ../common/obj/bar.d.o, but can it be an intermediate file? If
Make can find a rule for making ../common/obj/bar.d.o from files that do exist,
then it can also make ../common/obj/bar.d with this %: %.o rule.
And it can find a recipe for making ../common/obj/bar.d.o from existing files
because we just gave it one! - recipe B:
$(OBJDIRCOMMON)/%.o: $(COMMONDIR)/Makefile | $(OBJDIRCOMMON)
+$(MAKE) -C $(COMMONDIR)
That tells Make that if any target matching $(OBJDIRCOMMON)/%.o (like ../common/obj/bar.d.o)
does not exist, but $(COMMONDIR)/Makefile does exist (which it does), then that target
is made up-to-date by running:
$(MAKE) -C $(COMMONDIR)
Make believed us. It ran $(MAKE) -C $(COMMONDIR):
make -C ../common
make[1]: Entering directory '/home/imk/develop/so/make_prob/common'
gcc -MMD -MP -c -I. bar.c -o obj/bar.o
make[1]: Leaving directory '/home/imk/develop/so/make_prob/common'
and then considered ../common/obj/bar.d.o up-to-date. So it moved on to:
../common/obj/bar.d: ../common/obj/bar.d.o
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $#
and ran:
gcc ../common/obj/bar.d.o -o ../common/obj/bar.d
which failed because we lied:
make -C ../common
does not make ../common/obj/bar.d.o at all.
gcc: error: ../common/obj/bar.d.o: No such file or directory
This does not arise with recipe A, because
$(OBJDIRCOMMON)/bar.d.o: $(OBJDIRCOMMON)/bar.d.c $(COMMONDIR)/Makefile | $(OBJDIRCOMMON)
+$(MAKE) -C $(COMMONDIR)
does not offer Make a way to make $(OBJDIRCOMMON)/bar.d.o from existing files,
because $(OBJDIRCOMMON)/bar.d.c does not exist. So ../common/obj/bar.d is not
a target.
Stick with recipe A, because it's right, and recipe B is wrong. Also review
and fix the makefiles so that make clean always deletes all the non-.PHONY targets that might have been built, and nothing else. Lastly avoid writing recipes with non-.PHONY targets where the recipe does not mention the target.
Should there be && instead of pipe
$(OBJDIRCOMMON)/%.o: $(COMMONDIR)/Makefile | (OBJDIRCOMMON)
+$(MAKE) -C $(COMMONDIR

When I use "gcc" in makefile, after making it, I got a "cc" output

For example:
There are 3 source files {main.c test1.c test2.c} in the directory
and a directory file named test3,
and there is a source file named test.c in the directory of test3.
Now I want to create a makefile to compile and link these four source files.
And this is my Makefile:
# Cancel statement "CC=gcc"
src:=$(wildcard *.c) test3.c
obj:=$(patsubst %.c,%.o,$(src))
main:$(obj)
gcc -o main $(obj)
.PHONY:clean
clean:
rm *.o *~
When I called make to compile them, I got a output like this:
cc -c -o main.o main.c
cc -c -o test1.o test1.c
cc -c -o test2.o test2.c
cc -c -o test3.o test3/test3.c
gcc -o main main.o test1.o test2.o test3.o
I know 'cc' is linked to 'gcc' in Linux.
What I don't understand is why did Make call cc to compile these four source files, but call gcc to link the object files?
You changed one rule: the one that links the program main from the object files. And when make did that link, you can see it used gcc.
You didn't do anything to change the built-in rules that make is using to compile the object files, so they use the default (the value of the variable CC) which is cc.
You wrote only the rule to link the object files, and allowed Make to use its default rule to decide how to build the object files from the source files.
GNU Make will expose its rules if you ask it with --print-data-base. In this case, it tells us
%.o: %.c
# recipe to execute (built-in):
$(COMPILE.c) $(OUTPUT_OPTION) $<
and
COMPILE.c = $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
and finally
CC = cc
This explains why Make uses cc to compile your C sources. To change that, simply set CC = gcc. Here's a complete Makefile which does that and also makes best use of Make's built-in rules, to help when you need to extend it:
src := $(wildcard *.c) test3.c
obj := $(patsubst %.c,%.o,$(src))
CC = gcc
main: $(obj)
$(LINK.c) -o $# $^ $(LDLIBS)
.PHONY: clean
clean:
$(RM) *.o *~

How can I write Makefile (with sub Makfile ) more concise

When I do practice , I have a practice path.
Under this path , I have an Include path named myInclude (I have some useful function is this folder and I always use it.)
And a code path named symbol_try.I always make add new folder (with a c file and main function in it) in symbol_try and compile it.
Each time I have to compile it by gcc in terminal .Its a boring work , so I write a Makefile.
Here is an example:
the main Makefile in practice path:
FOBJS=
include myInclude/Rule.mk
include symbol_try/codeList_13.1/Rule.mk
symbol:$(FOBJS) <==What exactly I what . A executable file.
gcc -o symbol $(FOBJS) -pthread -lpthread
subsystem:
cd myInclude/ && $(MAKE)
cd symbol_try/codeList_13.1/ &&$(MAKE)
clean:
rm -rf symbol
In the myInclude/Rule.mk
FOBJS+=myInclude/otherFunction.o myInclude/error.o \
myInclude/unit.o myInclude/unitTest.o\
In the symbol_try/codeList_13.1/Rule.mk
FOBJS+=symbol_try/codeList_13.1/codeList_13.1.o
In myInclude/Makefile:
OBJS=otherFunction.o error.o unit.o unitTest.o
ALL:$(OBJS)
.PHONY:ALL
$(OBJS):%.o:%.c
gcc -c $< -o $#
clean :
otherFunction.o error.o unit.o
In symbol_try/codeList_13.1/Makefile:
codeList_13.1.o:codeList_13.1.c
gcc -c codeList_13.1.c
Well.That can work. But as you see , I have to write a Rule.mk(to initialize the FOBJS) and a Makefile for each folder.
I am new for make , I want find a way more concise , witch I only need write one Makefile for each folder and a main Makefile.No Rule.mk any more.
PS: I always change the code in myInclude ,so I don't want to build it a library.
Thanks for any help.
Here's one way you can do it with just one Makefile:
CC = gcc
CPPFLAGS += -I myInclude/ (1)
CFLAGS += -std=c99 -Wall (2)
VPATH = myInclude/ \ (3)
symbol_try/codeList_13.1/
symbol: otherFunction.o error.o unit.o unitTest.o codeList_13.1.o (4)
$(CC) -o $# $^ (5)
.PHONY : clean
clean:
rm -f symbol *.o
Note that make knows how to build C files and has some standard macros: CC, CPPFLGAS, CFLAGS
Add the include paths of your headers. You presumably have some headers for the individual object files in the myInclude directory.
Put the compiler flags here.
Add the paths to the source files you want to build.
List the object files that the executable depends upon
As there is no file called symbol.c you need to tell make how to create symbol.o with a rule. $# means the target ('symbol', here), and $^ means all of the prerequisites (the object files listed).
Here's a list of all of the files in my test directories for this:
$ find . -type f
.
./Makefile
./myInclude/error.c
./myInclude/header.h
./myInclude/otherFunction.c
./myInclude/unit.c
./myInclude/unitTest.c
./symbol_try/codeList_13.1/codeList_13.1.c
And the build output:
$ make
gcc -std=c99 -Wall -I myInclude/ -c -o otherFunction.o myInclude/otherFunction.c
gcc -std=c99 -Wall -I myInclude/ -c -o error.o myInclude/error.c
gcc -std=c99 -Wall -I myInclude/ -c -o unit.o myInclude/unit.c
gcc -std=c99 -Wall -I myInclude/ -c -o unitTest.o myInclude/unitTest.c
gcc -std=c99 -Wall -I myInclude/ -c -o codeList_13.1.o symbol_try/codeList_13.1/codeList_13.1.c
gcc -o symbol otherFunction.o error.o unit.o unitTest.o codeList_13.1.o
Why don't you create a library from the objects in myInclude and do the linking in the Makefile in your code path (symbol_try/codeList_13.1). The latter is better anyway because the needed libraries (-pthread -lpthread in your case) might change as well for some other code.
The main Makefile now would have got nothing to do but call make in all needed subdirectories.
In each folder have a makefile with
SOURCES=sample.c sampletest.c
OBJECTS=$(SOURCES:%.c=$(OBJDIR)/%.o)
all: $(OBJECTS)
$(OBJDIR)/%.o: %.c
$(CC) $(CFLAGS) -o $# $<
In the root directory of a project, create a makefile with a rule to compile every sub-folder like the below.
Dirs= path-to-rootdir
objs:
set -e ; \
for i in $(Dirs) ; do \
$(MAKE) CC="$(CC)" CFLAGS="$(CFLAGS_MODULE)" LDFLAGS="$(LDFLAGS)" OBJDIR="$(OBJDIR)" -C $$i; \
done
And then you could use it build the executable by adding a rule
EXE: objs
$(CC) -L./Path1 $(LIB_PATH) -llib1 -o $(EXE_NAME) $(wildcard $(OBJDIR)/*.o)
Hope this helps!!!

Determining C executable name

When we are compiling a C program the output is stored in a.out. How can we redirect the compiled output to another file?
Most C compilers provide an option for this, such as the -o option for gcc and some others:
gcc -o gentext gentext.c
cc -o mainprog -Llib -lmymath firstbit.c secondbit.o
xlc -o coredump coredump.c
-ofilename will make filename instead of a.out.
According to the manual:
-o <file> Place the output into <file>
In Unix, where C originated from, C programs are usually compiled module-by-module, and then the compiled modules are linked into an executable. For a project that consists of modules foo.c and bar.c, the commands would be like this:
cc -c foo.c
cc -c bar.c
cc -o myprog foo.o bar.o
(With -c, the output filename becomes the source file with the suffix replaced with .o.)
This allows you to also re-compile only those modules that have changed, which can be a big time saver for big programs, but can also become pretty tricky. (This part is usually automated using make.)
For a single-module program there's not really any point in first compiling to a .o file, and then linking, so a single command suffices:
cc -o foo foo.c
For single-module programs, it is customary to call the resulting executable program the same as the C source file without the .c suffix. For multi-module programs, there is no hard custom on whether the output is named after the file with the main function or not, so you're free to invent whatever strikes your fancy.
With the -o option.
gcc main.c -o myCoolExecutable.o
This is ok if your program consists of a single file. If you have more files I suggest using make: create a Makefile and then run the command make.
A Makefile is a file containing some rules for compilation.
An example can be the following (# means the line is a comment):
CXX = gcc
#CXXFLAGS = -std=c++11
#INC_PATH = ...
#LIBS = ...
SOURCEDIR := yourSourceFolder
SOURCES := $(wildcard $(SOURCEDIR)/*.c)
OBJDIR=$(SOURCEDIR)/obj
OBJECTS := $(patsubst $(SOURCEDIR)/%.c,$(OBJDIR)/%.o, $(SOURCES))
DEPENDS := $(patsubst $(SOURCEDIR)/%.c,$(OBJDIR)/%.d, $(SOURCES))
# ADD MORE WARNINGS!
WARNING := -Wall -Wextra
# .PHONY means these rules get executed even if
# files of those names exist.
.PHONY: all clean
# The first rule is the default, ie. "make",
# "make all" and "make parking" mean the same
all: yourExecutableName
clean:
$(RM) $(OBJECTS) $(DEPENDS) yourExecutableName
# Linking the executable from the object files
# $^ # "src.c src.h" (all prerequisites)
yourExecutableName: $(OBJECTS)
$(CXX) $(WARNING) $^ -o $#
#$(CXX) $(WARNING) $(CXXFLAGS) $(INC_PATH) $^ -o $# $(LIBS)
-include $(DEPENDS)
$(OBJDIR):
mkdir -p $(OBJDIR)
$(OBJDIR)/%.o: $(SOURCEDIR)/%.c Makefile | $(OBJDIR)
$(CXX) $(WARNING) -MMD -MP -c $< -o $#
Shortly CXX variable defines your compiler (gcc, g++), with CXXFLAGS you can define flags for your compilation (i.e. -std=c++11). Then you can include and define custom (INC_PATH and LIBS: not set in the example). With SOURCEDIR you can specify your source code directory (where *.c files are).Then SOURCES is basically telling that the source files for the compilation are all the files having extension *.c.
The Makefile contains a set of rules whose structure is the following:
output: inputs
commandToExecute
The rule to generate your executable file is
yourExecutableName: $(OBJECTS)
$(CXX) $(WARNING) $^ -o $#
which is equivalent to gcc -Wall -Wextra $(OBJECTS) -o yourExecutableName.
$(OBJECTS) are the object file resulting from the compilation. When the above rule is executed, if they are not found make will continue scanning the file to find a rule to generate them. In this case the rule to generate these files is:
$(OBJDIR)/%.o: $(SOURCEDIR)/%.c Makefile | $(OBJDIR)
$(CXX) $(WARNING) -MMD -MP -c $< -o $#
If further information is needed let me know.
If foo will be your executable and bar.c is your source file then the command is:
gcc -o foo bar.c
Compile using:
cc -o <opfilename> <filename.c>
Execute using:
./<opfilename>
gcc filename.c -o outputfile
This command will directly create an outputfile.exe OR outputfile.out according to operating system. In place of filename.c OR outputfile we can enter path, as shown below.
gcc ./home/user/filename.c -o ./home/outputfile
The format of giving the Name of .exe file according to the User Choice in C Language
step 1 :- Run the gcc (or the compiler you have) in the below format on the Terminal
gcc -o put_your_name_you_want_to_give (space) your_file_name_you_want_to_execute
NB:- If you are Running "Vs Code" Use the 'Tab' key for the Auto completion.
step 2 :- Write down the name of the program in format
.\the_name_you_have_given.exe
you are done!
Assuming you are in ubuntu
step-1: run gcc with these commands to compile filename.c
gcc filename.c -o filename.out
filename.out will be created, (it might or might not be shown where the other files are stored)
step-2: execute the filename.out by
./filename.out
step-3: wait for the output
thats it , you are done

Resources