Editing a makefile to allow debugging in linux - c

I've downloaded a basic makefile which I'm trying to edit to allow debugging of the program in linux, however even after adding the -g flag to the makefile, the terminal just displays [ No Source available ] when running the gdbtui command instead of the debugging information as expected.
Here's the makefile in question:
CC=gcc
EXE=myprog
CFLAGS=
LDFLAGS=
OPTCFLAGS=-O2
DEBUGCFLAGS=-g
OBJ=main.o util.o
# Default Target, dependency on $(EXE) target
all: $(EXE)
# Optimised target, add OPTCFLAGS
opt: CFLAGS+=$(OPTCFLAGS)
opt: $(EXE)
# Debug target, add DEBUG Flags
debug: CFLAGS+=$(DEBUGCFLAGS)
debug: $(EXE)
$(EXE): $(OBJ)
$(CC) $(LDFLAGS) -o $# $^
%.o:%.c
$(CC) $(CFLAGS) -c $<
.PHONY: clean test
clean:
rm *.o
rm $(EXE)
Thanks for all the help in advance.

Your makefile is OK for make debug.
gdbtui is reporting [ No Source Available ] right after you run gdbtui myprog
just because you have not yet started gdb so no debugging information
has yet been read from myprog
At this point you will see gdbtui prompting you:
---Type <return> to continue, or q <return> to quit---
Type <return>; then gdb still start; the source code will appear, and gdb will wait for
your debugging commands.
Apart from the oddness #MadScientist has noted about the default target,
there is this small bug in your makefile: The clean recipe:
clean:
rm *.o
rm $(EXE)
should be:
clean:
rm -f *.o
rm -f $(EXE)
or simply:
clean:
rm -f *.o $(EXE)
Without the -f (force) option, if you were to delete the object files
without deleting myprog and then run make clean, it will fail at rm *.o
and not run rm $(EXE).

You didn't show the commands you're using to run make. This makefile has the default target (all) not adding any flags at all (which is an odd decision).
In order to build an optimized version you have to run make clean followed by make opt.
To build a debug version of you have to run make clean followed by make debug.
What did you actually do?

Related

Makefile not generating debugging information with -g flag

I recently moved from working in the terminal to VScode and am needing to generate debugging information to use with the debugger in vscode.
My makefile is:
SRCS = src/ft_argcheck.c \
src/ft_operations.c \
src/ft_stcutils.c \
src/push_swap.c
NAME = push_swap
INCS = inc/push_swap.h
OBJS = $(SRCS:c=o)
CC = gcc
CFLAGS = -g -Wall -Wextra -Werror
RM = rm -f
LIBFT = libft/libft.a
LIBFT_DIR = libft
.PHONY: all bonus clean fclean re
all: $(NAME)
$(NAME): $(OBJS)
#make -C $(LIBFT_DIR) --silent
#$(CC) $(CFLAGS) -I$(INCS) -o $(NAME) $(OBJS) -L $(LIBFT_DIR) -lft
clean:
#$(RM) $(OBJS)
#make -s clean -C $(LIBFT_DIR)
fclean: clean
#$(RM) $(NAME)
#make -s fclean -C $(LIBFT_DIR)
re: fclean all
But despite adding the -g flag, no debugging information is generated. on which I can run lldb.
A good proposal is to remove the #s in front of the command names to see what commands make is executing.... To make a program debuggable, you need to check that all the compilation steps are done using the -g flag and that the linking step has also included the -g flag. Also a good option is to specify no optimization so you will not get to problems with breakpoints you cannot fix because the compiler has eliminated or changed the final code, and has broken the correspondence between source lines and points in the code.
If you take off all the #s there, you will see the commands as make is executing them, think you don't see now. I think there's a command (berkeley make has it) to make make to print the commands even though the #s remain in place.
By the way, as you are telling you are using vscode it should be fine if you execute make on the command line alone, to see the output of the commands, and try to see if it is some problem with make or with vscode itself.
As you have not provided your complete project, I'm sorry to say that I can only test it with dumb/fake files and no program can be made to test it with gdb.
I guess that the problem is that you have put your project sources in a different directory than where the program is built, and the sources cannot be found by gdb and so, no source debugging can be done because gdb cannot find the source files. Gdb has some way to specify the path to the source files... You should look at gdb documentation.
Thanks for all your answers (Removing # didn't really give me much more information, as it did show the -g flag and I already tried remaking everything with fclean). I seem to have figured out an easy fix with the help of a friend:
add a rule "debug"
debug:
$(CC) -g $(CFLAGS) -I$(INCS) $(LIBFT) $(SRCS) -o $(NAME)
which we can run just when we want to generate the debugging information and run this directly with $(SRCS) instead of running it on the $(OBJS) as in the normal command.

GNU make, implicit rules not needed

I have the following directory:
Makefile
src/
main.c
dummy.raw
(main.o) (<- to be built)
(dummy.txt) (<- to be built)
build/
(main) (<- to be built)
And the following Makefile:
C_FILES=$(wildcard src/*.c)
O_FILES=$(C_FILES:%.c=%.o)
main: build/main
build/main: $(O_FILES)
gcc $(O_FILES) -o build/main
src/%.o: src/%.c src/dummy.txt
echo "Compiling using my rule"
gcc -c $< -o $#
src/%.txt: src/%.raw
touch $#
#echo "Created dummy file"
clean:
rm -f src/*.o
rm -f src/*.txt
rm -f build/*
The problem is that make seems to ignore my rule for producing .o files and use its own built-in version ; in particular, it does not build dummy.txt. Here's a sample output:
$ make clean
rm -f src/*.o
rm -f src/*.txt
rm -f build/*
$ make
cc -c -o src/main.o src/main.c
gcc src/main.o -o build/main
make only starts using the rule in the Makefile if I build the .txt file myself using make src/dummy.txt.
Why is make behaving this way?
How do I correct my Makefile to force make to build the intermediate dummy.txt?
Thanks!
The trouble is that your method invokes a chain of pattern rules, one to build src/main.o and one to build src/dummy.txt, and Make will prefer an implicit rule to a chain of pattern rules.
There are a couple of ways to solve this. Two simple ones:
You could invoke Make with the ‘-r’ a.k.a. ‘--no-builtin-rules’ option:
make -r
Or you could hard-code the rule for src/dummy.txt:
src/%.txt: src/%.raw
touch $#
#echo "Created dummy file"
src/dummy.txt: src/dummy.raw

How to set up make to find the dependencies of autogenerated files that need to be compiled

I have a python script that needs to run before any other rule because it generates a few .c files that I want to compile. But there lies the problems.
In my make file I have a rule to make the depends
SRC = autogenerated_file1.c autogenerated_file2.c
depend dep: .depend
include .depend
But the problem is the files dont exist when the make file is run to make the depends, I need the python script to run first, how would I set up a rule to run before the include of the depends.
Any help would be greatly appreciated.
I simplified my makefile and provided it here:
SUBDIRS = ../modules/mod1 \
../modules/mod2 \
../modules/mod3
CFLAGS=-g -Wall
ARFLAGS=rs
CFLAGS:=$(CFLAGS) -I.
APPLICATION_FILES = main.c autogen1.c autogen2.c
APPLICATION_OBJ=$(APPLICATION_FILES:.c=.o)
-include $(APPLICATION_FILES:.c=.d)
.PHONY: dummy
dummy:
cd ../scripts && \
python autgen_files.py
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $#
clean :
rm -f *.o *.elf *.d
-for d in $(SUBDIRS); do (cd $$d; $(MAKE) clean ); done
%.fin: dummy $(SUBDIRS) %.elf
$(SUBDIRS):
$(MAKE) -C $#
%.d : %.c
$(CC) -MM $(CFLAGS) $*.c > $*.d
%.elf: $(APPLICATION_OBJ)
$(CC) -Tapp.ld $(CFLAGS) -o $# $^
The problem here is the autogen1.c and autogen2.c are not available at the start of make. And if I do what I provided above I get caught it a loop of recursive make.
I should say the way I start the build is "make test.fin"
If the python script generates the file .depend (that's my understanding but I'm not entirely sure), then add this rule:
.depend: script.py
$<
This way make will know that .depend is also a target that needs to be made, and will run script.py if it's newer than .depend or if .depend does not exist. Tweak to taste.
Note that this might only work with GNU Make.

Trouble with makefile

I am trying to write a make file that:
1) Turns the files myftpserver.c and myftpclient.c into myftpserver.o and myftpclient.o by just typing the command 'make'.
2)I'm also adding a 'clean' target for cleaning up the directory (removing all temporary files, object files and executable files)
3)using gcc compiler.
My current version is not working:
CC=gcc
myftpserver: myftpserver.o
$(CC) -o myftpserver.o
myftpclient: myftpclient.o
$(CC) -o myftpclient.o
clean: ? // not sure what to put here
This is my first time making a makefile. I've tried several other combinations but none seems to work. What am I doing wrong?
Make has rules built-in for basic C files, so you don't need to tell it how to build myftpserver.o or myftpclient.o. This Makefile should work correctly, and properly includes .PHONY so the clean rule won't get disabled in the presence of a file named "clean"
CC:=gcc
.PHONY: clean all
all: myftpserver myftpclient
myftpserver: myftpserver.o
myftpclient: myftpclient.o
clean:
rm -f *~ *.o myftpserver myftpclient
To test:
$ make --dry-run
gcc -c -o myftpserver.o myftpserver.c
gcc myftpserver.o -o myftpserver
gcc -c -o myftpclient.o myftpclient.c
gcc myftpclient.o -o myftpclient
Hope this helps!
You want instructions for compiling your .o file, and the rm shell command to clean:
CC=gcc
myftpserver: myftpserver.o
$(CC) -o myftpserver myftpserver.o
myftpclient: myftpclient.o
$(CC) -o myftpclient myftpclient.o
myftpserver.o: myftpserver.c
$(CC) myftpserver.c
myftpclient.o: myftpclient.c
$(CC) myftpclient.c
clean:
rm -f *~ *# *.o myftpserver myftpclient

Makefile in C with multiple sources

I am currently learning C and now I am upto the tutorial where I need to write the Makefile but I am difficulty writing a Makefile for multiple sources. Can someone tell me how I can correct my code for the Makefile for multiple sources? All of the files are in the same directory and there are a total of 3 C source files as indicated by filename1/2/3 etc. I am trying to build 3 separate programs with 3 source files in a single makefile
OPT = -O4
all: filename1
filename1: filename1.o
gcc $(OPT) -o filename1 filename1.o
filename1.o: filename1.c
gcc $(OPT) -c filename1.c
filename2: filename2.o
gcc $(OPT) -o filename2 filename2.o
filename2.o: filename2.c
gcc $(OPT) -c filename2.c
filename3: filename3.o
gcc $(OPT) -o filename3 filename3.o
filename3.o: filename3.c
gcc $(OPT) -c filename3.c
clean:
rm -f *.o
rm -f filename1
rm -f filename2
rm -f filename3
Or is my code fine for what I want it to do?
Okay, so there doesn't appear to be anything wrong with the makefile, given that you're making three different programs. It should work.
Some suggestions for making it a little more usable:
1) Declare the "all" and "clean" targets to be phony. This will prevent Make from trying to make files called "all" and "clean".
.PHONY: all clean
2) You probably want your "all" target to build all three of your programs, not just one, so change that to:
all: filename1 filename2 filename3
3) If you end up using this to make more than three programs, and they all share similar build procedures, you can collapse your rules into a smaller set using pattern matches. See Martin Beckett's answer for an example. But, that's not necessary.
Your makefile should work, but it could be simplified.
The make utility supports implicit rules. This can simplify common operations, such as compiling a C source code file into an object file and compiling an object file into an executable.
CC=gcc
CFLAGS=-O4
all: filename1 filename2 filename3
%.o: %.c
$(CC) $(CFLAGS) -c $<
%: %.o
$(CC) $(CFLAGS) -o $* $<
clean:
rm -f *.o
rm -f filename1
rm -f filename2
rm -f filename3
For three separate programs built from three files like that, you could simply use:
PROGRAMS = filename1 filename2 filename3
all: ${PROGRAMS}
clean:
rm -f ${PROGRAMS} ${PROGRAMS:=.o}
You might add:
CFLAGS = -O4
to get that level of optimization. You might use a macro instead of the rm command; generally, mature makefiles use a lot of macros:
RM_F = rm -f
If you're targeting GNU Make, you could add:
.PHONY: all clean
And the list goes on.
The key point is that make knows how to build single-file programs already, and it knows how to compile C source into an object file, so you don't have to train it to do that.
Use pattern matching:
PROGS = filename1 filename2 filename3
all: $(PROGS)
# cancel implicit program rule
%: %.c
%: %.o
$(CC) $(LDFLAGS) $^ -o $#
%.o: %.c
$(CC) $(OPT) $(CFLAGS) $^ -c -o $#
clean:
rm -f $(PROGS) *.o
.PHONY: all clean
FWIW,
HTH
'A Generic Makefile for Building Multiple main() Targets in $PWD'
Makefile to compile multiple c programs?

Resources