Codes I don't know when creating a makefile in c - c

NAME := libft.a
CC := gcc
CFLAGS := -Wall -Wextra -Werror -I. -c
FILES := $(shell find . -type f -name "ft_*.c")
OBJ := $(FILES:%.c=%.o)
all: $(NAME)
$(NAME): $(OBJ)
ar -rcs $(NAME) $(OBJ)
clean:
#rm -f *.o
fclean: clean
#rm -f $(NAME)
re: fclean all
.PHONY: all clean fclean re
can u explain what does it do ? = -I. , Files section , % , $ , ar -rcs

CFLAGS := -Wall -Wextra -Werror -I. -c set the variable CFLAGS to the value -Wall -Wextra -Werror -I. -c. This variable is used in an implicit rule to compile c programs so it's arguments to your c-compiler.
OBJ := $(FILES:%.c=%.o) sets a variable just like above and it does that by changing the extension .c to .o of the files listed in the variable FILES.
ar is a program used to create an archive (.a file). -rcs are arguments to said program:
c Create the archive.
r Insert the files member... into archive (with replacement).
s Write an object-file index into the archive, or update an existing

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!"

Adding a different object directory for Make

I want my make file to ouput (Object files .o) to a different subdirectory for example OBJECTS_DIR="./build"
I also want my .exe to be placed in DIST_DIR="./dist"
My make file below works(compiles & links) but in the same path.
# vars
CXX = g++
CXXFLAGS = -c89 -Wall -g
CC = gcc
CFLAGS = -Wall -g
SOURCES_C = main.c A.c B.c C.c D.c E.c
INCLUDES=
OBJECTS_DIR=./build
DIST_DIR=./dist
PROGRAM = main
OBJECTS = $(SOURCES_C:.c=.o)
debug := CFLAGS
all debug: $(PROGRAM)
$(PROGRAM): $(INCLUDES) $(OBJECTS)
$(LINK.c) -o $# $(OBJECTS)
clean:
rm -f $(PROGRAM) $(OBJECTS)
How can I achieve outputing .o files to OBJECTS_DIR and then linking from OBJECTS_DIR & outputing the .exe to DIST_DIR.
Updated based on user recommendations:
# vars
CXX = g++
CXXFLAGS = -Wall -g
CC = gcc
CFLAGS = -std=c89 -Wall -g
SOURCES_C = main.c A.c B.c C.c D.c E.c
OBJECTS_DIR := build
OBJECTS := $(SOURCES_C:%.c=$(OBJECTS_DIR)/%.o)
INCLUDES :=
DIST_DIR := dist
PROGRAM := $(DIST_DIR)/main
OBJECTS = $(SOURCES_C:.c=.o)
debug := CFLAGS
all debug: $(PROGRAM)
$(PROGRAM): $(INCLUDES) $(OBJECTS)
$(CC) -o $# $(OBJECTS)
clean:
rm -f $(PROGRAM)
rm -f $(OBJECTS)
I updated my Make & its works as expected.I have always relied on the IDE's to generate my Makefile.
1) Is there any issues that Im not aware of?
2) What is the point of the .PHONY (Still not getting that).
Thanks
The following makefile has not been tested
Note the use of ':=' for defining macros, so the macro only needs to be evaluated once
Note: the '.PHONY:' statements are to tell make that no file with the associated name (clean, all) will be generated
edited per Chris Dodd comments
CC := /usr/bin/gcc
RM := /bin/rm
CFLAGS := -Wall -g -Wextra -Wconversion -pedantic -std=gnu11
SOURCES_C := main.c A.c B.c C.c D.c E.c
OBJECTS_DIR := build
DIST_DIR := dist
PROGRAM := $(DIST_DIR)/main
OBJECTS := $(SOURCES_C:.c=$(OBJECTS_DIR)/%.o)
.PHONY: all
all: $(PROGRAM)
$(PROGRAM): $(OBJECTS)
$(CC) -o $# $(OBJECTS)
$(OBJECT_DIR)/%.o:%.c
$(CC) $(CFLAGS) -c %$< -o $#
.PHONY: clean
clean:
rm -f $(PROGRAM)
rm -f $(OBJECTS)

Makefile: wildcard and patsubst does not change file source names

I am trying to write a Makefile for my project, all the *.c and *.h files are in a folder called src, and the Makefile looks like this --
CC := gcc
CFLAGS := -g -Wall -ansi -pedantic -std=gnu99
LDFLAGS := -lm
INCLUDES := $(wildcard src/*.h)
IFLAGS := $(addprefix -I/,$(INCLUDES))
SRC := $(wildcard src/*.c)
OBJS := $(patsubst %.c, %.o, $(SRC))
APP := app
all: $(OBJS)
$(APP): $(OBJS)
$(CC) $(CFLAGS) $< -o $# $(LDFLAGS)
$(OBJS): $(SRC) $(INCLUDES)
$(CC) $(CFLAGS) $(IFLAGS) -c $< -o $#
clean:
rm -rf $(OBJS)
rm -rf *.out
rm -f $(APP)
At this point I am not building the executable, just trying to compile them to object files, so when I run, I am getting this output --
gcc -g -Wall -ansi -pedantic -std=gnu99 -I/src/structure.h -I/src/rng.h -c src/allocate.c -o src/allocate.o
gcc -g -Wall -ansi -pedantic -std=gnu99 -I/src/structure.h -I/src/rng.h -c src/allocate.c -o src/auxiliary.o
gcc -g -Wall -ansi -pedantic -std=gnu99 -I/src/structure.h -I/src/rng.h -c src/allocate.c -o src/decode.o
gcc -g -Wall -ansi -pedantic -std=gnu99 -I/src/structure.h -I/src/rng.h -c src/allocate.c -o src/display.o
You can see that in each gcc invocation, the source file names do not change, they are all always src/allocate.c why ? However, the object names are correctly expanded like src/allocate.o, src/auxiliary.o and src/decode.oetc.
It seems you've mixed up some things here.
They are basically two type of rules you need to use here, and they both share the same syntax:
targets : prerequisites
recipe
When you write this:
$(APP): $(OBJS)
$(CC) $(CFLAGS) $< -o $# $(LDFLAGS)
You're saying to make that you want to create $(APP), and to do that you need $(OBJS) to exist or to be created.
Now when you write this:
$(OBJS): $(SRC) $(INCLUDES)
$(CC) $(CFLAGS) $(IFLAGS) -c $< -o $#
You're telling make you want to create a list of .o files, and for each individual file that you need all $(SRC) and $(INCLUDES).
Since in the recipe you're using $<, which is a shortcut for the first entry in the prerequisites list, you always end up with the same source file being compiled.
To do what you want, you must abstract things a little bit and tell make "Here is how I want you to build any .o file that depends on a corresponding .c". That is the job of pattern rules:
%.o: %.c
$(CC) $(CPPFLAGS) $(CFLAGS) -o $# -c $<
Ultimately, your Makefile should look like this:
APP := app
SRC := $(wildcard src/*.c)
OBJ := $(SRC:.c=.o)
CFLAGS := -W -Wall -g -std=c99 -pedantic
LDLIBS := -lm
all: $(OBJS)
$(APP): $(OBJ)
$(CC) $(LDFLAGS) $^ $(LDLIBS) -o $#
clean:
$(RM) $(APP) $(OBJ)
Note another couple of things here that you missed:
The -I preprocessor flag (that should be placed in the CPPFLAGS variable) accept a directory, not a file.
The -ansi compiler flag is a synonym of -std=c89. You're using -std=gnu99 right after so that one will be picked ultimately
You don't need to list your header files at all. Don't bother.
Don't use the -r flag of the rm command without care, you'll end up removing folders. It is not used to remove multiple files but to remove recursively, read up your man.
You used $< instead of $^ at the linking phase, so your executable will miss many object files.
To address the comments:
GNU make has a lot of predefined rules, functions and variables that you should be using before rolling your own. It has basic rules for compiling and linking C and C++ programs, among other, this is why your Makefile does not need te redefine the %.o: %c rule that already exists.
You can see all of these by typing this in your favorite shell:
$ make -p > predefined.mk
$(RM), $(CC) are one of these predefined variables, you can see by yourself what they actually contain.
Now, as many users are concerned with header files dependencies, let's adress this issue. You won't have to manually do that, modern compilers like GCC and Clang do this for you once you set them up.
The dependencies for each .c file will be generated in a .d file that must be included in the Makefile.
To tell the compiler to generate these files while compiling, you need to pass a preprocessor flag:
CPPFLAGS := -MMD
Now the dependencies are auto-generated, we need to include them:
DEP := $(OBJ:.o=.d)
-include $(DEP)
You'd also want to clean them:
clean:
$(RM) $(APP) $(OBJ) $(DEP)
Now your Makefile looks like this:
APP := app
SRC := $(wildcard src/*.c)
OBJ := $(SRC:.c=.o)
DEP := $(OBJ:.o=.d)
CPPFLAGS := -MMD
CFLAGS := -W -Wall -g -std=c99 -pedantic
LDLIBS := -lm
all: $(OBJS)
$(APP): $(OBJ)
$(CC) $(LDFLAGS) $^ $(LDLIBS) -o $#
clean:
$(RM) $(APP) $(OBJ) $(DEP)
-include $(DEP)
Last point: the syntax $(SRC:.c=.o) is a shortcut for $(SRC:%.c=%.o) which is also a shortcut for $(patsubst %.c,%.o,$(SRC)).

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.

makefile for creating (.so) file from existing files

I have 4 files: 1.c, 1.h, 2.c, 2.h.
I need a makefile, which will create a dynamic library (.so) from those 4 files.
I have tried to write a makefile like this:
library.so : 1.c 1.h 2.c 2.h
but it did not work. It would be great, if someone helps me, thanks.
Something like
CC=gcc
CFLAGS= -Wall -g -O -fPIC
RM= rm -f
.PHONY: all clean
all: library.so
clean:
$(RM) *.o *.so
library.so: 1.o 2.o
$(LINK.c) -shared $^ -o $#
1.o: 1.c 1.h 2.h
2.o: 2.c 1.h 2.h
But this is untested! I am assuming Linux with GNU make, and a directory containing only the source code of your library (with the above Makefile), which might be bad practice -you might want a test case- (you could have a special Makefile rule for %.pic.o depending on %.c, etc...)
Hints: use make -p to understand the builtin rules. Then make --trace or (with remake) remake -x to understand a bit more what make is doing.
Read also Drepper's paper: How to Write Shared Libraries, documentation of GNU make, Program Library HowTo, this answer, ...
The simplest way is:
CXXFLAGS += -fPIC
CXXFLAGS += -O3
x.so: 1.o 2.o
$(LINK.cc) -shared $^ $(LOADLIBS) $(LDLIBS) -o $#
Slightly more advanced:
CC = gcc
FLAGS = # -std=gnu99 -Iinclude
CFLAGS = -fPIC -g #-pedantic -Wall -Wextra -ggdb3
LDFLAGS = -shared
DEBUGFLAGS = -O0 -D _DEBUG
RELEASEFLAGS = -O2 -D NDEBUG -combine -fwhole-program
TARGET = example.so
SOURCES = $(wildcard *.c)
HEADERS = $(wildcard *.h)
OBJECTS = $(SOURCES:.c=.o)
all: $(TARGET)
$(TARGET): $(OBJECTS)
$(CC) $(FLAGS) $(CFLAGS) $(DEBUGFLAGS) -o $(TARGET) $(OBJECTS)
CC = gcc # C compiler
CFLAGS = -fPIC -Wall -Wextra -g # C flags
LDFLAGS = -shared # linking flags
RM = rm -f # rm command
TARGET_LIB = sh_main.so # target lib
SRCS = add.c sub.c main.c # source file
DEPS = header.h # header file
OBJS = $(SRCS:.c=.o) # object file
.PHONY: all
all: ${TARGET_LIB}
$(TARGET_LIB): $(OBJS)
$(CC) ${LDFLAGS} -o $# $^ # -o $# says, put the output of the compilation in the file named on the left side of the :
$(SRCS:.c=.d):%.d:%.c
$(CC) $(CFLAGS) -MM $< >$# # the $< is the first item in the dependencies list, and the CFLAGS macro is defined as above
include $(SRCS:.c=.d)
.PHONY: clean
clean:
-${RM} ${TARGET_LIB} ${OBJS} $(SRCS:.c=.d)
After the shared library created successfully. We need to install it.
Become the root user.
Copy the shared library into standard directory "/usr/lib".
Run ldcofig command.
Recompile your .c file with shared library.
root#Admin:~/C/SharedLibrary# gcc -c main.c
root#Admin:~/C/SharedLibrary# gcc -o main main.o sh_main.so
root#Admin:~/C/SharedLibrary# ldd main
Note: In my case.
main.c: main C file
sh_main.so: shared library.
I'm no gnu make expert, this seems reasonable to me
CFLAGS+=-fPIC
%.so: ; $(LINK.c) $(LDFLAGS) -shared $^ -o $#
library.so: 1.o 2.o # default target first
# changes to `1.h` imply `1.o` needs to be rebuilt
1.o: 1.h
2.o: 2.h

Resources