How to properly create and use makefile - c

I'm getting started with makefiles and I'm having some problems.
I have one file which is fase_1.c that I want to compile and run.
I'm trying to make a simple makefile where I make and make clean.
This is what I tried:
OBJECTS = fase_1.o
CFLAGS = -Wall
NAME = makefile
build: $(OBJECTS)
cc $(CFLAGS) $(OBJECTS) -o $(NAME)
clean:
rm -f *.o
rm -f $(NAME)
I do make, and it creates fase_1.o and makefile. Then I run ./makefile (is there another way to do it without like make or make clean but to run it?). Then I type make clean, and it says that there's a missing separator and that the line is ignored and doesn't remove fase_1.o and makefile (what I want to do). Am I separating the lines right? Maybe it has something to do with tab or my editing but I can't find where.

Here's a rewrite. Call it Makefile, though, not makefile:
OBJECTS = fase_1.o
CFLAGS = -Wall
NAME = fase
$(NAME): $(OBJECTS)
cc $(CFLAGS) $(OBJECTS) -o $(NAME)
run : $(NAME)
./fase
.PHONY: clean
clean:
rm -f *.o
rm -f $(NAME)
There are fancier improvements that could be made, but it's probably best not to get bogged down at this stage. As a bonus, I have added .PHONY. This tells make that the target clean is a phony target; it doesn't actually create anything called clean.
You don't have to make run dependent on $(NAME), of course, but it makes sense in this particular context.

It looks like you are using GNU make. From the info page:
By default, when 'make' looks for the makefile, it tries the following
names, in order: 'GNUmakefile', 'makefile' and 'Makefile'.
Your executable is called makefile. When you run make, it tries to parse the executable as Makefile. Either rename the executable, or specify the makefile explicitly:
make -f Makefile clean

Related

Simplest C makefile using implicit rules

I know it is not optimal at all to rely on make's implicit rules but
my goal is to understand why they are not working in this case.
I want to write the simplest makefile one can write for a C project
without having to specify the sources.
I have tried to run make -d but the ouput is too big and verbose to
really be helpful.
I have written makefiles for some time and I believe I am familiar with how it
works. I am pretty sure I have managed to get implicit rules to work for me both
compiling and linking in the past but apparently I am forgetting something.
Here's what I have tried :
SRCS = $(wildcard *.c)
OBJS = ${SRCS:.c=.o}
NAME=exe
${NAME}: ${OBJS}
clean:
rm -rf *.o
fclean: clean
rm -rf ${NAME}
re: fclean ${NAME}
.PHONY: clean fclean re
It almost works but it doesn't link.
I am using gnu make version 4.3
Your Makefile doesn't execute the link step because there is only a very simple implicit rule for linking. From the documentation:
Linking a single object file
n is made automatically from n.o by running the C compiler to link the program. The precise recipe used is $(CC) $(LDFLAGS) n.o $(LOADLIBES) $(LDLIBS).
This rule does the right thing for a simple program with only one source file. It will also do the right thing if there are multiple object files (presumably coming from various other source files), one of which has a name matching that of the executable file. Thus,
x: y.o z.o
In other words, for your Makefile to work, NAME needs to match the basename of one of your object files.
For example, if I have your Makefile and a single source file named hello.c, I can run:
make NAME=hello
And see the result:
cc -c -o hello.o hello.c
cc hello.o -o hello

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.

'linker input file unused because linking not done' error when running make

I'm compiling C programs I made for a project.
Goals
Compiling get_next_line.c and get_next_line_utils.c.
Structure
I have 3 files, get_next_line.c, get_next_line_utils.c and get_next_line.h in my folder (excluding Makefile). Nothing more, nothing less.
Code
NAME = get_next_line
SRCS = get_next_line.c get_next_line_utils.c
OBJS = $(SRCS:.c=.o)
CC = gcc
CFLAGS = -Wall -Wextra -Werror
LIB_CRT = ar rcs
all: $(NAME)
$(NAME) : $(OBJS)
#$(LIB_CRT) $(NAME) $(OBJS)
%.o: %.c $(INCLUDE)
#$(CC) -c $(CFLAGS) -o $# $<
clean:
#rm -f $(OBJS) a.out
fclean: clean
#rm -f $(NAME)
re : fclean all
Error Message
linker input file unused because linking not done. I get this error several times.
I keep on running on this error when I run make. I followed another Makefile I had for another project, to no avail. I also read this article and that one too but they aren't relevant to my issue.
Any input appreciated.
Your makefile appears to be aimed at building a program named "get_next_line", but this is not altogether clear because what you are actually building is a static archive file with that (unconventional for an archive) name. That's what the ar utility does. With the gcc toolchain and many others, one would normally use the same front end (gcc in this case) for both compiling and linking. That is,
$(NAME) : $(OBJS)
$(CC) -o $(NAME) $(OBJS)
... or, a bit DRYer ...
$(NAME) : $(OBJS)
$(CC) -o $# $^
It is not clear why you are getting the specific message you report. It looks like a message from the linker, ld, but I see no reason in the makefile presented to think that the linker would ever run. As such, I am inclined to suppose that the message is associated with something altogether different. Possibly you are running make in a different working directory, and therefore using a different makefile. Or perhaps it is associated with some other command than make itself. Or maybe you have an influential variable set in your environment that alters the meaning of your makefile. Maybe you get that message when you try to run the archive as if it were a program (though that's not what I would expect to happen in that case).

How to build multiple targets from one makefile

I'm trying to parameterize my makefile targets. Currently, it has a
TARGET = main
declaration near the top. It derives the SRC list from that as well as does lots of other things.
I've changed my C code though, so that I have multiple different top level .c files to basically get variant builds. So what I want to be able to do is basically do
make target1
or
make target2
And vary what TARGET is set to in the makefile. I'm confused how to accomplish this. I thought I might add something like
target1: all
TARGET=target1
This didn't seem to work too well at all though. Is there a general pattern for how one does this?
I would suggest simply spelling out your targets as separate targets in the makefile:
all: target1 target2
OTHER_OBJS = misca.o miscb.o miscc.o
target1: target1.o $(OTHER_OBJS)
target2: target2.o $(OTHER_OBJS)
Then make, make target1, make target2, and so on will all do what you want.
You say your makefile "derives the SRC list from [$(TARGET)]" in some presumably high-tech way, but it might be interesting to try explicitly listing the object files in a low-tech way instead, as above. Using different make targets is arguably Make's general pattern for producing different results.
Parameterized variable names and target-specific variables may do what you want, as the value of a target-specific variable is normally "inherited" by the prereqs of that target (assuming you are using GNU make):
target1_SRC=123 456
target2_SRC=abc def
target1: TARGET=target1
target2: TARGET=target2
target1: all
target2: all
all: ; #echo $($(TARGET)_SRC)
Then you can run make target1 or make target2, for example:
$ make target1
123 456
$ make target2
abc def
Well... Using pmake we can do this: (If use gmake we can replace $(.THINGS) for equivalanet $# $< and so...
.PHONY: clean run
PROGRAMS = progrname_one progrname_two... and so
all: $(PROGRAMS)
$(PROGRAMS): $(PROGRAM=$(.TARGET))
CC = clang -I.
CFLAGS = -O0 -g -std=gnu11
OBJS =
LIBS =
CPATH = .
$(PROGRAM): $(PROGRAM).c $(OBJS)
$(CC) $(CFLAGS) -o $(.TARGET) $(.IMPSRC) $(OBJS) $(LIBS)
$(PROGRAM).o: $(PROGRAM).c
clean:
rm -f *~
rm -f *.core
rm -f $(PROGRAMS) $(PROGRAMS).o
run:
./$(PROGRAM)
dbg:
lldb ./$(PROGRAM)

How to properly make my makefile to compile and run?

The question is probably not the best one to describe my issue but I couldn't think of a better one. My makefile goes like this:
PROGRAM_NAME = prog
OBJECT_FILES = $(PROGRAM_NAME).o
CFLAGS = -O2 -Wall -g
$(PROGRAM_NAME) : $(OBJECT_FILES)
gcc $(CFLAGS) -o $# $(OBJECT_FILES)
$(PROGRAM_NAME).o : $(PROGRAM_NAME).c data.h
gcc $(CFLAGS) -c $<
clean :
$(RM) $(PROGRAM_NAME)
$(RM) $(OBJECT_FILES)
$(RM) *~ *.bak
run :
#$(MAKE) && ./$(PROGRAM_NAME) $(ARGS)
When I want to compile and run I just do "make run". The issue with this is that my program handles the signal produced by Ctrl+Z and if I start my program with "make run", the signal will be sent to "make run" and not my program itself.
Basically, calling "make run" is not the same thing as calling directly "make && ./prog" because in the first case, "make run" will not terminate unless "prog" terminates first.
Is there a way around this?
You can simplify your 'run' target by having it depend on whether your program is up to date, and then simply run the program:
run: ${PROGRAM_NAME}
./${PROGRAM} ${ARGS}
There's not much point in running make when you're already running make - at least, not in this context. Maybe for recursive operations (in different directories), but see 'Recursive Make Considered Harmful'.
Also, your makefile should normally provide a target 'all' and it should normally the first and therefore default target.
Running from the makefile is a bit unusual. Are you, perhaps, trying to duplicate the "Compile and Run" Menu item that some IDE provide? Make is not well equipped to do that.
All the stuff that happens in the target commands happens in sub-processes that are not attached directly to the terminal, which is why make receives your key stroke.
Another thing to look at: usually the object-file to executable stage (linking) uses a different set of flags (LDFLAGS and LIBS) then the compile stage. In this simple example you can get away with it, but if you copy this makefile for use in a more complicated case you'll run into trouble.
If you're going to build and run over and over, You can use the history command to help with this:
# Run this once
make && ./foo
# Repeat last command
!!
As dmckee's answer said, make(1) is making something, not for compile-and-run.
Of course, nothing stops you for creating a shell alias make-run which does the intended 'make && ./prog args'.
You can try like this:
APP = olupxtest
SRCS = $(wildcard *.cpp)
OBJS = $(SRCS:.cpp=.o)
CXXFLAGS = -g -fPIC -c
LDFLAGS =
LIBS =
.PHONY: all clean
all: clean $(APP) run
$(APP): $(OBJS)
$(CXX) $(LDFLAGS) $^ $(LIBS) -o $#
clean:
$(RM) $(OBJS) $(APP)
run: ${APP}
./${APP} ${ARGS}
Here you have calling multiple rules for target: all: clean $(APP) run

Resources