`makefile` not working as expected - c

How can I have it so that when I run make that:
prog.s is created then prog is created if prog.s and prog does not exist
prog.s is created if prog.s is newer than prog.c (eg. after manually modifying prog.s)
prog.s then prog is created if prog.c is newer than prog
In other words, have make create the files it needs to build prog, if the dependencies have been modified
My current makefile:
CC = gcc
CFLAGS =
TARGET = prog
all: $(TARGET).s $(TARGET).c
$(TARGET).c: $(TARGET).s
$(CC) $(CFLAGS) $(TARGET).s -o $(TARGET)
$(TARGET).s:
$(CC) $(CFLAGS) -S -o $(TARGET).s $(TARGET).c
clean:
$(RM) $(TARGET)
$(RM) $(TARGET).s
It works if I have:
only prog.c
manually modified prog.s
but does not work if I have manually modified prog.c
(make: Nothing to be done for 'all'.)

You define your target: source in the reversed order. For instance, your assembly code depends on your C code, you must write:
$(TARGET).s: $(TARGET).c
however, you have written (wrong order)
$(TARGET).c: $(TARGET).s
Here is the version with the right order for "target: sources" :
CC = gcc
CFLAGS =
TARGET = prog
all: $(TARGET)
$(TARGET): $(TARGET).s
$(CC) $(CFLAGS) $(TARGET).s -o $(TARGET)
$(TARGET).s: $(TARGET).c
$(CC) $(CFLAGS) -S -o $(TARGET).s $(TARGET).c
clean:
$(RM) $(TARGET)
$(RM) $(TARGET).s

Related

How to explicitly link library path via makefile

I installed a real-time library libre from brew install libre in my macOS. It is located in the directory /usr/local/Cellar/libre/0.5.7. I am trying to explicitly add this path in Makefile so I declare RT_LIBS_PATH=-L/usr/local/Cellar/libre/0.5.7. The entire makefile looks like this:
TARGET = run
LIBS = -O2 -lm
CC = gcc-7
CFLAGS = -fopenmp
RT_LIBS_PATH=-L/usr/local/Cellar/libre/0.5.7/lib
.PHONY: default all clean
all: $(TARGET)
OBJECTS = $(patsubst %.c, %.o, $(wildcard *.c))
HEADERS = $(wildcard *.h)
%.o: %.c $(HEADERS)
#$(CC) $(CFLAGS) $(RT_LIBS_PATH) -c $< -o $#
.PRECIOUS: $(TARGET) $(OBJECTS)
$(TARGET): $(OBJECTS)
#$(CC) $(OBJECTS) $(CFLAGS) $(LIBS) -o $#
clean:
-rm -f *.o
-rm -f $(TARGET)
However, it seems makefile does not recognize the libre, thus I assume I use RT_LIBS_PATH=-L/usr/local/Cellar/libre/0.5.7/lib in a wrong way. Kindly, is there something wrong in this way?
You have to specified library path when you are creating .o, you have to specify it when link all objs into executable
$(TARGET): $(OBJECTS)
#$(CC) $(OBJECTS) $(CFLAGS) $(RT_LIBS_PATH) $(LIBS) -o $#

How to create make file for only object and header file?

I'm performing blackbox testing using a set.h interface where I have no access to set.c, I've been provided with the object file set.o and I'm required to write a bunch of tests in a main.c file for the set. How do I create a makefile that would include set.o, set.h and main.c?
**I already have the set.o file so I don't have to regenerate it using set.c
I'm confused because I only know how to do this using the complete files.
Here's my template
CC = clang
CFLAGS = -g -Wall
PROG = example
HDRS = set.h
SRCS = main.c
OBJDIR = object
OBJS = $(OBJDIR)/main.o $(OBJDIR)/set.o
# compiling rules
$(PROG): $(OBJS) $(OBJDIR)
$(CC) $(CFLAGS) $(OBJS) -o $(PROG)
$(OBJDIR)/set.o: set.h $(HDRS) $(OBJDIR)
$(CC) $(CFLAGS) -c set.h -o $(OBJDIR)/set.o
$(OBJDIR)/main.o: main.c $(HDRS) $(OBJDIR)
$(CC) $(CFLAGS) -c main.c -o $(OBJDIR)/main.o
$(OBJDIR):
mkdir $(OBJDIR)
clean:
rm -f $(PROG) $(OBJS)
If you already have the set.o file there is no need to create a rule for it, just use it. Also note I got rid of the mkdir because if you already have a set.o, it should already be in objects/ right?
CC = clang
CFLAGS = -g -Wall
PROG = example
HDRS = set.h
SRCS = main.c
OBJDIR = object
OBJS = $(OBJDIR)/main.o
# compiling rules
$(PROG): $(OBJS)
$(CC) $(CFLAGS) $(OBJS) $(OBJDIR)/set.o -o $(PROG)
$(OBJDIR)/main.o: main.c $(HDRS)
$(CC) $(CFLAGS) -c main.c -o $(OBJDIR)/main.o
clean:
rm -f $(PROG) $(OBJS)

Makefile relink error

I am trying to get this makefile relink and not recompile unessecarily files that aren't modified. The "libft" is my library and doesnt have any errors. The error that I am having when doing
make
is :
make: *** No rule to make target `main.o', needed by `ft_printf'. Stop.
My makefile is:
NAME = ft_printf
SRC = main.c\
ft_printf.c\
parser_main.c\
utils.c\
debug_funcs.c
OBJ = $(SRC:.c=.o)
SRC_PATH = srcs/
SRC_POS = $(addprefix $(SRC_PATH),$(SRC))
INC = -I includes
LIBFT = libft/libft.a
CC = gcc
FLAGS = -Wall -Wextra -Werror
all: $(NAME)
$(NAME): $(OBJ)
$(CC) $(FLAGS) $(OBJ) -o $(NAME) $(LIBFT)
%.o: %.c
$(CC) -o $# -c $< $(FLAGS)
$(LIBFT):
make -C ./libft/
clean:
rm -f $(OBJ)
make clean -C ./libft/
fclean: clean
rm -f $(NAME)
make fclean -C ./libft/
re: fclean all
Any idea ? I can't figure it out and i think it's because %.o:%.c isn't called
Given the existence of these variables:
SRC_PATH = srcs/
SRC_POS = $(addprefix $(SRC_PATH),$(SRC))
I'm guessing that your source files actually live in srcs/ whereas you're building your object files in . So this pattern rule:
%.o: %.c
when trying to match main.o won't find a main.c since that file really is srcs/main.c. Since that pattern doesn't match, the rule itself isn't considered, and since no other rule is found, you get an error.
Instead, try:
%.o : $(SRC_PATH)/%.c
$(CC) -o $# -c $< $(FLAGS)

make: *** No rule to make target `gcc', needed by `libmy.so'. Stop

I would like to compile .c files to a .so (shared library).
And I don't understand why, I have that makefile that makes me an error:
LIB = libmy.so
SRC = lib.c
CC = gcc
OBJ = $(CC) -c -fPIC $(SRC)
all: $(LIB)
re: fclean all
$(LIB): $(OBJ)
$(CC) -shared -fPIC $(OBJ) -o $(LIB)
clean:
$(RM) $(OBJ)
fclean: clean
$(RM) $(LIB)
Thanks in advance for helping.
The problem is in the following line:
$(LIB): $(OBJ)
When expanded this becomes:
libmy.so : gcc -c -fPIC lib.c
Hence the error.
What you probably wanted was :
OBJ = lib.o
To save you having to manually convert all .c source files to .o you can use a rule like this instead of OBJ = lib.o:
OBJ = $(SRC:%.c=%.o)
This creates a variable OBJ containing a list of all the files in SRC with any .c extension changed to .o. eg. If we had SRC = foo.c bar.c then the rule above would automatically expand to:
OBJ = foo.o bar.o
$(LIB): $(OBJ)
expands to
libmy.so: gcc -c -fPIC $(SRC)
ie you put your recipe into the depency list, and make rightfully complains.
Personally, I'd write the makefile like this:
CC := gcc
RM := rm -f
LIB := libmy.so
OBJ := lib.o
GARBAGE := $(OBJ)
.PHONY: all clean realclean
all: $(LIB)
$(LIB): LDFLAGS += -shared
$(LIB): $(OBJ)
$(CC) $(LDFLAGS) -o $# $<
$(OBJ): CFLAGS += -fPIC
$(OBJ): %.o : %.c
$(CC) $(CFLAGS) -c -o $# $<
realclean: GARBAGE += $(LIB)
clean realclean:
$(RM) $(GARBAGE)
Note that your original version did not contain a rule to make $(OBJ). If you wanted to use the implicit one, you would need to add -fPIC to CFLAGS.
That works :
LIB = libmy.so
SRC = lib.c
CC = gcc
OBJ = $(SRC:.c=.o)
all: $(LIB)
re: fclean all
$(LIB):
$(CC) -c -fPIC $(SRC)
$(CC) -shared -fPIC $(SRC) -o $(NAME)
clean:
$(RM) $(OBJ)
fclean: clean
$(RM) $(LIB)
I just need OBJ = $(SRC:.c=.o) in fclean

Makefile, Compiling and Linking

I have a question regarding compiling and linking in Makefile (and perhaps in general).
I have a server.c file which consists of the main program which has a main() function. server.c includes rio.c. I have a module called rio which consists of rio.c and rio.h. It has no main() function.
I have two questions, how to actually write the Makefile, and the best practice for doing such a thing.
Q1: How to write the Makefile
I have the following Makefile:
CC = gcc
CFLAGS = -Wall -Werror -Wmissing-prototypes
OBJS = server.o rio.o
all: $(OBJS)
$(CC) $(CFLAGS) $(OBJS) -o sysstatd
server.o: server.c
$(CC) $(CFLAGS) -c server.c
rio.o: rio.c rio.h
$(CC) $(CFLAGS) -c rio.c
clean:
rm -f *~ *.o sysstatd
I am having linking issues with this. It says that I have multiple definitions of all the functions used in C. I'm not sure how this is possible since server.c is compiled with the -c flag so nothing is actually linked. It should know that some functions exist but not actually link them until the all rule compiles both object files together and produces a single object file which has everything linked.
What is the issue here?
Q2: Best practice
Since I have a module and then another file which contains the main program, should I compile the main program, server.c, as a separate module and then compile both together in all, or compile server.c in all and add the rio.o module there? Note that this still produces the same linking problem I have above so I'm pretty sure I have my issue lies somewhere else.
You should revise the structure a little:
CC = gcc
CFLAGS = -Wall -Werror -Wmissing-prototypes
OBJS = server.o rio.o
all: sysstatd
sysstatd: $(OBJS)
$(CC) $(CFLAGS) $(OBJS) -o sysstatd
server.o: server.c
$(CC) $(CFLAGS) -c server.c
rio.o: rio.c rio.h
$(CC) $(CFLAGS) -c rio.c
clean:
rm -f *~ *.o sysstatd
The difference is that the phoney rule all depends on sysstatd being up to date, and sysstatd is up to date when it is up to date w.r.t the object files.
Now it is just rather verbose, writing the compilation actions explicitly. It would be sufficient to use:
CC = gcc
CFLAGS = -Wall -Werror -Wmissing-prototypes
OBJS = server.o rio.o
all: sysstatd
sysstatd: $(OBJS)
$(CC) $(CFLAGS) $(OBJS) -o sysstatd
server.o: server.c
rio.o: rio.c rio.h
clean:
rm -f *~ *.o sysstatd
You could also debate: does server.c not use rio.h? If it does, the dependency should be listed. If not, why does rio.h exist? make will assume that server.o depends on server.c, so you don't have to specify that (but it won't make assumptions about the headers). You could also use a macro to prevent repetition of the program name:
CC = gcc
CFLAGS = -Wall -Werror -Wmissing-prototypes
OBJS = server.o rio.o
PROG = sysstatd
all: $(PROG)
$(PROG): $(OBJS)
$(CC) $(CFLAGS) $(OBJS) -o $#
server.o: rio.h
rio.o: rio.h
clean:
rm -f *~ *.o $(PROG) core a.out
If you needed other libraries, then you might use:
CC = gcc
CFLAGS = -Wall -Werror -Wmissing-prototypes
OBJS = server.o rio.o
PROG = sysstatd
LOCALLIBDIR = /usr/local/lib
LDFLAGS = -L$(LOCALLIBDIR)
LDLIBS = -lone -ltwo
all: $(PROG)
$(PROG): $(OBJS)
$(CC) $(CFLAGS) $(OBJS) -o $# $(LDFLAGS) $(LDLIBS)
server.o: rio.h
rio.o: rio.h
clean:
rm -f *~ *.o $(PROG) core a.out

Resources