I'm new to using Makefile and I'm struggling to make it work correctly.
I want to compile my files to an executable .o file and then remove all the other .o files that were created in the process.
SRC = ./main.c \
./rush00.c \
./ft_putchar.c
OBJ = $(SRC:.c=.o)
CFLAGS += -Wall -Werror -Wextra
NAME = rushB
all:$(NAME)
$(NAME):$(OBJ)
cc -o $(NAME) $(OBJ)
clean:
rm -f $(OBJ)
fclean: clean
rm -f $(NAME)
re: fclean $(NAME)
.PHONY: all clean fclean re
Is there a way to make an executable file without creating main.o, rush00.o and ft_putchar.o?
Related
I'd like that my makefile stopped linking every time I call it if the .o file is already up-to-date.
Do you have any ideas about it?
Here is my makefile:
CC = gcc
CFLAGS = -Wall -Werror -Wextra
RM = rm -f
NAME = ft_display_file
SRCS = ft_display_file.c
OBJS = ${SRCS:.c=.o}
all: $(NAME)
${NAME}: ${OBJS}
clean:
${RM} ${OBJS}
fclean: clean
${RM} $(NAME)
re: fclean all
Thanx,
Fab
Here is my Makefile:
NAME = fillit
FLAGS = -Wall -Wextra -Werror
LIB_NAME = libft.a
LIB_DIR = ../libft/
LIB_PATH = $(LIB_DIR)$(LIB_NAME)
OBJ_DIR_NAME = objects
OBJ_DIR = $(OBJ_DIR_NAME)/
HEADER_DIR = ../libft
SRC = main.c
OBJ = $(SRC:.c=.o)
all :
mkdir -p $(OBJ_DIR_NAME)
$(MAKE) $(NAME)
$(NAME) : $(OBJ) $(LIB_PATH)
gcc -o $(NAME) $(addprefix $(OBJ_DIR), $(OBJ)) -L$(LIB_DIR) -lft
$(LIB_PATH) : $(LIB_PATH)
$(MAKE) -C $(LIB_DIR) --no-print-directory
%.o : %.c
gcc $(FLAGS) -I$(HEADER_DIR) -c $<
mv $# $(OBJ_DIR)
clean :
rm -f $(addprefix $(OBJ_DIR), $(OBJ))
rm -rvf $(OBJ_DIR_NAME)
fclean : clean
rm -f $(NAME)
rm -f $(addprefix $(LIB_DIR), $(LIB_NAME))
re: fclean
make
When i write $(LIB_PATH) : $(LIB_PATH) i'm expecting that my Makefile check if my lib is updated or exist and if that's not the case compile it (like objects and sources) but when i do make it only argue about circular rules and compile anyway my library.
Then, what should i write for when i do make, it enter in the $(LIB_PATH): only when my library hasn't been compiled yet?
This is a common problem with hierarchical Makefiles. You don't want to have to specify the library dependencies twice (i.e., once to know when to launch the sub-makefile, and again in the sub-makefile to actually build the target) so you just have to call the sub-makefile each time to let it determine if it needs to rebuild.
Try:
.PHONY: $(LIB_PATH)
$(LIB_PATH):
[tab] $(MAKE) -C $(LIB_PATH) --no-print-directory
This should cause make to run in the $(LIB_PATH) directory every time this makefile evaluates a target that depends on $(LIB_PATH).
.PHONY is meant for targets that don't really represent files, like clean. It just marks the target as 'stale' even if a file happens to exist with that name and is fresh.
This is my Makefile:
.PHONY : clean fclean re $(LIB_PATH)
NAME = fillit
FLAGS = -Wall -Wextra -Werror
LIB_NAME = libft.a
LIB_DIR = ../libft/
LIB_PATH = $(LIB_DIR)$(LIB_NAME)
OBJ_DIR_NAME = objects
OBJ_DIR = $(OBJ_DIR_NAME)/
HEADER_DIR = ../libft/
SRC = main.c func1.c
OBJ = $(SRC:.c=.o)
all :
mkdir -p $(OBJ_DIR_NAME)
$(MAKE) $(NAME)
$(NAME): $(OBJ_DIR)$(OBJ) $(LIB_PATH)
gcc -o $(NAME) $(addprefix $(OBJ_DIR), $(OBJ)) -L$(LIB_DIR) -lft -I$(HEADER_DIR)
$(LIB_PATH):
$(MAKE) -C $(LIB_DIR) --no-print-directory
$(OBJ_DIR)%.o : %.c
gcc $(FLAGS) -I $(HEADER_DIR) -c $<
-mv $(#F) $(OBJ_DIR)
clean :
-rm $(addprefix $(OBJ_DIR), $(OBJ))
-rm -rv $(OBJ_DIR_NAME)
fclean : clean
-rm $(NAME)
$(MAKE) -C $(LIB_DIR) fclean --no-print-directory
re: fclean
make
When i do make, i expect that the rule $(OBJ_DIR)%.o : %.c compiles the two objects (func1.c main.c) and move them to objects directory. But the rule only happens with the first source file written in SRC
compiles the two objects (reader.c main.c)
Did you mean func1.c instead of reader.c?
If that is the case, please check if the func1.c file is in the same directory as main.c. If it isn't in the same directory, you'll have to write another pattern rule. Something like this:
FUNC1_DIR = # The directory where your func1.c is located, maybe src/ or something alike
$(OBJ_DIR)%.o : $(FUNC1_DIR)%.c
gcc $(FLAGS) -I $(HEADER_DIR) -c $<
-mv $(#F) $(OBJ_DIR)
$(NAME): $(OBJ_DIR)$(OBJ) doesn't apply $(OBJDIR) to each item $(OBJ).
It literally just concatenates $(OBJDIR) onto the list. This is why only one instance of your pattern rule fires (only one .o has the path prefix that the pattern is trying to match).
Instead, use:
OBJ_WITH_PATH := $(foreach obj,$(OBJ),$(OBJ_DIR)$(obj))
Then update the dependency on your NAME rule to
$(NAME): $(OBJ_WITH_PATH) $(LIB_PATH)
As an aside, I find it is sometimes helpful to add rules like
.PHONY: DEBUG
DEBUG:
#echo MAKING SURE THIS WORKS: $(OBJ_DIR)$(OBJ)
#echo ALTERNATE: $(OBJ_WITH_PATH)
then you can run your DEBUG target:
$ make DEBUG
MAKING SURE THIS WORKS temp/a.o b.o
ALT temp/a.o temp/b.o
I have a problem that I can't seem to resolve. I'm trying with the -I flag to add my includes to the list of which the compiler will look at. Instead of directly looking in the /usr/include directory which contains all the standard library, it will look first in my include directory for header files. But it doesn't seem to find the files since a long list of this kind of error appears when I compile:
src/termcaps/termcapbis.c:13:10: fatal error: 'termcaps.h' file not found #include <termcaps.h>
(That is one example out of multiple errors that all say the same thing.)
So I'm wondering if there is something wrong with my Makefile or if I have to do something else for the compiler to understand where my header files are.
Here's my makefile:
NAME = 42sh
SRC_DIR = "src"
SRC_DIRS = $(shell find $(SRC_DIR) -type d -follow -print)
SRC_FILES = $(shell find $(SRC_DIRS) -type f -follow -print | grep "\.c")
OBJ_DIR = "obj"
OBJ_DIRS = $(SRC_DIRS:$(SRC_DIR)%=$(OBJ_DIR)%)
OBJ_FILES = $(SRC_FILES:$(SRC_DIR)%.c=$(OBJ_DIR)%.o)
FLAGS = -Wall -Wextra -Werror
INCLUDE = -Iinclude -Ilibft/include
LIB = -Llibft -lft -ltermcap
all: $(NAME)
$(NAME): $(OBJ_FILES)
make -C libft
gcc $(FLAGS) $^ $(LIB) -o $#
$(OBJ_DIR)%.o: $(SRC_DIR)%.c
#mkdir -p $(OBJ_DIRS) $(OBJ_DIR)
gcc $(FLAGS) $(INCLUDE) -o $# -c $<
clean:
#rm -rf $(OBJ_DIR)
#make fclean -C libft
fclean: clean
#rm -rf $(NAME)
#make fclean -C libft
re: fclean $(NAME)
.PHONY: all clean fclean re
Any suggestions?
I have the following make file. The problem is that even if there are no changes in the two .cpp files, it still run all the commands on prompt. Everything else is working fine.
all: hello1
hello1: make func
gcc hellomake.o hellofunc.o -o hello -I.
make: hellomake.c
gcc -c hellomake.c
func: hellofunc.c
gcc -c hellofunc.c
clean:
rm -rf *o hello
run:
./hello
Here is a sample Makefile that you can modifiy (especially CFLAGS section), and in won't relink
NAME = xxx
SRCS = xxx.c
OBJS = $(SRCS:.c=.o)
CC = gcc
RM = rm -rf
CFLAGS += -W -Wall -Wextra
CFLAGS += -O2
CFLAGS += -ansi -pedantic
CFLAGS += -D_FORTIFY_SOURCE=2 -D_GNU_SOURCE
all: $(NAME)
$(NAME): $(OBJS)
$(CC) $(OBJS) -o $(NAME)
clean:
$(RM) $(OBJS)
fclean: clean
$(RM) $(NAME)
re: fclean all
.PHONY: all clean fclean re
.PHONY allow to differentiate eventual file names and rule names
You need to replace the .c to .o in the targets as described below
make: hellomake.o
gcc -c hellomake.c
func: hellofunc.o
gcc -c hellofunc.c