How to properly make my makefile to compile and run? - c

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

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.

'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 properly create and use makefile

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

C programming - picking up the machine name, username at compile time

Are there a set of defines that are created at compile time, that I can use to populate a printk statement with information about where and who last build a kernel driver? I know that there are predefined C macros, and I was hoping to find something in there that is dynamically set as the compile is kicked off, but there doesn't appear to be.
This would be specific to GCC as well. Thanks in advance.
To expand on my comment; you could just use the shell function of make, in case you use make.
It could look something like this in the makefile:
USER=$(shell whoami)
HOST=$(shell hostname)
CXX=gcc
CXX_DEFINES=-D__BUILD_USER=\"$(USER)\" -D__BUILD_HOST=\"$(HOST)\"
CXX_FLAGS=-c -Wall -Wextra $(CXX_DEFINES)
CXX_LFLAGS=
SOURCES=main.c
OBJECTS=$(SOURCES:.c=.o)
EXEC=hostusertest
all: $(SOURCES) $(EXEC)
clean:
rm $(OBJECTS)
rm $(EXEC)
$(EXEC): $(OBJECTS)
$(CXX) -o $# $(OBJECTS) $(CXX_LFLAGS)
%.o: %.c
$(CXX) $(CXX_FLAGS) $<
Basically just use the standard shell commands to gather the information and create a variable in the makefile that keeps that info after using the shell function $(shell ...) to get it.
Then just set it via -D NAME=VALUE but don't forget to add escaped qoutation marks.

Makefile dependencies on multiple files

I have created a Makefile for unit tests which uses GCC with arguments to create profiling files (gcno) during compiling. Here's a similified part of it where compiling and linking takes place:
UTEXE = $(UTOBJSDIR)\$(UTUNIT).exe
UTOBJS = $(UTUUTSRC:.c=.o) $(UTUTSRC:.c=.o) $(UTCSRC:.c=.o)
UTOBJSFULL = $(addprefix $(UTOBJSDIR)\,$(UTOBJS))
UTOBJSGCNO = $(addprefix $(UTOBJSDIR)\,$(UTOBJS:.o=.gcno))
$(UTOBJS): %.o: %.c $(UTMAKEDEP)
$(call report,Compiling $(*F).c)
$(MKDEP) $(MKDFLAGS) -o.o -f$(UTOBJSDIR)\$(*F).dep $(subst /,\,$<)
$(CC) -c $(CFLAGS) $(subst /,\,$<) -o $(UTOBJSDIR)/$#
$(UTOBJSGCNO): $(UTOBJS) $(UTMAKEDEP)
utbuild: $(UTEXE) $(UTOBJSGCNO) $(UTOBJS) $(UTMAKEDEP)
$(UTEXE): $(UTOBJSGCNO) $(UTOBJS) $(UTMAKEDEP)
$(call report,Linking to $(UTUNIT).exe)
$(LINK) $(UTOBJSFULL) $(LNKFLAGS) -o $(UTEXE)
It compiles all the object and profile files and links together a binary. However when i delete some profile file (gcno) and call "utbuild" again it won't re-compile to restore the .gcno file. It tries to do linking again because gcno is a prequisite to it, but it wont do the compiling.
I don't know how to name this case so couldn't find solution from internet. Basically one recipe creates two files and i don't know how to write the rule that re-run's recipe even when only one file needs to re-created.
I would appreciate some links or hints.
thanks for all the comments. I've tried no-op ";" and ":=" with same outcome.
I think i need to take one step back and explain why i asked this question. It's not just about deleting or not-deleting gcno files manually, it's about general understanding how to write such a Makefile which restores any missing or out-of-date file. My Makefile has similar cases in few places and it's using parallel build so when some file goes missing it gives lot of weird errors. Usually it's solved by "clean" and "all", but i'd like the Makefile to be perfect and handle the missing file issues nicely.
As the example above is not so clear without all the rest of the Makefile then i made a new simple test.
hello.c
#include <stdio.h>
int main()
{
printf("Hello world\n");
}
Makefile
CCDIR = C:\tools\MinGW
CCBINDIR = $(CCDIR)\bin
CCINCDIR = $(CCDIR)\include;$(CCDIR)\lib\gcc\mingw32\4.8.1\include
CCLIBDIR = $(CCDIR)\lib;$(CCDIR)\lib\gcc\mingw32\4.8.1
# Overcome "missing dll file" messages on Windows
CC = set PATH=%PATH%;$(CCBINDIR)& $(CCBINDIR)\gcc.exe
LINK = set PATH=%PATH%;$(CCBINDIR)& $(CCBINDIR)\gcc.exe
# Compile and link for code coverage
CFLAGS = -fprofile-arcs -ftest-coverage -g3 -O0 $(addprefix -I,$(CCINCDIR))
LNKFLAGS = -fprofile-arcs -ftest-coverage -static -static-libgcc $(addprefix -L,$(CCLIBDIR))
OBJECTS = hello.o
EXE = hello.exe
$(OBJECTS): %.o: %.c
$(CC) -c $(CFLAGS) $(subst /,\,$<) -o $#
$(EXE): $(OBJECTS)
$(LINK) $(OBJECTS) $(LNKFLAGS) -o $(EXE)
build: $(EXE)
"make build" creates following files:
hello.o
hello.gcno
hello.exe
Now if i delete the "hello.gcno" and run build again it tells me:
mingw32-make: Nothing to be done for 'build'.
The goal is to update Makefile so that the make re-creates the "hello.gcno". It would probably re-create "hello.o" and "hello.exe" also during that process but that's not a problem.
Edit:
Just to be clear: in real Makefile i really-really need the .gcno files. It's not just an additional information or something which to avoid or do optionally. The Makefile builds the unit test executables, runs them and executes gcov to generate code coverage information and gcovr creates a report of all the .gcov files. If .gcno file is missing it won't work. Also - as it's parallel build then dependencies shall be absolutely correct to avoid some process starting earlier and it's tricky because coverage report has dependencies coming from two "branches" - .gcno files from compile stage and .gcda files from execute stage. So that's why i need it to be correct.
your only option here is this :
(if you can change the rule)
$(EXE): $(OBJECTS)
$(LINK) $(OBJECTS) $(LNKFLAGS) -o $(EXE)
to this:
%.exe %.gnco: $(OBJECTS)
$(LINK) $(OBJECTS) $(LNKFLAGS) -o $(EXE)
$(GENERATE_GNCO) $<
Here is a very simple solution of one thing dependig on two other things
compile:./src/main.c ./src/error.c
gcc ./src/error.c ./src/main.c -o ./exe/calc
run : ./exe/calc
./exe/calc
The correct answer in my opinion, is, don't delete any .gcno files by themselves. If you have to "clean", use make clean, but don't just go about deleting files.
The "build" is a state machine, with all the files constituting a "state". Don't corrupt the state!
Some people say, one should be able to delete arbitrary files and the build should recover. My answer is, what about if you corrupt some .o file by hand, say, add some 0's and 1's, making it unusable (thank you user3629249 for pointing that needs to be clarified, that I am talking about corruption, not intentional editing). Should the build also recover from that? Obviously no - no build system in the world will recover if you touch the .o file this way. Then why allow deleting a file, but not allow modifying it?? Where do you draw the line?
Simply put, any corruption should not be allowed. Use make clean only, or better yet, write your Makefile properly, so you never need to clean period.
The whole Makefile has a number of problems, here is how it should look like (I am assuming this is on Windows/DOS):
.SUFFIXES:
UTEXE := $(UTOBJSDIR)\$(UTUNIT).exe
UTOBJSFULL := $(addprefix $(UTOBJSDIR)\,$(subst /,\, $(UTUUTSRC:.c=.o) $(UTUTSRC:.c=.o) $(UTCSRC:.c=.o)))
UTOBJSGCNO := $(UTOBJSFULL:.o=.gcno)
.PHONY: utbuild all
all: utbuild
utbuild: $(UTEXE) $(UTOBJSGCNO) $(UTMAKEDEP)
$(UTOBJSGCNO): %.gcno: %.o $(UTMAKEDEP) ;
.SECONDARY: %\.
%\.: Makefile
mkdir $*
.SECONDEXPANSION:
$(UTOBJSFULL): $(UTOBJSDIR)\%.o: %.c $(UTMAKEDEP) | $$(#D)\.
$(call report,Compiling $<)
$(MKDEP) $(MKDFLAGS) -o.o -f$(UTOBJSDIR)\$(*F).dep $<
$(CC) -c $(CFLAGS) $< -o $#
$(UTEXE): $(UTOBJSFULL) $(UTMAKEDEP) | $$(#D)\.
$(call report,Linking to $(#F))
$(LINK) $(UTOBJSFULL) $(LNKFLAGS) -o $#

Resources