make: *** No rule to make target `gcc', needed by `libmy.so'. Stop - c

I would like to compile .c files to a .so (shared library).
And I don't understand why, I have that makefile that makes me an error:
LIB = libmy.so
SRC = lib.c
CC = gcc
OBJ = $(CC) -c -fPIC $(SRC)
all: $(LIB)
re: fclean all
$(LIB): $(OBJ)
$(CC) -shared -fPIC $(OBJ) -o $(LIB)
clean:
$(RM) $(OBJ)
fclean: clean
$(RM) $(LIB)
Thanks in advance for helping.

The problem is in the following line:
$(LIB): $(OBJ)
When expanded this becomes:
libmy.so : gcc -c -fPIC lib.c
Hence the error.
What you probably wanted was :
OBJ = lib.o
To save you having to manually convert all .c source files to .o you can use a rule like this instead of OBJ = lib.o:
OBJ = $(SRC:%.c=%.o)
This creates a variable OBJ containing a list of all the files in SRC with any .c extension changed to .o. eg. If we had SRC = foo.c bar.c then the rule above would automatically expand to:
OBJ = foo.o bar.o

$(LIB): $(OBJ)
expands to
libmy.so: gcc -c -fPIC $(SRC)
ie you put your recipe into the depency list, and make rightfully complains.
Personally, I'd write the makefile like this:
CC := gcc
RM := rm -f
LIB := libmy.so
OBJ := lib.o
GARBAGE := $(OBJ)
.PHONY: all clean realclean
all: $(LIB)
$(LIB): LDFLAGS += -shared
$(LIB): $(OBJ)
$(CC) $(LDFLAGS) -o $# $<
$(OBJ): CFLAGS += -fPIC
$(OBJ): %.o : %.c
$(CC) $(CFLAGS) -c -o $# $<
realclean: GARBAGE += $(LIB)
clean realclean:
$(RM) $(GARBAGE)
Note that your original version did not contain a rule to make $(OBJ). If you wanted to use the implicit one, you would need to add -fPIC to CFLAGS.

That works :
LIB = libmy.so
SRC = lib.c
CC = gcc
OBJ = $(SRC:.c=.o)
all: $(LIB)
re: fclean all
$(LIB):
$(CC) -c -fPIC $(SRC)
$(CC) -shared -fPIC $(SRC) -o $(NAME)
clean:
$(RM) $(OBJ)
fclean: clean
$(RM) $(LIB)
I just need OBJ = $(SRC:.c=.o) in fclean

Related

How to create make file for only object and header file?

I'm performing blackbox testing using a set.h interface where I have no access to set.c, I've been provided with the object file set.o and I'm required to write a bunch of tests in a main.c file for the set. How do I create a makefile that would include set.o, set.h and main.c?
**I already have the set.o file so I don't have to regenerate it using set.c
I'm confused because I only know how to do this using the complete files.
Here's my template
CC = clang
CFLAGS = -g -Wall
PROG = example
HDRS = set.h
SRCS = main.c
OBJDIR = object
OBJS = $(OBJDIR)/main.o $(OBJDIR)/set.o
# compiling rules
$(PROG): $(OBJS) $(OBJDIR)
$(CC) $(CFLAGS) $(OBJS) -o $(PROG)
$(OBJDIR)/set.o: set.h $(HDRS) $(OBJDIR)
$(CC) $(CFLAGS) -c set.h -o $(OBJDIR)/set.o
$(OBJDIR)/main.o: main.c $(HDRS) $(OBJDIR)
$(CC) $(CFLAGS) -c main.c -o $(OBJDIR)/main.o
$(OBJDIR):
mkdir $(OBJDIR)
clean:
rm -f $(PROG) $(OBJS)
If you already have the set.o file there is no need to create a rule for it, just use it. Also note I got rid of the mkdir because if you already have a set.o, it should already be in objects/ right?
CC = clang
CFLAGS = -g -Wall
PROG = example
HDRS = set.h
SRCS = main.c
OBJDIR = object
OBJS = $(OBJDIR)/main.o
# compiling rules
$(PROG): $(OBJS)
$(CC) $(CFLAGS) $(OBJS) $(OBJDIR)/set.o -o $(PROG)
$(OBJDIR)/main.o: main.c $(HDRS)
$(CC) $(CFLAGS) -c main.c -o $(OBJDIR)/main.o
clean:
rm -f $(PROG) $(OBJS)

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 relink error

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)

Makefile: How to create both static and shared libraries in C?

Ladies, gentlemen, hello.
I'm trying to create a Makefile in C which will create two libraries
One static,one shared.So far my Makefile works for the static part.
Projet file structure:
//root
//root/src
An other point to mention, this Makefile also creates *.o in my root project directory and the /src dir.
What to do so it only creates object files inside the /src directory ?
Makefile:
SNAME = libmy_printf_`uname -m`-`uname -s`.a
DNAME = libmy_printf_`uname -m`-`uname -s`.so
SRC = $(wildcard src/*.c)
OBJ = $(SRC:.c=.o)
CC = gcc
RM = rm -f
CFLAGS = -W -Wall -ansi -pedantic -Werror -g3 -fPIC
LDFLAGS = -L. -l$(NAME)
STATIC: $(OBJ)
$(CC) -c $(SRC)
ar r $(SNAME) $(OBJ)
ranlib $(SNAME)
DYNAMIC: $(OBJ)
$(CC) -c $(SRC)
$(CC) -shared -o $(DNAME) $(OBJ)
.PHONY: my_printf_static
my_printf_static: $(STATIC)
.PHONY: my_printf_dynamic
my_printf_dynamic: $(DYNAMIC)
.PHONY: all
all: my_printf_static my_printf_dynamic
.PHONY: clean
clean:
$(RM) $(OBJ)
.PHONY: fclean
fclean: clean
$(RM) $(SNAME) $(DNAME)
.PHONY: re
re: fclean all
Thanks!
Your makefile can be boiled down to this:
NAME := libmy_printf_$(shell uname -m)-$(shell uname -s)
SNAME := $(NAME).a
DNAME := $(NAME).so
SRC := $(wildcard src/*.c)
OBJ := $(SRC:.c=.o)
CFLAGS := -ansi -pedantic -Wall -W -Werror -g3 -fPIC
LDFLAGS := -L.
LDLIBS := -l$(...)
.PHONY: all clean fclean re
all: $(SNAME) $(DNAME)
$(SNAME): $(OBJ)
$(AR) $(ARFLAGS) $# $^
$(DNAME): LDFLAGS += -shared
$(DNAME): $(OBJ)
$(CC) $(LDFLAGS) $^ $(LDLIBS) -o $#
clean:
$(RM) $(OBJ)
fclean: clean
$(RM) $(SNAME) $(DNAME)
re: fclean all
There are multiple things that you should know:
Don't use back-quotes commands, use the $(shell) built-in function in conjunction with the := assignment operator to prevent commands being re-run multiple times (unless this is the desired behavior).
Use only one .PHONY special rule, placed above all rules, and list them there.
Redefining $(CC) or $(RM) variables like you did is pointless since they already contain what you wanted here.
You wrote -l$(NAME) but you didn't define a NAME variable. I change it to $(...) since I couldn't guess what you really wanted here, don't forget to handle this.
Use the name of the targets to be created as the name of the related rules. That way Make won't recreate the targets unless you really want it (by calling the clean, fclean or re rules explicitly).
-L flags and -l flags should not be mixed in the same variable, unless placed at the right place in the linking command. Actually you didn't even used them. I explicitly separated them in the LDFLAGS and LDLIBS built-in variables, as per Make implicit rules.
If you have any questions, go ahead.
As discussed in the comments, if you need to remove the -fPIC flag from the compilation flags for the static library, you should consider building object files in different directories:
EDIT: I added your my_printf_static and my_printf_dynamic rules:
NAME := libmy_printf_$(shell uname -m)-$(shell uname -s)
SNAME := $(NAME).a
DNAME := $(NAME).so
SRC := $(wildcard src/*.c)
SDIR := build-static
SOBJ := $(SRC:src/%.c=$(SDIR)/%.o)
DDIR := build-shared
DOBJ := $(SRC:src/%.c=$(DDIR)/%.o)
CFLAGS := -ansi -pedantic -Wall -Werror -W -g3
LDFLAGS := -L.
LDLIBS := -l$(...)
.PHONY: all clean fclean re my_printf_static my_printf_dynamic
all: my_printf_static my_printf_dynamic
my_printf_static: $(SNAME)
my_printf_dynamic: $(DNAME)
$(SNAME): $(SOBJ)
$(AR) $(ARFLAGS) $# $^
$(DNAME): CFLAGS += -fPIC
$(DNAME): LDFLAGS += -shared
$(DNAME): $(DOBJ)
$(CC) $(LDFLAGS) $^ $(LDLIBS) -o $#
$(SDIR)/%.o: src/%.c | $(SDIR)
$(CC) $(CPPFLAGS) $(CFLAGS) -o $# -c $<
$(DDIR)/%.o: src/%.c | $(DDIR)
$(CC) $(CPPFLAGS) $(CFLAGS) -o $# -c $<
$(SDIR) $(DDIR):
#mkdir $#
clean:
$(RM) -r $(SDIR) $(DDIR)
fclean: clean
$(RM) $(SNAME) $(DNAME)
re: fclean all
What to do so it only creates object files inside the /src directory ?
Don't run the compiler twice. Your STATIC and DYNAMIC rules both depend on $(OBJ), which will cause those files to be built by make's implicit rules. Then, immediately after that you run the compiler again within those rules. Just take those lines out. make normally prints the commands it's going to run, so you should see why it's happening in your build log.

make: *** No rule to make target

Thanks for the responses. I found that this worked — I don't know why though.
all: $(OUT)
$(OBJ_DIR)/%.o: %.c
$(CC) $(CCFLAGS) -o $# -c $< $(INCLUDES)
$(OUT): $(OBJ)
ar rcs $(OUT) $(OBJ)
cp DIMEFILEAPPSAUTH.h ../include
.PHONY: clean
Below is a makefile I have. I keep getting the error make: *** No rule to make target but cannot see what is wrong in this case. The ".c" files exist in the current directory. I'm not sure why makefile cannot see them — can you explain?
DimeFileAppsAuth/src> ls
db_get_DIMEFILEAPPSAUTH.c db_reset_query_DIMEFILEAPPSAUTH.c Makefile
db_add_DIMEFILEAPPSAUTH.c db_print_DIMEFILEAPPSAUTH.c db_update_DIMEFILEAPPSAUTH.c
db_delete_DIMEFILEAPPSAUTH.c db_reset_DIMEFILEAPPSAUTH.c
Running the make
DimeFileAppsAuth/src> make
make: *** No rule to make target `../obj/db_add_DIMEFILEAPPSAUTH.o', needed by `../lib/lib_dime_file_apps.a'. Stop.
The Makefile
# clear out all suffixes
.SUFFIXES:
# list only those we use
.SUFFIXES: .o .c
# define a suffix rule for .c -> .o
.c.o :
$(CC) $(CFLAGS) -c $<
FILE_DIVERSION=$(IMG_PROJ_HOME)/dime/basics/BasicsLink
INC_DIR =../include
LIB_DIR =../lib
OBJ_DIR =../obj
BIN_DIR =../bin
CUR_DIR = .
OUT = $(LIB_DIR)/lib_dime_file_apps.a
BIN_OUT = $(BIN_DIR)/test_run
# include directories
INCLUDES = -I$(INC_DIR) -I$(FILE_DIVERSION)/include -I$(ORACLE_HOME)/rdbms/public -I/usr/local/include
# library paths
LIBS = -L$(LIB_DIR) -ldime_direct -L$(FILE_DIVERSION)/lib -loutput_files -lquerylib -lsql_common -lsql_common -L$(ORACLE_HOME)/lib -lclntsh -L$(ORACLE_HOME)/lib `cat $(ORACLE_HOME)/lib/sysliblist` -L/usr/local/lib -lm
CC=gcc
CCFLAGS=-w -O2 -unused-variable -Wall -fPIC -c -g -rdynamic
_DEPS = DIMEFILEAPPSAUTH.h
DEPS = $(patsubst %,$(INC_DIR)/%,$(_DEPS))
_OBJ = db_add_DIMEFILEAPPSAUTH.o db_delete_DIMEFILEAPPSAUTH.o db_get_DIMEFILEAPPSAUTH.o db_get_SEQ_DIMEFILEAPPSAUTH.o db_print_DIMEFILEAPPSAUTH.o db_reset_DIMEFILEAPPSAUTH.o db_reset_query_DIMEFILEAPPSAUTH.o db_special_DIMEFILEAPPSAUTH.o db_update_DIMEFILEAPPSAUTH.o
OBJ = $(patsubst %,$(OBJ_DIR)/%,$(_OBJ))
_BIN = db_add_DIMEFILEAPPSAUTH.o db_delete_DIMEFILEAPPSAUTH.o db_get_DIMEFILEAPPSAUTH.o db_get_SEQ_DIMEFILEAPPSAUTH.o db_print_DIMEFILEAPPSAUTH.o db_reset_DIMEFILEAPPSAUTH.o db_reset_query_DIMEFILEAPPSAUTH.o db_special_DIMEFILEAPPSAUTH.o db_update_DIMEFILEAPPSAUTH.o test_this.o
BIN = $(patsubst %,$(BIN_DIR)/%,$(_BIN))
all: $(OUT)
$(OBJ_DIR)/%.o: %.c $(DEPS)
$(CC) $(CCFLAGS) -o $# $< $(INCLUDES)
$(OUT): $(OBJ)
ar rcs $(OUT) $(OBJ)
cp DIMEFILEAPPSAUTH.h ../include
exec: $(BIN) $(OUT)
$(CC) -o $(BIN_OUT) $(BIN) $(LIBS)
rm $(BIN_DIR)/*.o
.PHONY: clean
The make error occurs when it comes to this line "$(OUT): $(OBJ)". Please check whether the file named "db_add_DIMEFILEAPPSAUTH.o" exists in the directory "../obj"

Resources