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
Related
I'm trying to create a generic Makefile to use with most of my projects. It should work as follows: only rebuild and link those .o files whose .c or .h dependency has changed. The .o and .d files are stored in a separate directory called 'build'.
With the help of the official GNU Make manual and some googling I've managed to achieve the desired behavior except for one thing: when I run make re I get the error:
Assembler messages: Fatal error: can't create build/ft_build_buffer.o: No such file or directory — the reason for this is that the 'build' directory only gets created whenever the .d files are generated, but for some reason the re rule simply skips this step and goes on to compile .o files straight away! Note: if I run make clean && make fclean && make all (which should be the exact same thing) everything works fine.
A few other things: I've tried using the -MMD option to generate dependencies on the fly but on my machine that causes the .d files to only contain .c dependencies. Of course I could just make all .c files depend on all .h files but that seems like a very sloppy solution.
Feel free to share any other advice/improvements that will make this file more clean and readable, thanks! :)
# Define the C compiler to use.
CC := gcc
# Define any compile-time flags.
CFLAGS := -I./include -Wall -Wextra -Werror -g
#CFLAGS := -I./include -march=native -O2 -pipe
# Define the executable file.
BIN := ft_hexdump
# Define build directory.
BUILD_DIR := build
# Define source files directory.
SRC_DIR := src
# Define the C source files.
SRCS := $(wildcard $(SRC_DIR)/*.c)
# Define the C object files.
OBJS := $(SRCS:$(SRC_DIR)/%.c=$(BUILD_DIR)/%.o)
# Define the prerequisite files.
DEPS := $(OBJS:%.o=%.d)
.PHONY: all clean fclean re
.DELETE_ON_ERROR:
all: $(BIN)
-include $(DEPS)
$(BIN): $(OBJS)
$(CC) $(CFLAGS) $^ -o $#
$(BUILD_DIR)/%.o: $(BUILD_DIR)/%.d
$(CC) $(CFLAGS) -c $(SRC_DIR)/$*.c -o $#
$(BUILD_DIR)/%.d: $(SRC_DIR)/%.c
#mkdir -p $(#D)
#set -e; rm -f $#; \
$(CC) $(CFLAGS) $(INCLUDE) -MM $< > $#.$$$$; \
sed 's,\($*\)\.o[ :]*,\1.o $# : ,g' < $#.$$$$ > $#; \
rm -f $#.$$$$
clean:
-rm -rf $(BUILD_DIR)
fclean: clean
-rm -f $(BIN)
re: fclean all
Here is the modified working version as suggested by #M.M
# Define the C compiler to use.
CC := gcc
# Define any compile-time flags.
CFLAGS := -I./include -Wall -Wextra -Werror -g
#CFLAGS := -I./include -march=native -O2 -pipe
# Define the executable file.
BIN := ft_hexdump
# Define build directory.
BUILD_DIR := build
# Define source files directory.
SRC_DIR := src
# Define the C source files.
SRCS := $(wildcard $(SRC_DIR)/*.c)
# Define the C object files.
OBJS := $(SRCS:$(SRC_DIR)/%.c=$(BUILD_DIR)/%.o)
# Define the prerequisite files.
DEPS := $(OBJS:%.o=%.d)
.PHONY: all clean fclean re
.DELETE_ON_ERROR:
all: $(BIN)
-include $(DEPS)
$(BIN): $(OBJS)
$(CC) $(CFLAGS) $^ -o $#
$(BUILD_DIR)/%.o: $(SRC_DIR)/%.c
#mkdir -p $(#D)
$(CC) $(CFLAGS) -MMD -c $(SRC_DIR)/$*.c -o $#
clean:
-rm -rf $(BUILD_DIR)
fclean: clean
-rm -f $(BIN)
re:
$(MAKE) fclean
$(MAKE) all
I've been trying for some time to separate the source files of my project from the generated object files.
Indeed, I would like my project to be structured this way:
obj/
main.o
src1.o
[...]
src/
main.c
src1.c
[...]
Makefile
The Makefile I currently have is as follows:
NAME = a.out
OBJ_DIR = "obj"
SRC_DIR = "src"
MAIN_SRC = main.c
PROJ_SRC = src1.c \
src2.c \
src3.c
MAIN_OBJ = $(MAIN_SRC:%.c=%.o)
PROJ_OBJ = $(PROJ_SRC:%.c=%.o)
CC = gcc
RM = rm -rf
$(NAME): $(MAIN_OBJ) $(PROJ_OBJ)
$(CC) $(MAIN_OBJ) $(PROJ_OBJ) -o $(NAME)
all: $(NAME)
clean:
$(RM) $(MAIN_OBJ) $(PROJ_OBJ)
fclean: clean
$(RM) $(NAME)
I tried to use pattern rules, without success.
MAIN_OBJ = $(MAIN_SRC:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o)
PROJ_OBJ = $(PROJ_SRC:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o)
[...]
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
$(CC) $(CFLAGS) -c $< -o $#
Does anyone have a solution to my problem?
MAIN_SRC and PROJ_OBJ do not have directory prefix, so that expressions
$(MAIN_SRC:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o)
$(PROJ_SRC:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o)
do not replace anything.
Fix:
MAIN_OBJ := $(MAIN_SRC:%.c=$(OBJ_DIR)/%.o)
PROJ_OBJ := $(PROJ_SRC:%.c=$(OBJ_DIR)/%.o)
And then your pattern rule should work.
You may like to have make create that $(OBJ_DIR) for you:
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c | $(OBJ_DIR)
$(CC) $(CFLAGS) -c -o $# $<
$(OBJ_DIR) :
mkdir -p $#
A more advanced example for you with automatic header dependency generation.
bro!
If your project "main" 's architecture is just liking this:
main
|
|__Makefile
|__obj
|__src
|__main.c
|__src1.c
|__src2.c
[...]
Just add this to your "Makefile" to store your object out of source files directory:
# Object files
# String substituion for every C/C++ file
# e.g: ./src/src1.cpp turns into ./obj/src1.o
OBJS := $(patsubst %.c, ${OBJ_DIR}/%.o, $(notdir $(SRC_DIR)))
And just add this to your "Makefile" to compile:
# Compile: Generate object files from source files
# $# := {NAME}
# $< := THE first file
# $^ all the dependency
# C Sources
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
$(CC) $(C_FLAGS) -c $< -o $#
END!
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.
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)
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?