Using make Static Pattern Rules for multiple files - c

I'm having trouble creating a pattern to apply to every file in a subdirectory
I have the following tree:
libft/
..makefile
..obj/
..bonus/
........bonusfile1.c
........bonusfile2.c
........bonusfile3.c
........[...etc...]
..mainfile1.c
..mainfile2.c
..mainfile3.c
..[...etc...]
I'm trying to compile the bonus/bonusfiles into the objects obj directory but no mater what I type I'm coming up short of my objective.
My makefile:
SRC_FILES= ft_atoi.c \
ft_bzero.c \
...
BONUS_FILES=ft_lstadd_back.c \
ft_lstadd_front.c \
...
NAME=libft.a
LIBSO=libft.so
CC=gcc
CFLAGS=-Wall -Wextra -Werror
BONUS_DIR=bonus/
OBJ_DIR=obj/
HDR_NAME=libft.h
BONUS_HDR=_bonus.h
SRC_PATH=$(addprefix $(SRC_DIR), $(SRC_FILES))
BONUS_PATH=$(addprefix $(BONUS_DIR), $(BONUS_FILES))
SRC_NAMES=${SRC_FILES:.c=.o}
BONUS_NAMES=${BONUS_FILES:.c=.o}
SRC_NAMES_O=$(addprefix $(OBJ_DIR), $(SRC_NAMES))
BONUS_NAMES_O=$(addprefix $(OBJ_DIR), $(BONUS_NAMES))
HDR= $(addprefix $(HDR_DIR),$(HDR_NAME))
all: $(NAME)
$(NAME): $(OBJ_DIR) $(SRC_NAMES)
ar -rc $# $(SRC_NAMES_O)
ranlib $#
$(OBJ_DIR):
mkdir $#
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $(OBJ_DIR)$#
bonus: $(BONUS_PATH)
ar -r $(NAME) $(BONUS_NAMES_O)
ranlib $#
$(BONUS_PATH): %.o: %.c
$(CC) $(CFLAGS) -c $< -o $(OBJ_DIR)$#
clean:
rm -rf $(OBJ_DIR)
rm -rf src/*.o
rm -rf *.o
sclean: clean
rm -rf $(NAME) $(LIBSO) a.out
fclean: clean
rm -f $(NAME)
re: fclean all
so:
$(CC) -nostartfiles -fPIC $(CFLAGS) $(SRC_FILES) $(BONUS_PATH)
gcc -nostartfiles -shared -o libft.so $(SRC_FILES) $(BONUS_PATH)
.PHONY: all clean fclean re so bonus
What I wanted to do was something similar to the %.o: %.c target but I can't. What am I doing wrong?

Related

Makefile - compiling library and executable when no changes made

So, I can understand what the problem is here, but I can't quite figure out how to fix it -- Because it is compiling files from a different directory, but throwing the .a library file and executable into the root...It seems that the makefile is expecting them to be in their source directory, and that's why it rebuilds every time even when no changes are made.
Problem is, my school is very strict on folder structure, so it needs to compile exactly how it is, I just need to figure out how to let the makefile know the executable and library file DO exist, in the root directory.
Here is my Makefile:
NAME = fillit
LIB = libft.a
CC = gcc
CFLAGS = -Wall -Wextra -Werror
RM = /bin/rm -rf
SRC = main.c validation.c create_piece.c game_board.c solver.c tables.c \
trimmer.c
LIBSRC = ft_putchar.c ft_putstr.c ft_strcpy.c ft_strnew.c ft_strdel.c \
ft_strequ.c ft_putendl.c ft_error.c
LIBLIST := $(shell ls -1 libft | grep .c$$)
LIBOBJ := $(LIBLIST:.c=.o)
LIBOBJ := $(addprefix libft/, $(LIBOBJ))
SRCLIST := $(shell ls -1 src | grep .c$$)
SRCOBJ := $(SRCLIST:.c=.o)
SRCOBJ := $(addprefix src/, $(SRCOBJ))
.PHONY: all $(NAME) lib
all: $(NAME)
libft/%.o: libft/%.c
$(CC) $(CFLAGS) -c -o $# $<
src/%.o: src/%.c
$(CC) $(CFLAGS) -c -o $# $<
lib:
ar rc $(LIB) $(LIBOBJ)
ranlib $(LIB)
debug:
$(CC) $(CFLAGS) $(addprefix libft/, $(LIBLIST)) $(addprefix src/, $(SRCLIST)) -g -o fillit
$(NAME): $(LIBOBJ) $(SRCOBJ) lib
$(CC) $(CFLAGS) $(SRCOBJ) -L. -lft -o fillit
clean:
$(RM) $(SRCOBJ)
$(RM) $(LIBOBJ)
fclean: clean
$(RM) $(NAME)
$(RM) $(LIB)
re: fclean all
re-db: fclean debug
It's working fine for compiling the .o files, it only does that once, but if I continue to type make, it still compiles this part:
➜ fillit git:(master) ✗ make
ar rc libft.a libft/ft_memset.o libft/ft_putchar.o libft/ft_putendl.o libft/ft_putstr.o libft/ft_strcpy.o libft/ft_strdel.o libft/ft_strequ.o libft/ft_strnew.o
ranlib libft.a
gcc -Wall -Wextra -Werror src/create_piece.o src/game_board.o src/main.o src/solver.o src/tables.o src/trimmer.o src/validation.o -L. -lft -o fillit
Want to thank kaylum for pointing me in the right direction, I have figured out how to solve this problem. I changed lib to $(LIB) and removed $(NAME) and lib from the phony list. Working makefile:
NAME = fillit
LIB = libft.a
CC = gcc
CFLAGS = -Wall -Wextra -Werror
RM = /bin/rm -rf
SRC = main.c validation.c create_piece.c game_board.c solver.c tables.c \
trimmer.c
LIBSRC = ft_putchar.c ft_putstr.c ft_strcpy.c ft_strnew.c ft_strdel.c \
ft_strequ.c ft_putendl.c ft_error.c
LIBLIST := $(shell ls -1 libft | grep .c$$)
LIBOBJ := $(LIBLIST:.c=.o)
LIBOBJ := $(addprefix libft/, $(LIBOBJ))
SRCLIST := $(shell ls -1 src | grep .c$$)
SRCOBJ := $(SRCLIST:.c=.o)
SRCOBJ := $(addprefix src/, $(SRCOBJ))
.PHONY: all
all: $(NAME)
libft/%.o: libft/%.c
$(CC) $(CFLAGS) -c -o $# $<
src/%.o: src/%.c
$(CC) $(CFLAGS) -c -o $# $<
$(LIB):
ar rc $(LIB) $(LIBOBJ)
ranlib $(LIB)
debug:
$(CC) $(CFLAGS) $(addprefix libft/, $(LIBLIST)) $(addprefix src/, $(SRCLIST)) -g -o fillit
$(NAME): $(LIBOBJ) $(SRCOBJ) $(LIB)
$(CC) $(CFLAGS) $(SRCOBJ) -L. -lft -o $(NAME)
clean:
$(RM) $(SRCOBJ)
$(RM) $(LIBOBJ)
fclean: clean
$(RM) $(NAME)
$(RM) $(LIB)
re: fclean all
re-db: fclean debug

Makefile does not find rule for object

I have a beginner's question about a Makefile. I have a very simple makefile containing:
SHELL = /bin/sh
CC = gcc
CFLAGS = -lm -std=c99 -g -o0
EXEC = test
BUILDDIR = build
OBJDIR = obj
SOURCES = $(shell cat sources.list)
DEPS = $(shell cat headers.list)
OBJ = $(SOURCES:.c=.o)
OBJECTS = $(patsubst %,$(OBJDIR)/%,$(OBJ))
all: $(OBJECTS)
$(CC) $(CFLAGS) $(OBJECTS) -o $(BUILDDIR)/$(EXEC)
$(OBJDIR)/%.o: %.c $(DEPS)
$(CC) -c $< -o $#
clean:
rm -f $(BUILDDIR)/$(EXEC) $(OBJDIR)/*.o
My Problem is, if I try to use this Makefile to compile, it returns the error message:
there is no rule for the target obj/Name.o
What am I doing wrong?
After the first few comments and further research I got to this working Version, but it does not create the object files in the obj folder, so it is not what I aim for
SHELL = /bin/sh
CC = gcc
CFLAGS = -lm -std=c99 -g -o0
EXEC = test
BUILDDIR = build
OBJDIR = obj
SOURCES = $(shell cat sources.list)
DEPS = $(shell cat headers.list)
OBJ = $(SOURCES:.c=.o)
OBJECTS = $(patsubst %,$(OBJDIR)/%,$(OBJ))
all: $(BUILDDIR)/$(EXEC)
$(BUILDDIR)/$(EXEC): $(OBJ)
$(CC) $(CFLAGS) $(OBJ) -o $(BUILDDIR)/$(EXEC)
%.o: %.c $(DEPS)
$(CC) -c $< -o $#
clean:
rm -f $(BUILDDIR)/$(EXEC) $(OBJDIR)/*.o
Are all the files in headers.list present at the right place ?
By the way, this is not a good way to handle dependencies on headers. You should take a look at -MP and -MDD and other options of your preprocessor to generate dependencies.
A classical makefile which should do what you need:
SHELL=/bin/bash
CC=gcc
CFLAGS=-std=c99 -g -o0
LDFLAGS=-lm
EXEC=test
BUILDDIR=build/
OBJDIR=obj/
SOURCES=$(shell cat sources.list)
OBJECTS=$(patsubst %.c,$(OBJDIR)%.o,$(notdir $(SOURCES)))
vpath %.c $(sort $(dir $(SOURCES)))
.PHONY:all mrproper clean depends
all:$(BUILDDIR)$(EXEC)
$(BUILDDIR)$(EXEC):$(OBJECTS)|$(BUILDDIR)
$(CC) $(CFLAGS) $^ -o $# $(LDFLAGS)
$(OBJDIR)%.o:%.c|$(OBJDIR)
$(CC) -c $< -o $#
$(BUILDDIR) $(OBJDIR):
mkdir $#
mrproper:clean
rm -f $(BUILDDIR)$(EXEC)
clean:
rm -f $(OBJECTS)
depends:
#rm -f dependencies.mk
#for i in $(SOURCES); do $(CC) -MM $$i -MT $(OBJDIR)`basename $$i | sed s:.c$$:.o:` >> dependencies.mk; done
include $(wildcard dependencies.mk)
If something is not clear, let me know.
Usage:
make depends
make

Makefile doesn't rebuild objects on header modification

I have made a Makefile for compiling my C programm but it's not building object when i change one of the headers.
My MakeFile:
CC=gcc
CFLAGS=-O3 -Wall
LDFLAGS=-I/usr/include/mysql -L/usr/lib/x86_64-linux-gnu -lmysqlclient
SOURCES=$(wildcard *.c)
OBJECTS=$(SOURCES:.c=.o)
EXECUTABLE=bin/beta_parser
all: $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) -o $# $^ $(CFLAGS) $(LDFLAGS)
%.o:%.c types.h cstes.h headers.h mysql.h
$(CC) -o $# -c $< $(CFLAGS)
.PHONY: clean mrproper
clean:
rm -rf *.o
mrproper:
rm -rf $(EXEC)
What have I done wrong ?
EDIT : Corection of the Makeil after a great comment.
Although there are other more elegant tricks, in your case, I think something like
$(OBJECTS): types.h cstes.h headers.h mysql.h
%.o: %.c
$(CC) -o $# -c $< $(CFLAGS)
should be sufficient.
Scanning your sources for dependencies is outside the scope of Make (although there are other tools, such as CMake which will do this automatically). You need to add an explicit rule to generate these dependencies, but this can be done in many different ways. I've sometimes used the following technique:
OBJECTS = ....
-include $(OBJECTS:.o=.d)
...
$(OBJECTS): %.o: %.c
$(CC) $(CFLAGS) -c $< -o $#
$(CC) $(CFLAGS) $(DEPFLAGS) $< > $*.d
Google for "make automatic dependency generation" will show you other ways to do it as well.

Makefile not working - Adding new files

I'm using this premade makefile. I tried adding heavyhitter.o and heavyhitter.h for those two files that I added to the application but I can't get it to work. I had added metadata_record.h and metadata_record.o without a problem and since I'm adding to the same area, I'm not sure why it worked before but isn't now.
CC = $(shell if test -f /opt/local/bin/gcc-mp-4.7; then \
echo gcc-mp-4.7; else echo gcc; fi)
CFLAGS = -std=gnu99 -g -W -Wall -O0 -gstabs -Iglib-2.0 -lglib-2.0
TESTS = $(patsubst %.c,%,$(sort $(wildcard test[0-9][0-9][0-9].c)))
%.o: %.c m61.h memory.h metadata_record.h heavyhitters.h
$(CC) $(CFLAGS) -o $# -c $
all: $(TESTS) hhtest
#echo "*** Run 'make check' or 'make check-all' to check your work."
test%: test%.o m61.o memory.o metadata_record.o heavyhitters.o
$(CC) $(CFLAGS) -o $# $^
test017: test017-help.o
hhtest: hhtest.o m61.o memory.o metadata_record.o heavyhitters.o
$(CC) $(CFLAGS) -o $# $^ -lm
check: $(TESTS) $(patsubst %,check-%,$(TESTS))
#echo "*** All tests succeeded!"
check-all: $(TESTS)
#x=true; for i in $(TESTS); do $(MAKE) check-$$i || x=false; done; \
if $$x; then echo "*** All tests succeeded!"; fi; $$x
check-test%: test%
#test -d out || mkdir out
#rm -f out/test$*.fail
#-sh -c "./$^ > out/test$*.output 2>&1" >/dev/null 2>&1; true
#perl compare.pl out/test$*.output test$*.c test$*
clean:
rm -f $(TESTS) hhtest *.o
rm -rf out
MALLOC_CHECK_=0
export MALLOC_CHECK_
.PRECIOUS: %.o
.PHONY: all clean check check-% prepare-check
It was actually supposed to be heavyhitter not heavyhitters

Cannot make the project when files are located in different folders

I'm trying to build project. There are two directories:
A/
foo.c
foo.h
B/
main.c
Makefile
main.c includes "foo.h". What do i have to write in Makefile to build the project.
I did this
INCLUDE_DIR=../A
LIBS=-lm
CC = gcc
CFLAGS = -c -Wall -I$(INCLUDE_DIR)
default:
#make clean
#make main
sample: main.o foo.o
$(CC) $(LIBS) $? -o $#
main.o: main.c
$(CC) $(CFLAGS) $< -c $%
foo.o: foo.c
$(CC) $(CFLAGS) $< -c $%
clean:
#rm -rf *.o
It cant find foo.c
INCLUDE_DIR=../A
LIBS=-lm
CC = gcc
CFLAGS = -c -Wall -I$(INCLUDE_DIR)
default:
#make clean
#make main
sample: main.o $(INCLUDE_DIR)/foo.o
$(CC) $(LIBS) $? -o $#
main.o: main.c
$(CC) $(CFLAGS) $< -c $%
$(INCLUDE_DIR)/foo.o: $(INCLUDE_DIR)/foo.c
$(CC) $(CFLAGS) $< -c $%
clean:
#rm -rf *.o $(INCLUDE_DIR)/*.o
You need to tell make the relative path to the files.
IIRC you can use
foo.o: ../A/foo.c
$(CC) $(CFLAGS) $< -c $%
but I guess that's not really a solution?

Resources