How do I add a debug option to Makefile - c

I've got the below simple Makefile which I use for compiling a C program:
all:
gcc -Wall -o myfile myfile.c lol_dht22/dht22.c lol_dht22/locking.c -lwiringPi -lcurl -lm
I want to add in a debug option so I can compile with -DDEBUG, so if I run
make
it compiles as normal. and if I run
make debug
it compliles with the debug flag.
I have read through a few tutorial but seems to be getting more and more confused.

If you want to know how to do it well, here it is. You don't do make debug, instead, you should call
>make
or
>make DEFS=DEBUG
or
>make DEFS='ANY DEFINES YOU WANT'
In addition to normal Make rebuild criteria, the following Makefile recognizes rebuilds based on DEFS.
define DEPENDABLE_VAR
.PHONY: phony
$1: phony
#if [[ `cat $1 2>&1` != '$($1)' ]]; then \
echo -n $($1) > $1 ; \
fi
endef
$(eval $(call DEPENDABLE_VAR,DEFS))
.PHONY: all
all: myfile
SRCS := myfile.c lol_dht22/dht22.c lol_dht22/locking.c
myfile: $(SRCS) Makefile DEFS
gcc $(addprefix -D, $(DEFS)) -Wall -o $# $(SRCS) -lwiringPi -lcurl -lm

Here's an example makefile that has the two options you are looking for.
all:
gcc -Wall -o myfile myfile.c lol_dht22/dht22.c lol_dht22/locking.c -lwiringPi -lcurl -lm
debug:
gcc -DDEBUG -Wall -o myfile myfile.c lol_dht22/dht22.c lol_dht22/locking.c -lwiringPi -lcurl -lm
You just needed to add a debug option, which is done in similar fashion to the 'all' option you had already declared.

Related

makefile - how to exclude file extension suffix from a variable

the next makefile receive the file to compile from its command line arg -ARGS. For example
make ARGS="out.c"
I would like to replace the name of the created executable "run" with the variable ARGS excluding the suffix
in this example : run="out"
all: Task1
Task1: outputs/output.o
gcc -g -m32 -Wall -o run outputs/output.o
outputs/output.o: outputs/${ARGS}
gcc -m32 -g -w -Wall -ansi -c -o outputs/output.o outputs/${ARGS}
.PHONY: clean
run: clean Task1
clean:
rm -f outputs\output.o Task1
The crude way to do what you ask is simply:
EXEC := $(basename $(ARGS))
all: Task1
Task1: outputs/output.o
gcc -g -m32 -Wall -o $(EXEC) outputs/output.o
A better way is:
EXEC := $(basename $(ARGS))
all: $(EXEC)
$(EXEC): outputs/output.o
gcc -g -m32 -Wall -o $(EXEC) outputs/output.o
Better still:
EXEC := $(basename $(ARGS))
all: $(EXEC)
$(EXEC): outputs/output.o
gcc -g -m32 -Wall -o $# $^
If using GNU make you need the basename function, perhaps as $(basename $(AUX)). Maybe variables like $(*F) might be useful too (please read the documentation). However, your Makefile is probably wrong.
I can't suggest an improvement, because what you want to do and to happen is unclear.
BTW, use remake (as remake -x) or at least make --trace (with a recent enough GNU make 4.x) to understand what make is doing and why.
Also, you'll find several examples of Makefile-s: here & there
etc... Don't forget that make has a many builtin rules, you'll get them by running make -p
You won't lose your time by reading the documentation of GNU make, and some tutorials, and some examples of Makefile-s.

Creating makefile with debug option

I have created a (very simple) makefile:
DEBUG = -DDEBUG
main: main.c add.c
gcc $(DEBUG) main.c add.c -o main -lm
What I want (and don't understand how to do), is to create the makefile so that if the user prints make debug, the code will compile with the debug option, but when printing only make, the debug will be left out. What is the best way to do this?
You probably are looking for something like
main: main.c add.c
gcc $(DEBUG) main.c add.c -o main -lm
debug: DEBUG = -DDEBUG
debug: main
This may be late, ...
The basic idea is to build all objects in the subdirectory, say ./build.
We create a release file in ./build when we compile with make and create a debug file when make debug. So if there is a release file when make debug, remove everything in ./build and then build.
all: $(BD)/release $(bin1) $(bin2)
debug: CFLAGS += -g -DDEBUG=1
debug: CXXFLAGS += -g -DDEBUG=1
debug: $(BD)/debug $(bin1) $(bin2)
$(BD)/%.o: %.c Makefile # changes in Makefile will cause a rebuild
#mkdir -p $(BD)
$(CC) $(CFLAGS) -c -o $# $<
$(BD)/%.o: %.cpp Makefile
#mkdir -p $(BD)
$(CXX) $(CXXFLAGS) -c -o $# $<
$(BD)/release:
#if [ -e $(BD)/debug ]; then rm -rf $(BD); fi
#mkdir -p $(BD)
#touch $(BD)/release
$(BD)/debug:
#if [ -e $(BD)/release ]; then rm -rf $(BD); fi
#mkdir -p $(BD)
#touch $(BD)/debug
I came up with this solution, that depends on bash variable substitution.
Makefile:
main: main.c add.c
${CC} `echo $${DEBUG+-DDEBUG}` main.c add.c -o main -lm
When environment variable DEBUG is defined to anything (even blank), this makefile will substitute the -DDEBUG useful to the compiler. So invocation looks like:
DEBUG=1 make main

Makefile compile error not applying -std=c99

I have been given supposedly working code that I just need to modify, however I can't actually compile the program with the supplied makefile given below.
INCLUDE_PATH = -I/usr/X11/include -I$(BLDR_FREEGLUT_INCLUDE_PATH)
LIBRARY_PATH = -L/usr/X11/lib -L$(BLDR_FREEGLUT_LIB_PATH)
CCFLAGS = -std=c99
LDFLAGS = -lGL -lGLU -lglut -lX11 -lpthread
GCC = gcc
APP = nbody
all: $(APP)
#echo Make done
clean:
#rm -f *.o $(APP)
nbody: nbody.c
$(GCC) nbody.c -o nbody $(INCLUDE_PATH) $(CCFLAGS) $(LIBRARY_PATH) $(LDFLAGS)
The first output line of the make command gives below.
gcc nbody.c -o nbody -I/usr/X11/include -I -std=c99 -L/usr/X11/lib -L -lGL -lGLU -lglut -lX11 -lpthread
However below that are errors saying that certain things are only "allowed in C99 mode", which I don't understand since the flag for c99 seems to be specified correctly. To troubleshoot this I have tried changing the location of the $(CCFLAGS) value without any success.
How can I modify this makefile so the program complies?
-I -std=c99 says compiler to add directory named -std=c99 to include search paths. This is not what you wanted. Judging by presented fragment, $(BLDR_FREEGLUT_INCLUDE_PATH) is empty - while it shouldn't be. Fix that variable's value and things will go well.

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!!!

A Makefile with Multiple Executables

I am trying to write a makefile which uses macros to create multiple executables from multiple files at once. I tried searching through previously answered questions but, because I am fairly new to programming in C as well as working with gcc, I was not able to find an answer to my question.
Here is what I have so far:
CC=gcc
CFLAGS=-I.
OBJ = ex1.c ex3.c
EXECUTABLE = ex1 ex3
$(EXECUTABLE): $(OBJ)
gcc -o $# $^ $(CFLAGS)
clean:
rm -f $(EXECUTABLE)
I would like the line
$(EXECUTABLE): $(OBJ)
to create executables ex1 and ex3 from files ex1.c ex3.c respectively.
For this particular case, where each executable has a single source file with .c extension, all you need is a one line Makefile:
all: ex1 ex3
The built-in default rules for make then work already:
$ make
cc -O2 -pipe ex1.c -o ex1
cc -O2 -pipe ex3.c -o ex3
Behind the scene, make is using the POSIXly mandated built-in single suffix rule
.c:
$(CC) $(CFLAGS) $(LDFLAGS) -o $# $<
Vary the command to your liking with make CC=gcc CFLAGS=-O2 LDFLAGS=-s and similar.
Trivia of the day: in fact, if you are willing to name the targets when invoking make, you can use an empty or even run without any Makefile:
$ make -f /dev/null CC=gcc CFLAGS=-O2 LDFLAGS=-s ex1 ex3
gcc -O2 -s ex1.c -o ex1
gcc -O2 -s ex3.c -o ex3
$ rm -f Makefile ex1 ex3
$ make CC=gcc CFLAGS=-O2 LDFLAGS=-s ex1 ex3
gcc -O2 -s ex1.c -o ex1
gcc -O2 -s ex3.c -o ex3
Make magic!
As a rule of thumb, don't reinvent the wheel (or rules), use the rules that are already there. It simplifies your and make's life a lot. This makes for small and sexy makefiles to impress the ladies with :-)
Some suggestions (assuming you use GNU make, not something else)
First, run once make -p, you'll understand what builtin rules make is knowing. Look in particular for COMPILE.c and LINK.c
Then, I suggest
CFLAGS= -g -Wall -I.
(because you really want -g for debugging, and -Wall to get most warnings)
And you probably don't need
$(EXECUTABLE): $(OBJ)
gcc -o $# $^ $(CFLAGS)
However, I suggest adding before most other rules
.PHONY: all clean
all: $(EXECUTABLES)
Actually, I would code your Makefile (for GNU make!) as follow
# file Makefile
CC= gcc
RM= rm -vf
CFLAGS= -Wall -g
CPPFLAGS= -I.
SRCFILES= ex1.c ex2.c ## or perhaps $(wildcard *.c)
OBJFILES= $(patsubst %.c, %.o, $(SRCFILES))
PROGFILES= $(patsubst %.c, %, $(SRCFILES))
.PHONY: all clean
all: $(PROGFILES)
clean:
$(RM) $(OBJFILES) $(PROGFILES) *~
## eof Makefile
Remember that tab is a significant character in Makefile-s (action part of rules). In this answer, lines starting with four spaces at least should really start with a tab character.
Once everything is debugged consider running make clean to clean everything, and then make -j CFLAGS=-O2 all to compile in parallel everything with optimizations.
At last, I recommend using remake and running remake -x to debug complex Makefile-s
Of course, I'm supposing that your directory has only single-file programs.
BTW, there are other build automation tools. Perhaps you might consider using omake or ninja. For building large programs (millions of source code lines) consider also automake, ccache, cmake, icecream. In some cases, consider generating some C code with GPP, GNU bison, SWIG, etc... or using your own Python or Guile script (or C meta-program). See also this draft report.
Don't forget to use a version control system like git for your source files. It is also time to learn such a tool.
The following answer includes multiple executable such as initiate, process1, process2, ..., process4.
LOCAL_INCLUDE=./
all: clean process_first process_second init
process_first:
gcc -g -o process1 -I$(LOCAL_INCLUDE) process1.c -lzmq -L. -L./.
gcc -g -o process2 -I$(LOCAL_INCLUDE) process2.c -lzmq -L. -L./.
process_second:
gcc -g -o process3 -I$(LOCAL_INCLUDE) process3.c -lzmq -L. -L./.
gcc -g -o process4 -I$(LOCAL_INCLUDE) process4.c -lzmq -L. -L./.
init:
gcc -g -o initiate -I$(LOCAL_INCLUDE) initiate.c -lzmq -lconfig -lpthread -L. -L./. -ldl -lrt
clean:
rm -rf init_manager.o init_manager
rm -rf process1 process2 process3 process4
NOTE: It is a good practice to clean and touch all the executable files before making them again.
You're close, but you need a pattern rule:
$(EXECUTABLE): % : %.c
And then a default rule to make it build both:
all: $(EXECUTABLE)

Resources