Search Icon Icon to open search Makefile
GNU build thingie for C language. #todo one template to rule them all.
# Useful# NotesThere are
implicit variables and rules, use make -p -f /dev/null
to print them. For compiling C++ use CXX
instead of CC
, CXXFLAGS
instead of CFLAGS
.
Suffix rules
ignore prerequisites. So you can’t write something like:
1
2
.c.o : $( HEADER )
<your compilation steps>
But it seems like you can do this instead:
1
2
%.o : %.c $( HEADER )
<your compilation steps>
There’s also a thing called “.d files”, which… Like an intermediate file format for Make, I guess?
what is .d file after building with make - Stack Overflow
# basename
functionIt’s not like /usr/bin/basename
. It takes a path and strips away file extention. So foo/bar.txt
becomes foo/bar
. Use $(notdir foo/bar.txt)
to get bar.txt
. Yes, this is fucked up.
# Change file extensionsUse $(SRC:.c=.o)
syntax. SRC
is a list of files, separated by space.How to change the extension of each file in a list with multiple extensions in GNU make?
# vpathTell make
where exactly to search for files. Probably archaic, like many things in Make.
# Examples# fract-ol-MMD -MP
so that the compiler creates .d
files. They’re needed for automatic header dependency generation. On the last line we include them in our Makefile.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
NAME := fract-ol
SRC_DIR := src
OBJ_DIR := obj
LIB_DIR := lib
LIBFT_DIR := libft
MLX_DIR := minilibx-linux
LIBFT := $( LIB_DIR) /libft.a
LIBMLX := $( LIB_DIR) /libmlx.a
SRC_FILES := complex.c float_parser.c graphics_utils.c julia.c keyboard.c \
main.c mandelbrot.c mouse.c ship.c
SRC := $( addprefix $( SRC_DIR) /, $( SRC_FILES))
OBJ := $( SRC:$( SRC_DIR) /%.c= $( OBJ_DIR) /%.o)
CC := cc
CPPFLAGS := -I include -I $( LIBFT_DIR) -I $( MLX_DIR) -MMD -MP
CFLAGS := -O3 -Wall -Werror -Wextra
LDFLAGS := -L$( LIB_DIR)
LDLIBS := -lft -lmlx -lXext -lX11 -lm -lz
.PHONY : all bonus clean fclean re
all : $( NAME )
bonus : $( NAME )
$(LIBFT) : $( LIB_DIR )
$( MAKE) --directory= $( LIBFT_DIR)
cp $( LIBFT_DIR) /libft.a $( LIB_DIR)
$(LIBMLX) : $( LIB_DIR )
$( MAKE) --directory= $( MLX_DIR)
cp $( MLX_DIR) /libmlx.a $( LIB_DIR)
$(NAME) : $( OBJ ) $( LIBFT ) $( LIBMLX )
$( CC) $( LDFLAGS) $( OBJ) $( LDLIBS) -o $( NAME)
$(OBJ_DIR)/%.o : $( SRC_DIR ) /%.c | $( OBJ_DIR )
$( CC) $( CPPFLAGS) $( CFLAGS) -c $< -o $@
$(OBJ_DIR) $(LIB_DIR) :
mkdir -p $@
clean :
rm -rv $( OBJ_DIR)
$( MAKE) clean --directory= $( LIBFT_DIR)
$( MAKE) clean --directory= $( MLX_DIR)
fclean : clean
rm $( NAME)
$( MAKE) fclean --directory= $( LIBFT_DIR)
re : fclean all
-include $(OBJ : .o =.d )
# libft 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
NAME = libft.a
RUNNER = runner
CC = gcc
CFLAGS = -Wall -Werror -Wextra
S = ft_atoi.c ft_bzero.c ft_calloc.c ft_isalnum.c ft_isalpha.c \
ft_isascii.c ft_isdigit.c ft_isprint.c ft_itoa.c ft_memchr.c \
ft_memcmp.c ft_memcpy.c ft_memmove.c ft_memset.c ft_putchar_fd.c \
ft_putendl_fd.c ft_putnbr_fd.c ft_putstr_fd.c ft_split.c \
ft_strchr.c ft_strdup.c ft_striteri.c ft_strjoin.c ft_strlcat.c \
ft_strlcpy.c ft_strlen.c ft_strmapi.c ft_strncmp.c ft_strnstr.c \
ft_strrchr.c ft_strtrim.c ft_substr.c ft_tolower.c ft_toupper.c \
# main.c
O = $( S:.c= .o)
BONUS_S = ft_lstnew_bonus.c ft_lstadd_front_bonus.c ft_lstsize_bonus.c \
ft_lstlast_bonus.c ft_lstadd_back_bonus.c ft_lstdelone_bonus.c \
ft_lstclear_bonus.c ft_lstiter_bonus.c ft_lstmap_bonus.c
BONUS_O = $( BONUS_S:.c= .o)
H = libft.h
RM = rm -rf
.PHONY : all bonus clean fclean re
all bonus : $( NAME )
$(NAME) : $( O ) $( if $( findstring bonus , $( MAKECMDGOALS )) , $( BONUS_O ))
ar rcs $( NAME) $( O) $(if $( findstring bonus, $( MAKECMDGOALS)) , $( BONUS_O))
# needs to have 'int main()' to be functional
runner : $( O ) $( BONUS_O )
@$( CC) $( CFLAGS) -o $( RUNNER) $( O) $( BONUS_O)
%.o : %.c $( H )
$( CC) $( CFLAGS) -c $< -o $( addsuffix .o, $( basename $<))
clean :
$( RM) $( O) $( BONUS_O)
fclean : clean
$( RM) $( NAME)
re : fclean all
# Basic with wildcardsBeware that *
works only for existing files, so don’t use it in rules for object files. Use %
pattern matching instead.
A basic and more or less universal example (
a version with tabs , as Make has a very stupid relationship with spaces) (also a
gist ):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
CC = gcc
CFLAGS = -Wall -Werror -Wextra
NAME = bsq
HDIR = ./include/
S = $( wildcard *.c */*.c */*/*.c)
H = $( wildcard *.h */*.h */*/*.h)
O = $( S:.c= .o)
RM = rm -rf
.PHONY : all clean fclean re
all : $( NAME )
$(NAME) : $( O )
@$( CC) $( CFLAGS) -o $( NAME) $( O)
.c.o :
@$( CC) $( CFLAGS) -c $< -o $@ -I $( HDIR)
clean :
@$( RM) $( O)
fclean : clean
@$( RM) $( NAME)
re : fclean all
# jbelinda #todo