Makefile - compiling library and executable when no changes made - c

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

Related

Makefile compilation warning (libftprintf.a the table of contents is empty (no object file members in the libr ary define global symbols)

I am trying to compile my Makefile to make library from different directories. The library is successfully compiled but I am facing the following warning
/Applications/Xcode.app/Contents/Developer/usr/bin/make -C ./libft
make[1]: Nothing to be done for `all'.
gcc -Wall -Werror -Wextra -c srcs/ft*.c libft/ft*.c -I ./includes
ar rcs libftprintf.a srcs/ft*.c libft/ft*.c*****
warning: /Applications/Xcode.app/Contents/Developer/Toolchains/Xcod
eDefault.xctoolchain/usr/bin/ranlib: archive library: libftprintf.a
the table of contents is empty (no object file members in the libr
ary define global symbols)
Please kindly advise on how to solve this warning. The structure of my directory is as follow:
steh#u90z01s01 printf % ls
Makefile includes main.c libft srcs
My Makefile is as following
NAME := libftprintf.a
CC := gcc
AR := ar rcc
CFLAGS:= -Wall -Werror -Wextra -c
SRCS = srcs/ft*.c libft/ft*.c
INCLUDES = ./includes
OBJ_FILES = $(SRCS:%.c = %.o)
$(NAME): $(OBJ_FILES)#.fr
$(MAKE) -C ./libft
$(CC) $(CFLAGS) $(SRCS) -I $(INCLUDES)
$(AR) $(NAME) $(OBJ_FILES)
all: $(NAME)
clean:
#echo "Cleaning..."
rm -rf $(NAME) ft*.o
fclean:
rm -rf $(NAME)
re: fclean all
norm:
#norminette $(LIB_FILES)
.PHONY: clean fclean all re norm
This is my latest code
NAME := libftprintf.a
CC := gcc
AR := ar rcs
CFLAGS := -Wall -Werror -Wextra -c
SRCS = ./libft/ft*.c ./srcs/ft*.c
OBJS = ft*.o
LIBFT = ./libft
INC = ./includes
# Colors
GREEN= \033[1;32m
RED= \033[1;31m
all: $(NAME)
$(NAME):
#make re -C $(LIBFT)
#$(CC) $(CFLAGS) $(SRCS) -I $(INC)
#$(AR) $(NAME) $(OBJS)
#ranlib $(NAME)
#echo "$(GREEN)ft_printf compiled!"

Generate library with makefile : No rule to make target

CC= gcc
CFLAGS= -Wall -g
INCLUDES= -I/usr/local/include/
LFLAGS= -L/usr/local/lib64
LDFLAGS=
LIBS= -L. -lrabbitmq
SRCS= amqp_connection.c amqp_consumer.c amqp_deconnection.c amqp_producer.c amqp_utils.c
OBJS= $(SRCS:.c=.o)
EXEC=amqp_test
.PHONY: all
all: $(EXEC)
#echo "$(MAKE) : Tout est généré"
$(EXEC): $(OBJS)
$(CC) $(CFLAGS) -o $(EXEC) $(OBJS) $(LDFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS)
.PHONY: clean
clean:
$(RM) *~ *.o $(EXEC)
I want to generate a library not an executable
Can you help me please ?
I launched "make" and the result is :
make: *** No rule to make target
amqp_connection.o', needed by amqp_test'. Stop. amqp_test is the
name of the file which contain the main().
The sources are :
amqp_connection / amqp_consumer /amqp_deconnection / amqp_producer
This is an example file using some common practices. Here, I'm redefining the source directory and the object directory, and defining an implicit rule to build the objects given a source in a different directory.
CC := gcc
CFLAGS := -Wall -g
SRCDIR := src
OBJDIR := obj
INCLUDES := -I/usr/local/include/
LFLAGS := -L/usr/local/lib64
LDFLAGS :=
LIBS := -L. -lrabbitmq
SRCS_RAW := amqp_connection.c amqp_consumer.c amqp_deconnection.c amqp_producer.c amqp_utils.c
SRCS := $(addprefix $(SRCDIR)/,$(SRCS_RAW))
OBJS := $(addprefix $(OBJDIR)/,$(SRCS_RAW:.c=.o))
EXEC := amqp_test
$(info DEBUG: SRCS=$(SRCS))
$(info DEBUG: OBJS=$(OBJS))
$(info DEBUG: EXEC=$(EXEC))
.PHONY: all
all: $(EXEC)
#echo "$(MAKE) : Tout est généré"
$(EXEC): $(OBJS)
$(CC) $(CFLAGS) -o $(EXEC) $(OBJS) $(LDFLAGS) $(INCLUDES) $(LFLAGS) $(LIBS)
#rule to create object directory if it doesnt exist
$(OBJDIR):
mkdir $(OBJDIR)
#define implicit rule to build objects in their own directory
#(note -- order only dependency on object directory)
$(OBJS): $(OBJDIR)/%.o: $(SRCDIR)/%.c | $(OBJDIR)
$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $#
.PHONY: clean
clean:
$(RM) *~ $(EXEC)
$(RM) -r $(OBJDIR)

Makefile is not creating a directory

Teacher gave us this makefile for compiling two C files and storing the objects into a directory called object. It compiles the programs fine however it doesn't store their objects into the directory, and it also doesn't even create the directory. Not sure what to do and could really use some help.
This is my make file
CC = clang
CFLAGS = -g -Wall
OBJDIR = object
HDRS = $(wildcard *.h)
SRCS = $(wildcard *.c)
OBJS = $(addprefix $(OBJDIR)/, $(SRCS:.c=.o))
.PHONY: all
all: client server
# WARNING: must have a tab before each definition
$(OBJDIR)/client.o: client.c $(HDRS) $(OBJDIR)
$(CC) $(CFLAGS) -c client.c -o object/client.o
$(OBJDIR)/server .o: server.c $(HDRS) $(OBJDIR)
$(CC) $(CFLAGS) -c server.c -o object/server.o
$(OBJDIR)/%.o: %.c $(HDRS) $(OBJDIR)
$(CC) $(CFLAGS) -c $*.c -o object/$*.o
$(OBJDIR):
mkdir $(OBJDIR)
.PHONY: clean
clean:
rm -f $(TARGET) $(OBJS)
All I had to do was add multiple targets to the makefile and change all to target the targets
CC = clang
CFLAGS = -g -Wall
# TODO: rename the target to something meaningful!
TARGET = client server
OBJDIR = object
HDRS = $(wildcard *.h)
SRCS = $(wildcard *.c)
OBJS = $(addprefix $(OBJDIR)/, $(SRCS:.c=.o))
.PHONY: all
all: $(TARGET)
# WARNING: *must* have a tab before each definition
$(TARGET): $(OBJDIR) $(OBJS)
$(CC) $(CFLAGS) $(OBJDIR)/protocol.o $(OBJDIR)/$#.o -o $#
$(OBJDIR)/%.o: %.c $(HDRS) $(OBJDIR)
$(CC) $(CFLAGS) -c $*.c -o object/$*.o
$(OBJDIR):
mkdir $(OBJDIR)
.PHONY: clean
clean:
rm -f $(TARGET) $(OBJS)

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 always recompiling some sections

The directory structure for Example is something like this.
Example - Contains Makefile, main.c, xyz.c, xyz.h and sub-directories Hal and Interrupt_Config
Hal - Contains test2.c and test2.h Interrupt_Config - Contains try.h
EXE := Micro
CC := gcc
CPPFLAGS := -IHal -IInterruptConfig
VPATH := Hal:InterruptConfig
OUT_DIR := Output/
OUT_SRC := Output/source/
OUT_EXE := Output/output
LIBS = Hal InterruptConfig
MAIN_OBS := $(patsubst %.c,%.o,$(wildcard *.c))
INT_OBS := $(patsubst %.c,%.o,$(wildcard InterruptConfig/*.c))
HAL_OBS := $(patsubst %.c,%.o,$(wildcard Hal/*.c))
ALL_DEPS := $(patsubst %.o,%.d,$(MAIN_OBS) $(HAL_OBS) $(INT_OBS))
ALL_OBS := $(MAIN_OBS) $(INT_OBS) $(HAL_OBS)
all: $(OUT_DIR) $(EXE)
$(OUT_DIR):
mkdir -p $(OUT_DIR)
mkdir -p $(OUT_SRC)
mkdir -p $(OUT_EXE)
%.o: %.c
$(CC) -o $(OUT_SRC)$# -MD -MP $(CPPFLAGS) $(CFLAGS) -c $<
$(EXE): $(MAIN_OBS) $(HAL_OBS) $(INT_OBS)
$(CC) -o $(OUT_EXE)$# $(LDFLAGS) $(OUT_SRC)*.o $(LDLIBS)
$(HAL_OBS): %.o: %.c
$(CC) -o $(OUT_SRC)$(notdir $#) -MD -MP $(CPPFLAGS) $(CFLAGS) -c $<
$(INT_OBS): %.o: %.c
$(CC) -o $(OUT_SRC)$(notdir $#) -MD -MP $(CPPFLAGS) $(CFLAGS) -c $<
-include $(ALL_DEPS)
clean:
rm -rf $(OUT_DIR) $(ALL_DEPS)
.PHONY: all clean
Whenever I do make, it successfully creates a directory called as Output with sub-directories source containing all the object files and output containing an executable named Micro . The first time if I do make it build everything successfully but if I do make again , I expected it should give make - has nothing to do but it builds everything except $(OUT_DIR) rule. I am not able to figure out what is the problem.
Repeated make -
Expected - nothing
Actual -
gcc -o Output/source/main.o -MD -MP -IHal -IInterrupt_Config -c main.c
gcc -o Output/source/xyz.o -MD -MP -IHal -IInterrupt_Config -c xyz.c
gcc -o Output/source/test2.o -MD -MP -IHal -IInterrupt_Config -c Hal/test2.c
gcc -o Output/output/nextgenrsm Output/source/*.o
Also I am not sure whether I am doing dependencies thing correctly or not.
Without knowing your build directory setup, its hard to give you an exact solution, but my build rules look something like this:
MAIN_OBS := $(add_prefix $(OUT_DIR), $(patsubst %.c,%.o,$(wildcard *.c)))
$(OUT_DIR):
mkdir -p $(OUT_DIR)
mkdir -p $(OUT_SRC)
mkdir -p $(OUT_EXE)
$(OUT_SRC)/%.o: %.c
$(CC) -o $# -MD -MP $(CPPFLAGS) $(CFLAGS) -c $<
It gets complicated if you have a complicated directory structure because you will need to make more directories or get fancy with your object renaming.
Many thanks to mjr and Etan Reisner. I am just posting here the final Makefile for learning purposes for other people.
UPDATED
EXE :=nextgenrsm
CC := gcc
CPPFLAGS := -IHal -IInterrupt_Config
VPATH := Hal:Interrupt_Config
OUT_DIR := Output/
OUT_SRC := Output/source/
OUT_EXE := Output/output/$(EXE)
LIBS = Hal Interrupt_Config
MAIN_OBS := $(addprefix $(OUT_SRC), $(patsubst %.c,%.o, $(wildcard *.c)))
INT_OBS := $(addprefix $(OUT_SRC), $(notdir $(patsubst %.c,%.o,$(wildcard Interrupt_Config/*.c))))
HAL_OBS := $(addprefix $(OUT_SRC), $(notdir $(patsubst %.c,%.o,$(wildcard Hal/*.c))))
ALL_DEPS := $(patsubst %.o,%.d, $(MAIN_OBS) $(HAL_OBS) $(INT_OBS))
ALL_OBS = $(notdir $(MAIN_OBS) $(INT_OBS) $(HAL_OBS)))
all: $(OUT_DIR) $(OUT_EXE)
$(OUT_DIR):
mkdir -p $(OUT_DIR)
mkdir -p $(OUT_DIR)source/
mkdir -p $(OUT_DIR)output/
$(OUT_EXE): $(MAIN_OBS) $(HAL_OBS) $(INT_OBS)
$(CC) -o $# $(LDFLAGS) $(OUT_SRC)*.o $(LDLIBS)
$(OUT_SRC)%.o: %.c
$(CC) -o $# -MD -MP $(CPPFLAGS) $(CFLAGS) -c $<
-include $(ALL_DEPS)
clean:
rm -rf $(OUT_DIR)
.PHONY: all clean

Resources