Makefile - Compile object with different library - c

I´m trying to create a Makefile that build a lib and compile the file. My problem is that depending on the %.c file I need to compile with different lib.
The SRC_MLX need the $(LFLAGS) and the SRC don´t. So the gcc compiler don´t allow me to compile the SRC with the LFLAGS. That´s the reason I need to separate.
I´ve tried this way:
SRCS = $(DIR_SRC)/ft_utils.c \
$(DIR_SRC)/ft_adt.c \
$(DIR_SRC)/ft_circle.c \
$(DIR_SRC)/ft_line.c \
$(DIR_SRC)/ft_trgb.c \
$(DIR_SRC)/ft_quadrilateral.c \
$(DIR_SRC)/ft_player.c \
$(DIR_SRC)/ft_color.c
SRCS_MLX = $(DIR_SRC)/win_update.c \
$(DIR_SRC)/ft_vars.c \
$(DIR_SRC)/ft_image.c \
$(DIR_SRC)/ft_map.c
$(NAME): $(LIB_NAME)
$(CC) $(CFLAGS) main.c -I. -I$(DIR_MLX) -L$(DIR_MLX) -L. $(LFLAGS) $(LIB_FLAG) -o $# -g
$(DIR_OBJ)/$(OBJ).o: $(DIR_SRC)/$(SRCS).c
mkdir -p $(DIR_OBJ)
$(CC) $(CFLAGS) -c $< -I. -I$(DIR_MLX) -o $#
$(DIR_OBJ)/$(OBJ_MLX).o: $(DIR_SRC)/$(SRCS_MLX).c
mkdir -p $(DIR_OBJ)
$(CC) $(CFLAGS) -c $< -I. -I$(DIR_MLX) -L$(DIR_MLX) $(LFLAGS) -o $#
$(LIB_NAME): $(OBJ_MLX) LIB_OBJ
$(AR) $(LIB_NAME) $(OBJ)
ranlib $(LIB_NAME)
LIB_OBJ: $(OBJ)
$(AR) $(LIB_NAME) $(OBJ)
In the example above I´ve tried to create a lib with one kind of files and after that create a lib with the first lib with the others files. But I keep getting this error:
Makefile:41: warning: overriding recipe for target '.objs/'
Makefile:37: warning: ignoring old recipe for target '.objs/'
make: Warning: File 'Makefile' has modification time 454 s in the future
rm -f .objs/ft_utils.o .objs/ft_adt.o .objs/ft_circle.o .objs/ft_line.o .objs/ft_trgb.o .objs/ft_quadrilateral.o .objs/ft_player.o .objs/ft_color.o
rm -f libcub3d.a
rm -f main
make: *** No rule to make target 'src/src/win_update.c', needed by '.objs/win_update.o'. Stop.
How can I compile this objects with different lib?
P.S. Those are my variables:
DIR_OBJ = .objs
DIR_SRC = src
DIR_LIB = lib
DIR_MLX = ./minilibx-linux
NAME = main
LIB_NAME = libcub3d.a
OBJ = $(patsubst $(DIR_SRC)/%.c, $(DIR_OBJ)/%.o, $(SRCS))
OBJ_MLX = $(patsubst $(DIR_SRC)/%.c, $(DIR_OBJ)/%.o, $(SRCS_MLX))
CC = clang
CFLAGS = -Wall -Werror -Wextra
LFLAGS = -lmlx -lm -lX11 -lXext -lbsd
LIB_FLAG = -lcub3d
AR = ar -rc
RM = rm -f

These lines are definitely not right:
$(DIR_OBJ)/$(OBJ).o: $(DIR_SRC)/$(SRCS).c
...
$(DIR_OBJ)/$(OBJ_MLX).o: $(DIR_SRC)/$(SRCS_MLX).c
along with the way you've defined SRCS and SRCS_MLX and these:
OBJ = $(patsubst $(DIR_SRC)/%.c, $(DIR_OBJ)/%.o, $(SRCS))
OBJ_MLX = $(patsubst $(DIR_SRC)/%.c, $(DIR_OBJ)/%.o, $(SRCS_MLX))
Just expand the variables in the rule in your head, or else ask make to expand it for you with the info function, and you'll see it's definitely not right:
$(info output is '$(DIR_OBJ)/$(OBJ).o: $(DIR_SRC)/$(SRCS).c')

Related

I cannot include my own libft.h and i don't know why

I want to include in a random test.c file my own library to test if it works but I can't do it.
Even a simple make all doesn't work, but I'm supposed to have done everything right. I have the impression that my makefile doesn't even compile my .c files in .o
here is my make file:
SRCS = ft_atoi.c ft_isascii.c ft_memchr.c ft_putchar_fd.c ft_strchr.c ft_strlen.c ft_strtrim.c \
ft_bzero.c ft_isdigit.c ft_memcmp.c ft_putendl_fd.c ft_strdup.c ft_strmapi.c ft_substr.c \
ft_calloc.c ft_isprint.cft_memcpy.c ft_putnbr_fd.c ft_strjoin.c ft_strncmp.c ft_tolower.c \
ft_isalnum.c ft_itoa.c ft_memmove.c ft_putstr_fd.c ft_strlcat.c ft_strnstr.c ft_toupper.c \
ft_isalpha.c ft_memccpy.c ft_memset.c ft_split.c ft_strlcpy.c ft_strrchr.c \
\
CC = gcc
CFLAGS = -Wall -Wextra -Werror
HEADER = libft.h
OBJS = $(SRCS:.c=.o)
RM = rm -f
NAME = libft.a
.c.o:
$(CC) $(CFLAGS) -c $< -o ${<:.c=.o}
$(NAME): $(OBJS) $(HEADER)
ar rcs $(NAME) $(OBJS)
all: $(NAME)
clean:
$(RM) $(OBJS)
fclean: clean
$(RM) $(NAME)
re: fclean all
.PHONY: all clean fclean re

Why are the source and header files modified, but the makefile is not recompiled

I encountered a problem about makefile, I modified my 2 source files link_ec.c and link_cloud.c, and 2 head files link_ec.h and link_cloud.h, but makefile is not recompiled. Is there a problem with where it was written?
my makefile as follows:
LIB_FOR_JSON = ./lib/json_lib/*
LIB_FOR_MQTT = ./lib/mqtt_lib/*
SRC_DIR = ./src
OUTPUT_DIR = ./output
SYS_LOCAL_LIB_DIR = /usr/local/lib
TARGET = linkCloudApp
RM = rm -rf
MV = mv
CP = cp -r
LDCONFIG = ldconfig
#### compile comment #####
COMPILE = aarch64-linux-gnu-
CC = $(COMPILE)gcc
STRIP = $(COMPILE)strip
LD = $(COMPILE)ld
COMPILE_OPTION = -O2 -Wall -Wcomment -Wformat -Wmissing-braces -Wswitch -Wuninitialized \
-Wbad-function-cast -Waggregate-return -Wmultichar -Wsign-compare -Wshadow
#COMPILE_OPTION_DEBUG = -gdwarf-2 -g
COMPILE_ALL_OPTION += $(COMPILE_OPTION) $(COMPILE_OPTION_DEBUG)
LINK_OPTION = -lpaho-mqtt3a -ljson-c -lm -lpthread -lz
OBJS_MAIN = main.o
OBJS_LINK_EC = link_ec.o
OBJS_LINK_CLOUD = link_cloud.o
OBJS = $(OBJS_MAIN) $(OBJS_LINK_EC) $(OBJS_LINK_CLOUD)
$(TARGET):$(OBJS)
$(CC) -o $(OUTPUT_DIR)/$(TARGET) $(OBJS) $(LINK_OPTION)
$(STRIP) $(OUTPUT_DIR)/$(TARGET)
$(OBJS_MAIN):
$(CC) -c $(SRC_DIR)/main.c $(COMPILE_ALL_OPTION)
$(OBJS_LINK_EC):
$(CC) -c $(SRC_DIR)/link_ec.c $(COMPILE_ALL_OPTION)
$(OBJS_LINK_CLOUD):
$(CC) -c $(SRC_DIR)/link_cloud.c $(COMPILE_ALL_OPTION)
.PHONY:clean copylib
clean:
-$(RM) $(OUTPUT_DIR)/* $(OBJS)
copylib:
$(CP) $(LIB_FOR_MQTT) $(SYS_LOCAL_LIB_DIR)/
$(CP) $(LIB_FOR_JSON) $(SYS_LOCAL_LIB_DIR)/
$(LDCONFIG)
Your object file recipes don't have any dependencies associated with them, so they won't get built unless you specify them explicitly.
Add the .c files to the dependency lists:
$(OBJS_MAIN): $(SRC_DIR)/main.c
$(CC) -c $(SRC_DIR)/main.c $(COMPILE_ALL_OPTION)
$(OBJS_LINK_EC): $(SRC_DIR)/link_ec.c
$(CC) -c $(SRC_DIR)/link_ec.c $(COMPILE_ALL_OPTION)
$(OBJS_LINK_CLOUD): $(SRC_DIR)/link_cloud.c
$(CC) -c $(SRC_DIR)/link_cloud.c $(COMPILE_ALL_OPTION)
Or you could make a single generic target for all of your .o files:
%.o: $(SRC_DIR)/%.c
$(CC) $(COMPILE_ALL_OPTION) -c $<

Linking is no occuring in my Makefile; returns 'undefined reference to `main'

This simple program (two .c files and one .h) compiles and links properly from the command line. However, my Makefile is throwing an error during the linking stage. Proper tab usage is in effect.
CC = gcc
BINDIR = bin/
OBJDIR = obj/
SRCDIR = src/
MKDIR = mkdir -p
RM = rm -rf
SRC = $(wildcard $(SRCDIR)*.c)
_OBJS = $(patsubst $(SRCDIR)%.c, %.o, $(SRC))
OBJS = $(addprefix $(OBJDIR), $(_OBJS))
CFLAGS = -Wall -g -Iinclude
.PHONY: all
all: $(BIN)
_BIN = a.out
BIN = $(addprefix $(BINDIR), $(_BIN))
$(BIN): $(OBJS) $(BINDIR)
$(CC) -o $# $(CFLAGS) $<
$(BINDIR):
$(MKDIR) $(BINDIR)
$(OBJS): $(SRC) $(OBJDIR)
$(CC) $(CFLAGS) -c $< -o $#
$(OBJDIR):
$(MKDIR) $(OBJDIR)
.PHONY: clean
clean:
#echo "Cleaning things up..."
$(RM) $(OBJDIR) $(BINDIR)
The program's files:
main.c
#include <stdio.h>
#include <stdlib.h>
#include "hellomake.h"
int main(void) {
myPrintHelloMake();
return EXIT_SUCCESS;
}
hellomake.c
#include <stdio.h>
#include "hellomake.h"
void myPrintHelloMake(void) {
puts("Hello makefiles!");
}
hellomake.h
#ifndef __HELLO_H__
#define __HELLO_H__
void myPrintHelloMake(void);
#endif
The .c files are in the src/ directory and the .h file is in the include/ directory. Makefile compiles the code, creates the obj/ directory, and places and main.o and hellomake.o therein. However, that is where things break down. Here is gcc's complaint:
$ make
mkdir -p obj/
gcc -Wall -g -Iinclude -c src/hellomake.c -o obj/hellomake.o gcc -Wall -g -Iinclude -c src/hellomake.c -o obj/main.o mkdir -p bin/ gcc -o bin/a.out -Wall -g -Iinclude
obj/hellomake.o /usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/Scrt1.o: in function `_start': (.text+0x20): undefined reference to `main' collect2: error: ld returned 1 exit status make: *** [Makefile:34: bin/a.out] Error 1
There were a number of issues.
I'd leave off / from (e.g.) BINDIR et. al.
The patsubst was incorrect. It needed $(OBJDIR) in the the TO
Using _OBJS was unnecessary/harmful.
The rule for $(OBJS) was incorrect. It created the two .o files using the first prereq source, so [the function] main was defined twice. It needs a pattern rule instead.
Using $(BINDIR) as a prereq for $(BIN) added bin/ at the end of the gcc line [and it complained]
As M.Oehm mentioned, $< only gets the first prereq.
The all: was indented so it was not recognized properly
Anyway, here's the corrected Makefile:
CC = gcc
BINDIR = bin
OBJDIR = obj
SRCDIR = src
MKDIR = mkdir -p
RM = rm -rf
SRC = $(wildcard $(SRCDIR)/*.c)
###_OBJS = $(patsubst $(SRCDIR)%.c, %.o, $(SRC))
###OBJS = $(addprefix $(OBJDIR), $(_OBJS))
OBJS = $(patsubst $(SRCDIR)/%.c, $(OBJDIR)/%.o, $(SRC))
CFLAGS = -Wall -g -Iinclude
_BIN = a.out
BIN = $(addprefix $(BINDIR)/, $(_BIN))
.PHONY: all
all: $(BINDIR) $(OBJDIR) $(BIN)
####$(BIN): $(OBJS) $(BINDIR)
$(BIN): $(OBJS) $(BINDIR)
###$(CC) -o $# $(CFLAGS) $<
$(CC) -o $# $(CFLAGS) $(OBJS)
$(BINDIR):
$(MKDIR) $(BINDIR)
###$(OBJS): $(SRC) $(OBJDIR)
$(OBJDIR)/%.o: $(SRCDIR)/%.c
$(CC) $(CFLAGS) -c $< -o $#
$(OBJDIR):
$(MKDIR) $(OBJDIR)
.PHONY: clean
clean:
#echo "Cleaning things up..."
$(RM) $(OBJDIR) $(BINDIR)

Makefile: two different executables taking two overlapping subsets of code

This is my situation, I am trying to write a Makefile for my c program, it has these components --
2 Headers:
src/header1.h
src/header2.h
N Sources:
src/src1.c
src/src2.c
src/src3.c ...
src/srcn.c
2 Mains:
src/main1.c
src/main2.c
main1.c and main2.c takes all the same src*.c and header*.h files, but in a different way. It would be really nice if I could write my Makefile in this way --
CC := gcc
INCLUDES := $(wildcard src/*.h)
SRC1 := all src*.c sources and main1.c (not main2.c)
SRC2 := all src*.c sources and main2.c (not main1.c)
IFLAGS := $(addprefix -I/,$(INCLUDES))
CFLAGS := -g -Wall -pedantic -std=gnu99 $(IFLAGS)
LDFLAGS := -lm
OBJS1 := all objects from src*.c (i.e. src*.o) and main1.o
OBJS1 := all objects from src*.c (i.e. src*.o) and main2.o
APP1 := app1
APP2 := app2
all: $(APP1) $(APP2)
$(APP1): $(OBJS1)
$(CC) $(CFLAGS) $^ -o $# $(LDFLAGS)
$(APP2): $(OBJS2)
$(CC) $(CFLAGS) $^ -o $# $(LDFLAGS)
$(OBJS1): $(SRC1)
$(CC) $(CFLAGS) -o $# -c $<
$(OBJS2): $(SRC2)
$(CC) $(CFLAGS) -o $# -c $<
clean:
rm $(OBJS1)
rm $(OBJS2)
rm $(APP1)
rm $(APP2)
How do I write the target/prerequisites rule for $SRC1, $SRC2, $OBJS1 and $OBJS2 above ?
COMMON = \
src1.c \
src2.c \
... \
srcn.c
MAIN1 = main1.c
MAIN2 = main2.c
COMOBJ = ${COMMON:.c=.o}
OBJS1 = ${MAIN1:.c=.o} ${COMOBJ}
OBJS2 = ${MAIN2:.c=.o} ${COMOBJ}
I often write macros such as MAIN1.c = main1.c as POSIX requires make to support that notation (and all the variants I've encountered do support it). But beware the vim doesn't think the macro names like that are kosher (which is a bug in vim's recognition of make macros). Then I'd write:
COMMON.c = ...
MAIN1.c = main1.c
...
FILES1.o = ${MAIN1.c:.c=.o} ${COMMON.c:.c=.o}
etc. Not everyone likes this notation.
You should be fine with just a list of objects
OBJS = src1.o src2.o #... etc
main1: main1.o $(OBJS)
main2: main2.o $(OBJS)
and let make use your provided CC, CFLAGS, and LDFLAGS to figure out the rest

undefined reference to 'main' no read source file

I've got a strange issue when I try to compile my code on my laptop.
It gives me this error: undefined reference to 'main' because apparently it cannot see my source files and then the objects either.
However, the same makefile and code work perfectly on my office machine.
here's the makefile. any hints?
thanks a lot for helping me in advance
ROOT = $(addprefix $(PWD), /)
BUILDS_DIR = $(addprefix $(ROOT), builds/)
SRCS_DIR = $(addprefix $(ROOT), src/)
INCS_DIR = $(addprefix $(ROOT), src/)
OBJS_DIR = $(addprefix $(SRCS_DIR), objects/)
LIBS_DIR = ./
SRCS = $(wildcard $(SRCS_DIR)*.c)
OBJS = $(SRCS:$(SRCS_DIR)%.c=$(OBJS_DIR)%.o)
TARGET = INTERP
EXES = $(addprefix $(BUILDS_DIR), $(TARGET))
CC = gcc
CFLAGS = -Wall -O3 -MD -DTRILIBRARY
INCLUDES = -I$(INCS_DIR)
CL = gcc
LFLAGS =
LIBS = -L$(LIBS_DIR) -lm
RM = rm -f
.PHONY: all $(TARGET) distclean clean
default: clean $(TARGET)
$(TARGET): $(OBJS)
#echo -e "\n\n\t\t*** Compiled $(TARGET) successfully! ***\n" ;
$(CL) $(LFLAGS) -o $(BUILDS_DIR)$# \
$(OBJS) \
$(LIBS)
#echo -e "\n\n\t\t*** Linking $(TARGET) completed! ***\n"
$(OBJS): $(OBJS_DIR)%.o : $(SRCS_DIR)%.c
$(CC) $(CFLAGS) $(INCLUDES) \
-c $<\
-o $#
distclean: clean
$(RM) $(EXES)
#echo -e "\n\n\t\t*** Purge $(TARGET) completed! ***\n"
clean:
$(RM) $(OBJS_DIR)*.o \
$(SRCS_DIR)*~
#echo -e "\n\n\t\t*** Cleanup $(TARGET) completed! ***\n"
depend: $(SRCS)
makedepend $(INCLUDES) $^

Resources