C Makefile for a source tree - c

Need help in writing a Makefile for below source tree.
I have tried out simple examples for Makefile and those worked fine. But not able to figure out how do I write a Makefile for below kind of source tree.
I am organizing my code as below
root_dir:
Makefile
component1:
dir1:
file1.c file1.h
dir2:
file2.c file2.h
dir3:
file3.c file3.h
component2:
dir4:
file4.c file4.h
dir5:
file5.c file5.h
common:
debug.c debug.h
utils.c utils.h
main.c main.h
Here, main.c uses some functions declared in debug.h, utils.h, file1.h and file4.h. These file1.c and file4.c use the debug.h and utils.h. I have started writing the Makefile rules as below.
CC=gcc
CFlags=-c -g3 -Wall
myexec: main.o
$(CC) main.o -o myexec
main.o: common/main.c common/main.h common/utils.h
$(CC) $(CFLAGS) common/main.c
This Makefile gives "undefined reference" error messages for the functions declared in utils.h. It can crib about the functions declared in debug.h, file1.h or file4.h, but shouldn't have given the error message for functions from utils.h
Please help me in finding out what is wrong with the Makefile here.

First let's fix the main.o rule:
main.o: common/main.c common/main.h common/utils.h
$(CC) $(CFLAGS) common/main.c
If, as you say main.c uses some functions declared in debug.h, utils.h, file1.h and file4.h, then those headers should be prerequisites of the rule (so that if you modify a header, Make will rebuild main.o):
main.o: common/main.c common/main.h common/debug.h common/utils.h component1/dir1/file1.h component2/dir4/file4.h
$(CC) $(CFLAGS) common/main.c
Now look at the myexec rule:
myexec: main.o
$(CC) main.o -o myexec
It's no surprise that you get "undefined reference" errors; the functions declared in debug.h, utils.h, file1.h and file4.h are defined in (I presume) debug.c, utils.c, file1.c and file4.c, which this makefile never mentions. Do not proceed until you understand this.
The way to handle this is tho have the myexec rule link all of the relevant object files:
myexec: main.o debug.o utils.o file1.o file4.o
$(CC) main.o debug.o utils.o file1.o file4.o -o myexec
Naturally you must have rules for debug.o, utils.o, file1.o and file4.o, similar to the one for main.o.
Once that is done, you have a makefile that works but is needlessly long and redundant. "Effective but crude". It can be made much shorter and more elegant, but this answer is getting long; just get it working, then we can work on making it cleaner.

here is a long example: it is for a linux embedded system, but will work with only minor changes for your application
These two makefiles will create an executable in each sub directory
it has a directory tree something like the following:
top
utility .h and .c files
makefile.top
makefile.bot
/executable1
exec1 .h and .c files
/executable2
exec2 .h and .c files
contents of makefile.mak
SHELL = /bin/sh
# note: this makefile.mak needs to be run from the ./src directory
# of the GOT4 directory tree
SRC := $(wildcard *.c)
OBJ := $(SRC:.c=.o)
DEP := $(SRC:.c=.d)
INC := $(SRC:.c=.h)
MAKE := /usr/bin/make
CC := /usr/bin/gcc
CP := cp
MV := mv
LDFLAGS := -L/usr/local/lib -L/usr/lib -L/lib
DEBUG := -ggdb3
CCFLAGS := $(DEBUG) -Wall -Wextra -pedantic
#CPPFLAGS += =MD
LIBS := -lssl -ldl -lrt -lz -lc -lm
.PHONY: AllDirectories
AllDirectories := \
executable1 \
executable2
.PHONY: all
all: $(OBJ) $(AllDirectories)
$(foreach d,$(AllDirectories), \
( cd $d && $(MAKE) -f ../makefile.bot name=Tsk_$d all ); )
#
# create dependancy files
#
%.d: %.c
#
# ========= START $< TO $# =========
$(CC) -M $(CPPFLAGS) $< > $#.$$$$; \
sed 's,\($*\)\.o[ :]*,\1.o $# : ,g' < $#.$$$$ > $#; \
rm -f $#.$$$$
# ========= END $< TO $# =========
#
# compile the .c file into .o files using the compiler flags
#
%.o: %.c %.d
#
# ========= START $< TO $# =========
$(CC) $(CCFLAGS) -c $< -o $# -I.
# ========= END $< TO $# =========
#
.PHONY: clean
#clean: $(AllDirectories)
# # ========== start clean activities ==========
# rm -f *.o
# rm -f $(name).map
# rm -f $(name)
# rm -f *.d
# $(foreach d,$(AllDirectories), \
# ( cd $d && $(MAKE) -f makefile.mak clean ); )
# # ========== end clean activities ==========
clean: $(AllDirectories)
# ========== start clean activities ==========
rm -f *.o
rm -f $(name).map
rm -f $(name)
rm -f *.d
rm -f ../bin/Tsk_*
$(foreach d,$(AllDirectories), \
( cd $d && $(MAKE) -f ../makefile.bot name=Tsk_$d clean ); )
# ========== end clean activities ==========
.PHONY: install
#install: $(AllDirectories)
# # ========== start install activities ==========
# $(foreach d,$(AllDirectories), \
# ( cd $d && $(MAKE) -f makefile.mak clean ); )
# # ========== end install activities ==========
install: $(AllDirectories)
# ========== start install activities ==========
$(foreach d,$(AllDirectories), \
( cd $d && $(MAKE) -f ../makefile.bot name=Tsk_$d install ); )
# ========== end install activities ==========
# include the contents of all the .d files
# note: the .d files contain:
# <filename>.o:<filename>.c plus all the dependancies for that file
# I.E. the #include'd header files
# wrap with ifneg... so will not rebuild *.d files when goal is 'clean'
#
ifneq "$(MAKECMDGOALS)" "clean"
-include $(DEP)
endif
and the makefile.bot
SHELL = /bin/sh
BINDIR := /home/user/bin
.PHONY: all
all : $(BINDIR)/$(name) ../makefile.mak ../makefile.bot
#
# macro of all *.c files
# (NOTE:
# (the following 'wildcard' will pick up ALL .c files
# (like FileHeader.c and FunctionHeader.c
# (which should not be part of the build
# (so be sure no unwanted .c files in directory
# (or change the extension
#
SRC := $(wildcard *.c)
OBJ := $(SRC:.c=.o)
DEP := $(SRC:.c=.d)
INC := $(SRC:.c=.h)
COMMON_OBJ := $(wildcard ../*.o)
#COMMON_SRC := $(wildcard ../*.c)
#COMMON_OBJ := $(COMMON_SRC:.c=.o)
#COMMON_DEP := $(COMMON_SRC:.c=.d)
#COMMON_INC := $(COMMON_SRC:.c=.h)
MAKE := /usr/bin/make
CC := /usr/bin/gcc
CP := cp
MV := mv
LDFLAGS := -L/usr/local/lib
DEBUG := -ggdb3
CCFLAGS := $(DEBUG) -Wall -Wextra -pedantic -std=c99
#CPPFLAGS += =MD
LIBS := -lssl -ldl -lrt -lz -lc -lm
#
# link the .o files into the executable
# using the linker flags
# -- explicit rule
#
$(name): $(OBJ) $(COMMON_OBJ) ../makefile.mak ../makefile.bot
#
# ======= $(name) Link Start =========
$(CC) $(LDFLAGS) -o $# $(OBJ) $(COMMON_OBJ) $(LIBS)
# ======= $(name) Link Done ==========
#
# note:
# using MV rather than CP results in all executables being re-made everytime
$(BINDIR)/$(name): $(name)
#
# ======= $(name) Copy Start =========
sudo $(CP) $(name) $(BINDIR)/.
# ======= $(name) Copy Done ==========
#
#
#create dependancy files -- inference rule
# list makefile.mak as dependancy so changing makfile forces rebuild
#
%.d: %.c
#
# ========= START $< TO $# =========
$(CC) -M $(CPPFLAGS) $< > $#.$$$$; \
sed 's,\($*\)\.o[ :]*,\1.o $# : ,g' < $#.$$$$ > $#; \
rm -f $#.$$$$
# ========= END $< TO $# =========
#
# compile the .c file into .o files using the compiler flags
# -- inference rule
#
%.o: %.c %.d
#
# ========= START $< TO $# =========
$(CC) $(CCFLAGS) -c $< -o $# -I.
# ========= END $< TO $# =========
#
.PHONY: clean
clean:
# ========== CLEANING UP ==========
rm -f *.o
rm -f $(name).map
rm -f $(name)
rm -f *.d
# ========== DONE ==========
.PHONY: install
install: all
# include the contents of all the .d files
# note: the .d files contain:
# <filename>.o:<filename>.c plus all the dependancies for that .c file
# I.E. the #include'd header files
# wrap with ifneg... so will not rebuild *.d files when goal is 'clean'
#
ifneq "$(MAKECMDGOALS)" "clean"
-include $(DEP)
endif

Related

How to fix error in function `_start': (.text+0x20): undefined reference to `main'

I am running Ubuntu 18.0.4 virtual machine using Vagrant and Virtualbox. I am writing a C program to manage virtual memory on said machine, which consists of many C and header files. Every time I run make while in my virtual machine, I get this error:
make[1]: Entering directory '/vagrant'
/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/Scrt1.o: In
function `_start':
(.text+0x20): undefined reference to `main'
collect2: error: ld returned 1 exit status
Makefile:45: recipe for target 'vm-sim' failed
make[1]: *** [vm-sim] Error 1
make[1]: Leaving directory '/vagrant'
Makefile:23: recipe for target 'all' failed
make: *** [all] Error 2
Here is my Makefile:
TARGET = vm-sim
CC = gcc
CFLAGS = -Wall -Wextra -Wsign-conversion -Wpointer-arith -Wcast-qual -
Wwrite-strings -Wshadow -Wmissing-prototypes -Wpedantic -Wwrite-strings -g -
std=gnu99 -lm
LFLAGS =
SRCDIR = *-src
INCDIR = $(SRCDIR)
BINDIR = .
SUBMIT_FILES = $(SRC) $(INC) Makefile
SUBMISSION_NAME = project3-vm
SRC := $(wildcard $(SRCDIR)/*.c)
INC := $(wildcard $(INCDIR)/*.h)
INCFLAGS := $(patsubst %/,-I%,$(dir $(wildcard $(INCDIR)/.)))
.PHONY: all
all:
#$(MAKE) release && \
echo "$$(tput setaf 3)$$(tput bold)Note:$$(tput sgr0) this project compiled
with release flags by default. To compile for debugging, please use $$(tput
setaf 6)$$(tput bold)make debug$$(tput sgr0)."
.PHONY: debug
debug: CFLAGS += -ggdb -g3 -DDEBUG
debug: $(BINDIR)/$(TARGET)
.PHONY: release
release: CFLAGS += -mtune=native -O2
release: $(BINDIR)/$(TARGET)
.PHONY: clean
clean:
#rm -f $(BINDIR)/$(TARGET)
#rm -rf $(BINDIR)/$(TARGET).dSYM
.PHONY: submit
submit:
#(tar zcfh $(SUBMISSION_NAME).tar.gz $(SUBMIT_FILES) && \
echo "Created submission archive $$(tput
bold)$(SUBMISSION_NAME).tar.gz$$(tput sgr0).")
$(BINDIR)/$(TARGET): $(SRC) $(INC)
#mkdir -p $(BINDIR)
#$(CC) $(CFLAGS) $(INCFLAGS) $(SRC) -o $# $(LFLAGS)
I only have one main() function defined, but previously defined a different one in another file; I think this may be the issue but don't know how to fix it.
the following makefile:
is not for your specific directory layout
shows a good (but not great) way to write the makefile
shows one method for creating dependency files (however, gcc can be used directly to produce those files
is written for a linux OS
this is a generic make file, where the when the make is invoked, needs the parameter: -D name=executablename
and now, the makefile:
SHELL = /bin/sh
BINDIR := /home/user/bin
.PHONY: all
all : $(BINDIR)/$(name)
SRC := $(wildcard *.c)
OBJ := $(SRC:.c=.o)
DEP := $(SRC:.c=.d)
INC := $(SRC:.c=.h)
MAKE := /usr/bin/make
CC := /usr/bin/gcc
CP := cp
MV := mv
LDFLAGS := -L/usr/local/lib
DEBUG := -ggdb3
CCFLAGS := $(DEBUG) -Wall -Wextra -pedantic -Wconversion -std=gnu11
LIBS := -lssl -ldl -lrt -lz -lc -lm
#
# link the .o files into the executable
# using the linker flags
# -- explicit rule
#
$(name): $(OBJ)
#
# ======= $(name) Link Start =========
$(CC) $(LDFLAGS) -o $# $(OBJ) $(LIBS)
# ======= $(name) Link Done ==========
#
# note:
# using MV rather than CP results in all executables being re-made everytime
$(BINDIR)/$(name): $(name)
#
# ======= $(name) Copy Start =========
sudo $(CP) $(name) $(BINDIR)/.
# ======= $(name) Copy Done ==========
#
#
#create dependancy files -- inference rule
# list makefile.mak as dependancy so changing makfile forces rebuild
#
%.d: %.c
#
# ========= START $< TO $# =========
$(CC) $< > $#.$$$$; \
sed 's,\($*\)\.o[ :]*,\1.o $# : ,g' < $#.$$$$ > $#; \
rm -f $#.$$$$
# ========= END $< TO $# =========
#
# compile the .c file into .o files using the compiler flags
# -- inference rule
#
%.o: %.c %.d
#
# ========= START $< TO $# =========
$(CC) $(CCFLAGS) -c $< -o $# -I.
# ========= END $< TO $# =========
#
.PHONY: clean
clean:
# ========== CLEANING UP ==========
rm -f *.o
rm -f $(name).map
rm -f $(name)
rm -f *.d
# ========== DONE ==========
# include the contents of all the .d files
# note: the .d files contain:
# <filename>.o:<filename>.c plus all the dependancies for that .c file
# I.E. the #include'd header files
# wrap with ifneg... so will not rebuild *.d files when goal is 'clean'
#
ifneq "$(MAKECMDGOALS)" "clean"
-include $(DEP)
endif

Makefile not building when updating source

I've recently picked up makefiles and am trying to automate my build process. For this makefile, I want it to find every xxx/src/xxx.c source file and build an equivalent xxx/obj/xxx.o object for each. So every obj folder mirrors the layout of a src folder.
This is working as intended but only if I clean and make. Modifying a source file and running make won't rebuild that file. I think it might have to do with my subst in the dependecy of %.o, but I don't know how to modify that and still have my automated build layout work.
CFLAGS := -std=c11 -pedantic -Wall -Wextra -O3
LIBARIES := -lm -lglut -lGL
INCDIR := include ../plib/include
SRCDIR := src ../plib/src
INC := $(foreach d, $(INCDIR),-I$d)
SRC := $(wildcard $(foreach d, $(SRCDIR),$d/*.c $d/*/*.c))
OBJ := $(subst src/,obj/, $(SRC:.c=.o))
EXE := bin/test
$(EXE): $(OBJ)
gcc -o $# $(OBJ) $(LIBARIES)
$#
%.o: $(subst obj/,src/,$(%.c))
#mkdir -p $(#D)
gcc -o $# -c $(subst obj/,src/,$(#:.o=.c)) $(CFLAGS) $(INC)
.PHONY: clean
clean:
rm $(EXE)
rm $(OBJ)
You can solve such a %/xxxx/% pattern replacement by iterating over the SRCDIR:
define genrule
_prefix := $$(subst src,obj,$1/)
$$(filter $${_prefix}%.o,$$(OBJ)):\
$${_prefix}%.o: $1/%.c
endef
$(foreach d,${SRCDIR},$(eval $(call genrule,$d)))
${OBJ}:
gcc ... -c $< -p $#
You can do it with secondary expansion. It's not elegant, but it works:
.SECONDEXPANSION:
%.o: $$(addsuffix .c,$$(basename $$(subst /obj/,/src/,$$#)))
#echo building $# from $^
#mkdir -p $(#D)
gcc -o $# -c $< $(CFLAGS) $(INC)
The posted makefile is rather 'iffy' for several different reasons
The following proposed makefile is VERY EASILY modified for other projects BUT does place the object files in the same directory as the source files. You might want to 'tweak' that feature
And now, the proposed makefile
SHELL := /bin/sh
CC := /usr/bin/gcc
RM := /usr/bin/rm
MAKE := /usr/bin/make
CFLAGS := -std=c11 -pedantic -Wall -Wextra -O3
LIBS := -lm -lglut -lGL
INC := -Iinclude/ -I../plib/
SRC := $(wildcard src/*.c) $(wildcard ../plib/src/*.c)
OBJ := $(SRC:.c=.o))
DEP := $(SRC:.c=.d)
EXE := bin/test
.PHONY: all clean
all: $(EXE)
$(EXE): $(OBJ)
#
# ======= $(EXE) Link Start =========
$(CC) $(LDFLAGS) -o $# $(OBJ) $(LIBS)
# ======= $(EXE) Link Done ==========
#
#
# create dependancy files
#
%.d: %.c
#
# ========= START $< TO $# =========
$(CC) -M $(CPPFLAGS) $< > $#.$$$$; \
sed 's,\($*\)\.o[ :]*,\1.o $# : ,g' < $#.$$$$ > $#; \
(RM) -f $#.$$$$
# ========= END $< TO $# =========
#
# compile the .c files into .o files using the compiler flags
#
%.o: %.c %.d
#
# ========= START $< TO $# =========
$(CC) $(CFLAGS) -c $< -o $# $(INC)
# ========= END $< TO $# =========
#
clean:
# ========== start clean activities ==========
rm -f *.o
rm -f $(EXE)
rm -f *.d
# ========== end clean activities ==========
# include the contents of all the .d files
# note: the .d files contain:
# <filename>.o:<filename>.c plus all the dependancies for that file
# I.E. the #include'd header files
# wrap with ifneg... so will not rebuild *.d files when goal is 'clean'
#
ifneq "$(MAKECMDGOALS)" "clean"
-include $(DEP)
endif

how does the .Tpo file generate?why there is "NO Such file or directory"?

output of make:
Making all in access/
gcc -g -O2 -o fileOpt fileOpt.o
Making all in executor/
gcc -g -O2 -o executor execFilter.o execJoin.o execMain.o execNode.o execProject.o execScan.o execSort.o execUtil.o
Making all in index/
gcc -g -O2 -o index b_plus_tree.o
Making all in nodes/
gcc -g -O2 -o nodes nodes.o
Making all in optimizer/
gcc -g -O2 -o optimizer optimizer.o path.o
Making all in parse/
gcc -g -O2 -o parser analyze.o check.o gram.o parser.o scan.o
Making all in posql/
gcc -DHAVE_CONFIG_H -D_GNU_SOURCE -I. -I.. -I /Users/YOuth/Program/posql/src/backend/include -g -O2 -MT ../util/transfrom.o -MD -MP -MF .deps/../util/transfrom.Tpo -c -o ../util/transfrom.o ../util/transfrom.c
error: error opening '.deps/../util/transfrom.Tpo': Error opening output file '.deps/../util/transfrom.Tpo': No such file or director
I found in other folder(access/ index/ ...),It also has no .Tpo file in the .dep folder? Why it just util cannot find?
ls util/
Makefile Makefile.am Makefile.in transfrom.c util.c
transfrom.c:
#include "util/transfrom.h"
#include "util/datatype.h"
#include "string.h"
#include "stdlib.h"
void strToDate(Date* date , char* str){
....
}
My question is how the Tpo generate? Is there any possible even obvious mistakes? thanks in advance.
Amongst other problems with the listed makefile(s), this parameter: .deps/../util/transfrom.Tpo is very unlikely to be correct.
It says: in the sub directory .deps (notice the .)
step up one directory (that is where the makefile is) then step down to the util directory.
Then generate the file transfrom.Tpo.
Hummm. Perhaps it is just a typo, but I suspect transform.Tpo is wrong as is the path being presented.
However, of interest is (normally) there is a dependency file for each source file, not just one dependency file. And it is usually best to name those dependency files the same root name as the associated source file, with a unique extension, like .d
I would suggest the generation of dependancy file(s) be done in a separate make file rule, using -M -MF <file name>.c
Do not use -MP as that causes gcc to gen a target for each file and to not supply any dependency(s).
The gcc parameter details can be found at:
http://tigcc.ticalc.org/doc/comopts.html#SEC3
The following is a make file (actually a pair of makefiles) that handle
generation of dependencies, compiling, linking in each sub directory and the main directory. They use sed rather than gcc to generate the dependency files, but the above info will enable you to tweak that rule.
This is the top level makefile:
Note: the allDirectories macro is a list of the sub directories,
which would would have to tweak for your list of sub directories
SHELL = /bin/sh
# note: this makefile.mak needs to be run from the ./src directory
# of the GOT4 directory tree
SRC := $(wildcard *.c)
OBJ := $(SRC:.c=.o)
DEP := $(SRC:.c=.d)
INC := $(SRC:.c=.h)
MAKE := /usr/bin/make
CC := /usr/bin/gcc
CP := cp
MV := mv
LDFLAGS := -L/usr/local/lib -L/usr/lib -L/lib
DEBUG := -ggdb3
CCFLAGS := $(DEBUG) -Wall -W
#CPPFLAGS += =MD
LIBS := -lssl -ldl -lrt -lz -lc -lm -lcrypto
.PHONY: AllDirectories
# the following statement needs to be edited as
# subdirectories are added/deleted/re-named
AllDirectories := \
CommandConfiguration \
Communication \
MainScheduler \
RetrieveCDSLog \
RetrieveEventRecorderLog \
RetrieveGPS \
QESRouter
.PHONY: all
#all: $(OBJ) $(AllDirectories)
# $(foreach d,$(AllDirectories), \
# ( cd $d && $(MAKE) -f makefile.mak name=Tsk_$d all ); )
all: $(OBJ) $(AllDirectories)
$(foreach d,$(AllDirectories), \
( cd $d && $(MAKE) -f ../makefile.bot name=Tsk_$d all ); )
#
# create dependancy files
#
%.d: %.c
#
# ========= START $< TO $# =========
$(CC) -M $(CPPFLAGS) $< > $#.$$$$; \
sed 's,\($*\)\.o[ :]*,\1.o $# : ,g' < $#.$$$$ > $#; \
rm -f $#.$$$$
# ========= END $< TO $# =========
#
# compile the .c file into .o files using the compiler flags
#
%.o: %.c %.d
#
# ========= START $< TO $# =========
$(CC) $(CCFLAGS) -c $< -o $# -I.
# ========= END $< TO $# =========
#
.PHONY: clean
#clean: $(AllDirectories)
# # ========== start clean activities ==========
# rm -f *.o
# rm -f $(name).map
# rm -f $(name)
# rm -f *.d
# $(foreach d,$(AllDirectories), \
# ( cd $d && $(MAKE) -f makefile.mak clean ); )
# # ========== end clean activities ==========
clean: $(AllDirectories)
# ========== start clean activities ==========
rm -f *.o
rm -f $(name).map
rm -f $(name)
rm -f *.d
rm -f ../bin/Tsk_*
$(foreach d,$(AllDirectories), \
( cd $d && $(MAKE) -f ../makefile.bot name=Tsk_$d clean ); )
# ========== end clean activities ==========
.PHONY: install
#install: $(AllDirectories)
# # ========== start install activities ==========
# $(foreach d,$(AllDirectories), \
# ( cd $d && $(MAKE) -f makefile.mak clean ); )
# # ========== end install activities ==========
install: $(AllDirectories)
# ========== start install activities ==========
$(foreach d,$(AllDirectories), \
( cd $d && $(MAKE) -f ../makefile.bot name=Tsk_$d install ); )
# ========== end install activities ==========
# include the contents of all the .d files
# note: the .d files contain:
# <filename>.o:<filename>.c plus all the dependancies for that file
# I.E. the #include'd header files
# wrap with ifneg... so will not rebuild *.d files when goal is 'clean'
#
ifneq "$(MAKECMDGOALS)" "clean"
-include $(DEP)
endif
This is the makefile that goes in each sub directory.
SHELL = /bin/sh
BINDIR := /home/user/bin
.PHONY: all
all : $(BINDIR)/$(name) ../makefile.mak ../makefile.bot
#
# macro of all *.c files
# (NOTE:
# (the following 'wildcard' will pick up ALL .c files
# (like FileHeader.c and FunctionHeader.c
# (which should not be part of the build
# (so be sure no unwanted .c files in directory
# (or change the extension
#
SRC := $(wildcard *.c)
OBJ := $(SRC:.c=.o)
DEP := $(SRC:.c=.d)
INC := $(SRC:.c=.h)
COMMON_OBJ := $(wildcard ../*.o)
#COMMON_SRC := $(wildcard ../*.c)
#COMMON_OBJ := $(COMMON_SRC:.c=.o)
#COMMON_DEP := $(COMMON_SRC:.c=.d)
#COMMON_INC := $(COMMON_SRC:.c=.h)
MAKE := /usr/bin/make
CC := /usr/bin/gcc
CP := cp -f
MV := mv
LDFLAGS := -L/usr/local/lib
DEBUG := -ggdb3
CCFLAGS := $(DEBUG) -Wall -W
#CPPFLAGS += =MD
#LIBS := -lidn -lssl -ldl -lrt -lz -lc -lm
LIBS := -lssl -ldl -lrt -lz -lc -lm -lcrypto
#
# link the .o files into the executable
# using the linker flags
# -- explicit rule
#
$(name): $(OBJ) $(COMMON_OBJ) ../makefile.mak ../makefile.bot
#
# ======= $(name) Link Start =========
$(CC) $(LDFLAGS) -o $# $(OBJ) $(COMMON_OBJ) $(LIBS)
# ======= $(name) Link Done ==========
#
# note:
# using MV rather than CP results in all executables being re-made everytime
$(BINDIR)/$(name): $(name)
#
# ======= $(name) Copy Start =========
$(CP) $(name) $(BINDIR)/
# ======= $(name) Copy Done ==========
#
#
#create dependancy files -- inference rule
# list makefile.mak as dependancy so changing makfile forces rebuild
#
%.d: %.c
#
# ========= START $< TO $# =========
$(CC) -M $(CPPFLAGS) $< > $#.$$$$; \
sed 's,\($*\)\.o[ :]*,\1.o $# : ,g' < $#.$$$$ > $#; \
rm -f $#.$$$$
# ========= END $< TO $# =========
#
# compile the .c file into .o files using the compiler flags
# -- inference rule
#
%.o: %.c %.d
#
# ========= START $< TO $# =========
$(CC) $(CCFLAGS) -c $< -o $# -I.
# ========= END $< TO $# =========
#
.PHONY: clean
clean:
# ========== CLEANING UP ==========
rm -f *.o
rm -f $(name).map
rm -f $(name)
rm -f *.d
# ========== DONE ==========
.PHONY: install
install: all
# include the contents of all the .d files
# note: the .d files contain:
# <filename>.o:<filename>.c plus all the dependencies for that .c file
# I.E. the #include'd header files
# wrap with ifneg... so will not rebuild *.d files when goal is 'clean'
#
ifneq "$(MAKECMDGOALS)" "clean"
-include $(DEP)
endif

Makefile: Compiling objects to source folder

I have the following makefile
# project name (generate executable with this name)
TARGET = tp3
CC = gcc -std=c99 -c
# compiling flags here
CFLAGS = -Wall -I. -Werror-implicit-function-declaration
LINKER = gcc -o
# linking flags here
LFLAGS = -Wall
# debug flags here
DFLAGS = -g -DDEBUG
SOURCES := $(shell find . -type f -name '*.c')
INCLUDES := $(shell find . -type f -name '*.h')
OBJECTS := $(SOURCES:.c=.o)
rm = rm -rf
$(TARGET): obj
#$(LINKER) $(TARGET) $(LFLAGS) $(OBJECTS)
#echo "Linking complete!"
obj: $(SOURCES) $(INCLUDES)
#$(CC) $(CFLAGS) -DNDEBUG $(SOURCES)
#echo "Compilation complete!"
#debug:
# gcc $(DFLAGS) $(SOURCES) -o $(TARGET)
dobj: $(SOURCES) $(INCLUDES)
#$(CC) $(CFLAGS) $(DFLAGS) $(SOURCES)
#echo "dlinking complete!"
debug: dobj
#$(LINKER) $(TARGET) $(LFLAGS) $(DFLAGS) $(OBJECTS) -o $(TARGET)
#echo "dcompilation complete!"
run:
./tp3
clean:
#$(rm) $(TARGET) $(OBJECTS) *.dSYM
#echo "Cleanup complete!"
Problem is: I have files inside the folder CMM/CMM and OBJECTS assumes the objects to also be in the CMM/CMM folder, but the compiler is putting them in the root folder. How can I either get the compiler to compile the .o files in CMM/CMM or tell the pattern replacer OBJECTS := $(SOURCES:.c=.o) that everything is in the root folder?
Your real problem here is that you're not using the tools make provides you to simplify your task.
Also, your compiler is putting all the .o files in the root folder because you didn't tell him not to do so, or let make do that for you.
Here is the working Makefile:
EXE := tp3
SRC := $(shell find . -type f -name '*.c')
OBJ := $(SRC:.c=.o)
# Preprocessor flags here
CPPFLAGS := -I.
# Compiler flags here
CFLAGS := -std=c99 -Wall -Werror-implicit-function-declaration
.PHONY: all debug run clean
all: CPPFLAGS += -DNDEBUG
all: $(EXE)
debug: CPPFLAGS += -DDEBUG
debug: CFLAGS += -g
debug: $(EXE)
$(EXE): $(OBJ)
#echo "Compilation complete!"
$(CC) $(LDFLAGS) $^ $(LDLIBS) -o $#
#echo "Linking complete!"
run:
./$(EXE)
clean:
#$(RM) $(EXE) $(OBJ) *.dSYM
#echo "Cleanup complete!"
Make has a set of built-in variables and rules that you should use to avoid losing time and encountering simple mistakes.
Note that this Makefile does not handle dependencies well, and simply adding the list of .h files to the Makefile won't be enough. You can workaround this by letting your compiler create the dependency files on the fly along with the compilation of .o files like this:
Build the list of .d filenames: DEP := $(OBJ:.o=.d),
Tell the compiler to generate the corresponding files, add the -MMD -MP switches to the CPPFLAGS built-in variable,
Include them in the Makefile so it will parse their content: -include $(DEP),
Don't forget to clean them up, add $(DEP) to the $(RM) command in the clean target.
Result:
EXE := tp3
SRC := $(shell find . -type f -name '*.c')
OBJ := $(SRC:.c=.o)
DEP := $(OBJ:.o=.d)
# Preprocessor flags here
CPPFLAGS := -MMD -MP -I.
# Compiler flags here
CFLAGS := -std=c99 -Wall -Werror-implicit-function-declaration
.PHONY: all debug run clean
all: CPPFLAGS += -DNDEBUG
all: $(EXE)
debug: CPPFLAGS += -DDEBUG
debug: CFLAGS += -g
debug: $(EXE)
$(EXE): $(OBJ)
#echo "Compilation complete!"
$(CC) $(LDFLAGS) $^ $(LDLIBS) -o $#
#echo "Linking complete!"
-include $(DEP)
run:
./$(EXE)
clean:
#$(RM) $(EXE) $(OBJ) $(DEP) *.dSYM
#echo "Cleanup complete!"
If you have any question, go ahead.
If you use GNU make, then you may use patters rules or even static patterns:
%.o: %.c
$(CC) -c $(CFLAGS) $< -o $#
if not, use old syntax
.c.o:
here are the contents of two makefile items.
a top level makefile the drives the makefile.bot
the makefile.bot handles files/executables in other directorys
these makefiles also use recursion to produce the dependency lists
so only those header files that are actually include'd in the source
are listed as dependencies for that source.
Note: there are several common .c and .h files in the top level directory
so they are compiled first, then referenced later
when performing the link activity in each of the sub directories
Note: the 'AllDirectorys' is a list of the sub directories
where source code is to be compiled/linked in individual executables
Note: this is setup to run on Linux, and uses linux shell commands
and certain utilities, like 'sed'
file: makefile.mak (the top level file)
SHELL = /bin/sh
# note: this makefile.mak needs to be run from the ./src directory
# of the GOT4 directory tree
SRC := $(wildcard *.c)
OBJ := $(SRC:.c=.o)
DEP := $(SRC:.c=.d)
INC := $(SRC:.c=.h)
MAKE := /usr/bin/make
CC := /usr/bin/gcc
CP := cp
MV := mv
LDFLAGS := -L/usr/local/lib -L/usr/lib -L/lib
DEBUG := -ggdb3
CCFLAGS := $(DEBUG) -Wall -W
#CPPFLAGS += =MD
LIBS := -lssl -ldl -lrt -lz -lc -lm -lcrypto
.PHONY: AllDirectories
# the following statement needs to be edited as
# subdirectories are added/deleted/re-named
AllDirectories := \
CommandConfiguration \
Communication \
MainScheduler \
RetrieveCDSLog \
RetrieveEventRecorderLog \
RetrieveGPS \
QESRouter
#AllDirectories := \
# MainScheduler \
# Communication \
# RetrieveGPS \
# TestCommunicationDev
.PHONY: all
#all: $(OBJ) $(AllDirectories)
# $(foreach d,$(AllDirectories), \
# ( cd $d && $(MAKE) -f makefile.mak name=Tsk_$d all ); )
all: $(OBJ) $(AllDirectories)
$(foreach d,$(AllDirectories), \
( cd $d && $(MAKE) -f ../makefile.bot name=Tsk_$d all ); )
#
# create dependancy files
#
%.d: %.c
#
# ========= START $< TO $# =========
$(CC) -M $(CPPFLAGS) $< > $#.$$$$; \
sed 's,\($*\)\.o[ :]*,\1.o $# : ,g' < $#.$$$$ > $#; \
rm -f $#.$$$$
# ========= END $< TO $# =========
#
# compile the .c file into .o files using the compiler flags
#
%.o: %.c %.d
#
# ========= START $< TO $# =========
$(CC) $(CCFLAGS) -c $< -o $# -I.
# ========= END $< TO $# =========
#
.PHONY: clean
#clean: $(AllDirectories)
# # ========== start clean activities ==========
# rm -f *.o
# rm -f $(name).map
# rm -f $(name)
# rm -f *.d
# $(foreach d,$(AllDirectories), \
# ( cd $d && $(MAKE) -f makefile.mak clean ); )
# # ========== end clean activities ==========
clean: $(AllDirectories)
# ========== start clean activities ==========
rm -f *.o
rm -f $(name).map
rm -f $(name)
rm -f *.d
rm -f ../bin/Tsk_*
$(foreach d,$(AllDirectories), \
( cd $d && $(MAKE) -f ../makefile.bot name=Tsk_$d clean ); )
# ========== end clean activities ==========
.PHONY: install
#install: $(AllDirectories)
# # ========== start install activities ==========
# $(foreach d,$(AllDirectories), \
# ( cd $d && $(MAKE) -f makefile.mak clean ); )
# # ========== end install activities ==========
install: $(AllDirectories)
# ========== start install activities ==========
$(foreach d,$(AllDirectories), \
( cd $d && $(MAKE) -f ../makefile.bot name=Tsk_$d install ); )
# ========== end install activities ==========
# include the contents of all the .d files
# note: the .d files contain:
# <filename>.o:<filename>.c plus all the dependancies for that file
# I.E. the #include'd header files
# wrap with ifneg... so will not rebuild *.d files when goal is 'clean'
#
ifneq "$(MAKECMDGOALS)" "clean"
-include $(DEP)
endif
file: makefile.bot which only occurs once, in the top level directory
along side the above listed makefile.mak
SHELL = /bin/sh
BINDIR := /home/user/bin
.PHONY: all
all : $(BINDIR)/$(name) ../makefile.mak ../makefile.bot
#
# macro of all *.c files
# (NOTE:
# (the following 'wildcard' will pick up ALL .c files
# (like FileHeader.c and FunctionHeader.c
# (which should not be part of the build
# (so be sure no unwanted .c files in directory
# (or change the extension
#
SRC := $(wildcard *.c)
OBJ := $(SRC:.c=.o)
DEP := $(SRC:.c=.d)
INC := $(SRC:.c=.h)
COMMON_OBJ := $(wildcard ../*.o)
#COMMON_SRC := $(wildcard ../*.c)
#COMMON_OBJ := $(COMMON_SRC:.c=.o)
#COMMON_DEP := $(COMMON_SRC:.c=.d)
#COMMON_INC := $(COMMON_SRC:.c=.h)
MAKE := /usr/bin/make
CC := /usr/bin/gcc
CP := cp -f
MV := mv
LDFLAGS := -L/usr/local/lib
DEBUG := -ggdb3
CCFLAGS := $(DEBUG) -Wall -W
#CPPFLAGS += =MD
#LIBS := -lidn -lssl -ldl -lrt -lz -lc -lm
LIBS := -lssl -ldl -lrt -lz -lc -lm -lcrypto
#
# link the .o files into the executable
# using the linker flags
# -- explicit rule
#
$(name): $(OBJ) $(COMMON_OBJ) ../makefile.mak ../makefile.bot
#
# ======= $(name) Link Start =========
$(CC) $(LDFLAGS) -o $# $(OBJ) $(COMMON_OBJ) $(LIBS)
# ======= $(name) Link Done ==========
#
# note:
# using MV rather than CP results in all executables being re-made everytime
$(BINDIR)/$(name): $(name)
#
# ======= $(name) Copy Start =========
$(CP) $(name) $(BINDIR)/
# ======= $(name) Copy Done ==========
#
#
#create dependancy files -- inference rule
#
%.d: %.c
#
# ========= START $< TO $# =========
$(CC) -M $(CPPFLAGS) $< > $#.$$$$; \
sed 's,\($*\)\.o[ :]*,\1.o $# : ,g' < $#.$$$$ > $#; \
rm -f $#.$$$$
# ========= END $< TO $# =========
#
# compile the .c file into .o files using the compiler flags
# -- inference rule
#
%.o: %.c %.d
#
# ========= START $< TO $# =========
$(CC) $(CCFLAGS) -c $< -o $# -I.
# ========= END $< TO $# =========
#
.PHONY: clean
clean:
# ========== CLEANING UP ==========
rm -f *.o
rm -f $(name).map
rm -f $(name)
rm -f *.d
# ========== DONE ==========
.PHONY: install
install: all
# include the contents of all the .d files
# note: the .d files contain:
# <filename>.o:<filename>.c plus all the dependancies for that .c file
# I.E. the #include'd header files
# wrap with ifneg... so will not rebuild *.d files when goal is 'clean'
#
ifneq "$(MAKECMDGOALS)" "clean"
-include $(DEP)
endif

How to use gcc to compile multiple different source .c files into differently named executables

Wow, what a title. I need help either creating a makefile, or simply figuring out the gcc command for the following. It has very specific specifications which need to be met.
I have 6 source files, called AA.c, BB.c, CC.c, DD.c, EE.c, and FF.c. I need to compile these such that the executables are named as AA, BB, CC, DD, EE, and FF, respectively.
This is because AA.c calls other executables from within, which are named with hardcoded values. Thus, the executables must be named as I listed above, or AA will throw error and not run.
Then the user can simply type AA at the console.
Not sure if .out is needed to be present past the end of each executable name, if so, that is perfectly fine as it can be modified easily.
Here's how I would do it with GNU make:
all: $(patsubst %.c,%,$(wildcard *.c))
%: %.o
$(CC) -o $# $<
Or if you have other .c files too and just want the 6 you listed to be compiled as programs, make the first line:
all: AA BB CC DD EE FF
I have a pair of make files that produce one executable for each sub directory
IMO: the best layout is one executable per directory.
Top level make file: makefile.mak
------------------
SHELL = /bin/sh
SRC := $(wildcard *.c)
OBJ := $(SRC:.c=.o)
DEP := $(SRC:.c=.d)
INC := $(SRC:.c=.h)
MAKE := /usr/bin/make
CC := /usr/bin/gcc
CP := cp
MV := mv
LDFLAGS := -L/usr/local/lib -L/usr/lib -L/lib
DEBUG := -ggdb3
CCFLAGS := $(DEBUG) -Wall -W
#CPPFLAGS += =MD
LIBS := -lssl -ldl -lrt -lz -lc -lm
.PHONY: AllDirectories
# the following statement needs to be edited as
# subdirectories are added/deleted/re-named
#AllDirectories := \
# Command_Configuration \
# Communication \
# Main_Scheduler \
# Retrieve_CDS_Log \
# Retrieve_EventRecorder_Log \
# Retrieve_GPS \
# Retrieve_QES_Alarm_Log \
# Retrieve_QES_RealTime \
# Write_CDS_Log
AllDirectories := \
Main_Scheduler \
Communication \
Retrieve_GPS \
Test_Communication_Dev
.PHONY: all
all: $(OBJ) $(AllDirectories)
$(foreach d,$(AllDirectories), \
( cd $d && $(MAKE) -f ../makefile.bot name=Tsk_$d all ); )
#
# create dependancy files
#
%.d: %.c
#
# ========= START $< TO $# =========
$(CC) -M $(CPPFLAGS) $< > $#.$$$$; \
sed 's,\($*\)\.o[ :]*,\1.o $# : ,g' < $#.$$$$ > $#; \
rm -f $#.$$$$
# ========= END $< TO $# =========
#
# compile the .c file into .o files using the compiler flags
#
%.o: %.c %.d
#
# ========= START $< TO $# =========
$(CC) $(CCFLAGS) -c $< -o $# -I.
# ========= END $< TO $# =========
#
.PHONY: clean
clean: $(AllDirectories)
# ========== start clean activities ==========
rm -f *.o
rm -f $(name).map
rm -f $(name)
rm -f *.d
rm -f ../bin/Tsk_*
$(foreach d,$(AllDirectories), \
( cd $d && $(MAKE) -f ../makefile.bot name=Tsk_$d clean ); )
# ========== end clean activities ==========
.PHONY: install
#install: $(AllDirectories)
# # ========== start install activities ==========
# $(foreach d,$(AllDirectories), \
# ( cd $d && $(MAKE) -f makefile.mak clean ); )
# # ========== end install activities ==========
install: $(AllDirectories)
# ========== start install activities ==========
$(foreach d,$(AllDirectories), \
( cd $d && $(MAKE) -f ../makefile.bot name=Tsk_$d install ); )
# ========== end install activities ==========
# include the contents of all the .d files
# note: the .d files contain:
# <filename>.o:<filename>.c plus all the dependancies for that file
# I.E. the #include'd header files
# wrap with ifneg... so will not rebuild *.d files when goal is 'clean'
#
ifneq "$(MAKECMDGOALS)" "clean"
-include $(DEP)
endif
--------------
the second make file performs the actual make in each sub directory
--------------
SHELL = /bin/sh
BINDIR := /home/user/bin
.PHONY: all
all : $(BINDIR)/$(name) ../makefile.mak ../makefile.bot
#
# macro of all *.c files
# (NOTE:
# (the following 'wildcard' will pick up ALL .c files
# (like FileHeader.c and FunctionHeader.c
# (which should not be part of the build
# (so be sure no unwanted .c files in directory
# (or change the extension
#
SRC := $(wildcard *.c)
OBJ := $(SRC:.c=.o)
DEP := $(SRC:.c=.d)
INC := $(SRC:.c=.h)
COMMON_OBJ := $(wildcard ../*.o)
#COMMON_SRC := $(wildcard ../*.c)
#COMMON_OBJ := $(COMMON_SRC:.c=.o)
#COMMON_DEP := $(COMMON_SRC:.c=.d)
#COMMON_INC := $(COMMON_SRC:.c=.h)
MAKE := /usr/bin/make
CC := /usr/bin/gcc
CP := cp
MV := mv
LDFLAGS := -L/usr/local/lib
DEBUG := -ggdb3
CCFLAGS := $(DEBUG) -Wall -W
#CPPFLAGS += =MD
#LIBS := -lidn -lssl -ldl -lrt -lz -lc -lm
LIBS := -lssl -ldl -lrt -lz -lc -lm
#
# link the .o files into the executable
# using the linker flags
# -- explicit rule
#
$(name): $(OBJ) $(COMMON_OBJ) ../makefile.mak ../makefile.bot
#
# ======= $(name) Link Start =========
$(CC) $(LDFLAGS) -o $# $(OBJ) $(COMMON_OBJ) $(LIBS)
# ======= $(name) Link Done ==========
#
# note:
# using MV rather than CP results in all executables being re-made everytime
$(BINDIR)/$(name): $(name)
#
# ======= $(name) Copy Start =========
sudo $(CP) $(name) $(BINDIR)/.
# ======= $(name) Copy Done ==========
#
#
#create dependancy files -- inference rule
# list makefile.mak as dependancy so changing makfile forces rebuild
#
%.d: %.c
#
# ========= START $< TO $# =========
$(CC) -M $(CPPFLAGS) $< > $#.$$$$; \
sed 's,\($*\)\.o[ :]*,\1.o $# : ,g' < $#.$$$$ > $#; \
rm -f $#.$$$$
# ========= END $< TO $# =========
#
# compile the .c file into .o files using the compiler flags
# -- inference rule
#
%.o: %.c %.d
#
# ========= START $< TO $# =========
$(CC) $(CCFLAGS) -c $< -o $# -I.
# ========= END $< TO $# =========
#
.PHONY: clean
clean:
# ========== CLEANING UP ==========
rm -f *.o
rm -f $(name).map
rm -f $(name)
rm -f *.d
# ========== DONE ==========
.PHONY: install
install: all
# include the contents of all the .d files
# note: the .d files contain:
# <filename>.o:<filename>.c plus all the dependancies for that .c file
# I.E. the #include'd header files
# wrap with ifneg... so will not rebuild *.d files when goal is 'clean'
#
ifneq "$(MAKECMDGOALS)" "clean"
-include $(DEP)
endif
-----------------

Resources