How to avoid my makefile to relink - makefile

My Makefile is relinking and I can't find why.
I'm not sure why malloc assume that $(NAME) have to be executed. Is the $(SRC:.c=.o) macro changing the timestamps of the .o files or something like that ?
CC = gcc
NAME = app
#
CFLAGS = -Wall -Werror -Wextra -pedantic -pedantic-errors
INCLUDES = -I ./includes
#
DIRSRC = srcs/
DIROBJ = objs/
SRC += main.c
SRC += malloc.c
OBJ = $(SRC:.c=.o)
DIROBJS = $(addprefix $(DIROBJ), $(OBJ))
#
LIBS_PATH = ./libs
LIBFT_PATH = $(LIBS_PATH)/libft
LIBFT_INCLUDES = -I $(LIBFT_PATH)
LIBFT = -L $(LIBFT_PATH) -lft
#
COMPILE = $(CC) $(CFLAGS) $(INCLUDES)
#
all: $(NAME)
$(NAME): configure libs $(DIROBJS)
$(COMPILE) $(LIBFT) $(DIROBJS) -o $(NAME)
$(DIROBJ)%.o: $(DIRSRC)%.c
#echo Compiling: $<
$(COMPILE) $(LIBS_INCLUDES) -c $< -o $#
clean:
#rm -rf $(DIROBJ)
fclean: clean
#rm -rf $(NAME)
re: fclean all
#
configure:
#mkdir -p $(DIROBJ)
#
libs:
#$(MAKE) -C $(LIBS)
.PHONY: all configure clean fclean re libs cleanlibs fcleanlibs relibs

It always relink because the configure rule will always run. So Make believes one of the dependencies changed, and it reevaluates the rule.
The way I would solve this would be to get rid of the configure rule and to move the #mkdir -p $(DIROBJS) in the rule that builds your object files:
$(DIROBJ)%.o: $(DIRSRC)%.c
#mkdir -p $(DIROBJS)
#echo Compiling: $<
$(COMPILE) $(LIBS_INCLUDES) -c $< -o $#
There might be more reasons (that could be related to the library you're also building), I don't know. Let us know if this solves it entirely.

#rtur's answer works, however I should mention another alternative. You could do:
$(DIROBJ):
mkdir $#
$(DIROBJ)/%.o: $(DIRSRC)/%.c | $(DIROBJ)
#echo Compiling: $<
$(COMPILE) $(LIBS_INCLUDES) -c $< -o $#
That way, it only makes the directory if it doesn't already exist. One thing to notice is the | symbol. This makes $(DIROBJ) an order-only prerequisite. This means if it's newer than the target, it will not cause the the target to rebuild. This is really important for directories, as the timestamp of a directory is the date the last item in it was added/deleted/modified, and your target would always be out of date without that symbol. This is considered cleaner, as you have less invocations of mkdir this way.
Also, as a style note, you usually, you don't include the trailing / at the end of directory names. $(OBJ_DIR)/%.o looks nicer than $(OBJ_DIR)%.o. Of course, that could just be my opinion :-)

I'm 42 network student.
I had this problem quite often as well.
Moving the .o files into a folder usually causes the Makefile to relink since that directory is not a 'dependency'.
Here's an example:
NAME = lib.a
INC = lib.h
FLAGS = -Wall -Wextra -Werror
LIB = function1.c function2.c function3.c function4.c
OBJ = $(SRC:%.c=%.o)
all: $(NAME) clear
$(NAME): $(OBJ)
#$(AR) rcs $# $^
#ranlib $(NAME)
%.o: %.c
#$(CC) $(FLAGS) -I $(INC) -c $< -o $#
clear:
#mkdir -p obj
#mv $(OBJ) obj
clean:
#$(RM) $(OBJ)
fclean: clean
#$(RM) $(NAME)
re: fclean all
The existence $(OBJ) are going to be checked when making $(NAME), not the 'obj' folder.
Solution:
NAME = lib.a
INC = lib.h
FLAGS = -Wall -Wextra -Werror
SRC = function1.c function2.c function3.c function4.c
DIR_OBJ = obj/
OBJ = $(SRC:%.c=$(DIR_OBJ)%.o)
all: $(NAME)
$(NAME): $(OBJ)
#$(AR) rcs $# $^
#ranlib $(NAME)
$(DIR_OBJ)%.o:%.c
#mkdir -p $(dir $#)
#$(CC) $(FLAGS) -I $(INC) -c $< -o $#
clean:
#$(RM) -rf $(DIR_OBJ)
fclean: clean
#$(RM) $(NAME)
re: fclean all
I think I covered it with this example, let me know if I missed a detail.
Good luck with your projects!

Related

Why is Makefile relinking?

I was trying to make a more complex Makefile with a src dir and a obj dir.
But doing that the Makefile is now relinking, and I don't understand why.
NAME = program
SRC = main.cpp
SRC_DIR = src/
OBJ = $(SRC:.cpp=.o)
OBJ_DIR = obj/
CC = c++
CFLAGS = -Wall -Werror -Wextra -std=c++98 -fsanitize=address
all: $(NAME)
$(OBJ): $(OBJ_DIR)
$(CC) $(CFLAGS) -c $(SRC_DIR)$(SRC) -o $(OBJ_DIR)$(OBJ)
$(OBJ_DIR):
mkdir $(OBJ_DIR)
$(NAME): $(OBJ)
$(CC) $(CFLAGS) $(OBJ_DIR)$(OBJ) -o $(NAME)
clean:
rm -rf $(OBJ_DIR)
fclean: clean
rm -f $(NAME)
re: fclean all
.PHONY: all clean fclean re
OBJ = $(SRC:.cpp=.o)
This becomes main.o
$(OBJ): $(OBJ_DIR)
$(CC) $(CFLAGS) -c $(SRC_DIR)$(SRC) -o $(OBJ_DIR)$(OBJ)
and this becomes:
main.o: obj/
c++ [options] -o obj/main.o
This will result in the compiler creating obj/main.o. main.o still does not exist. So, on the next make run, make will valiantly try to build it, with the same results (not to mention that an explicit dependency on a directory will create its own set of problems, too).

How to include a static library inside my static library with makefile?

I have the following subdirectories:
libftprintf/
-Makefile(1)
-ft_printf.h
-ft_printf.c
-ft_printf_source1.c
-ft_printf_source2.c
-libft/
-Makefile(2)
-ft_atoi.c
-ft_itoa.c
-...
And what I want is to call makefile(2) (which gives me a libft.a file) from makefile(1) and add all under the same libftprintf.a file.
How do I go about to do this?
My makefile:
SRC_FILES:=$(wildcard *.c)
NAME=libftprintf.a
CC=gcc
CFLAGS=-Wall -Wextra -Werror
OBJ_DIR=obj
HDR=ft_printf.h
SRC_NAMES=$(patsubst %.c,%.o,$(SRC_FILES))
SRC_NAMES_O=$(addprefix $(OBJ_DIR)/, $(SRC_NAMES))
$(OBJ_DIR):
mkdir $#
%.o: %.c $(HDR) $(OBJ_DIR)
$(CC) $(CFLAGS) -c $< -o $(OBJ_DIR)/$#
$(NAME): $(OBJ_DIR) $(SRC_NAMES)
ar -rc $# $(SRC_NAMES_O)
ranlib $#
all: $(NAME)
bonus: all
clean:
rm -rf obj/
sclean: clean
fclean: clean
re: sclean all
.PHONY: all clean fclean re so
It is not possible to combine two static libraries together into a single static library, directly. It's just not something that's supported by the toolchain.
If you are determined to do it the only way is to write a little script that will extract every object file from one of the libraries using ar x and add each one into the other library with ar r.
I fixed it by copying the first library libft.a and renaming it libftprintf.a and then ar -rcs it with the object files.
My Makefile:
SRC_FILES:=$(wildcard *.c)
NAME=libftprintf.a
LIBFT=libft/libft.a
CC=gcc
CFLAGS=-Wall -Wextra -Werror
OBJ_DIR=obj
HDR=ft_printf.h
SRC_NAMES=$(patsubst %.c,%.o,$(SRC_FILES))
SRC_NAMES_O=$(addprefix $(OBJ_DIR)/, $(SRC_NAMES))
$(OBJ_DIR):
mkdir $#
%.o: %.c $(HDR) $(OBJ_DIR)
$(CC) $(CFLAGS) -c $< -o $(OBJ_DIR)/$#
$(LIBFT):
make -C libft
$(NAME): $(LIBFT) $(OBJ_DIR) $(SRC_NAMES)
cp libft/libft.a $#
ar -rcs $# $(SRC_NAMES_O)
all: $(NAME)
bonus: all
clean:
rm -rf obj/
make -C libft $#
fclean: clean
rm -f libftprintf.a
make -C libft $#
re: fclean all
.PHONY: all clean fclean re so

Makefile does not work properly

I've this folder structure
project
|_src
| |_test
| |_main.cpp
|_Makefile
This is my makefile (trying to adapt from this link):
CC = g++
RM = rm
WFLAGS = -c -Wall -W
LDFLAGS =
SRCTESTD = src/test
EXECUTABLE = test
OBJD = .obj
DEPD = .dep
SRCSTEST = $(SRCTESTD)/main.cpp
OBJECTSTEST = $(patsubst %.cpp, $(OBJD)/test/%.o, $(notdir $(SRCSTEST)))
DEPDSTEST = $(patsubst %.cpp, $(DEPD)/test/%.d, $(notdir $(SRCSTEST)))
all: $(SRCSTEST) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTSTEST)
$(CC) $(LDFLAGS) $(OBJECTSTEST) -o $#
.cpp.o:
$(CC) $(WFLAGS) $< -o $#
It does not work, and I've this error
make: *** No rule to make target `.obj/test/main.o', needed by `test'. Stop.
What I'm doing wrong? Sorry for trivial question, but I'm a make newbie.
The link shows outdated methods, such as suffix rules. Making dependencies can also be done during compilation by gcc/g++.
As for the rest, here is it :
EXE := test
SRCDIR := src
OBJDIR := .obj
SRC := $(shell find $(SRCDIR) -name "*.cpp")
OBJ := $(SRC:$(SRCDIR)/%.cpp=$(OBJDIR)/%.o)
DEP := $(OBJ:.o=.d)
LDLIBS := # -l flags
LDFLAGS := # -L flags
CPPFLAGS := -MMD -MP # -I flags also
CXXFLAGS := -W -Wall # no -c flag here
.PHONY: all clean fclean re
all: $(EXE)
clean:
$(RM) -r $(OBJDIR)
fclean: clean
$(RM) $(EXE)
re: fclean all
-include $(DEP)
$(EXE): $(OBJ)
$(CXX) $(LDFLAGS) $^ $(LDLIBS) -o $#
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp
#mkdir -p $(#D)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $# -c $<
No redefinition of internally defined variables, no suffix rules, correct linking step and dependencies generation.
Update: To avoid calling mkdir for every source file, one should use order-only prerequisites and the special target .SECONDEXPANSION.
Change this block:
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp
#mkdir -p $(#D)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $# -c $<
To this:
.SECONDEXPANSION:
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp | $$(#D)/
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $# -c $<
%/:
mkdir $*
The error means make can't find a correct rule to build your object files. Your tree structure lacks some informations: only one file ? Where are the others ? Anyway, here are some hints:
In the last two lines, you are using an obsolete feature of make: suffix rules. I suggest you switch to a pattern rule, which is functionaly equivalent.
Say something like:
%.o: %.cpp
$(CXX) $(CXXFLAGS) $< -o $#
Another thing (that shouldn't be a problem here): you are using the variable CC which is internally defined as the default C compiler. It's okay because you redefine it, but as your sources seem to be C++ files, why not use the variable CXX, that is internally defined as the C++ compiler ?
Lastly, to make sure your set of files are correctly defined, you can print them with a dummy show target, see here.
show:
#echo "OBJECTSTEST=$(OBJECTSTEST)"
...

Why is makefile recompiling entire set of files if I only change one?

Here is my makefile... Why does it recompile all sources even if only one changes??
CC = g++
CFLAGS = -w -g -c
LIBS = -lm
EXEC = DFMS_PDS_L2_to_L3
.PHONY : clean tgz wdtgz
HOMEDIR = ../
BIN = bin
SRC = src
OBJ = obj
SRCFILES := $(wildcard $(SRC)/*.cc)
OBJFILES := $(patsubst %.cc, $(OBJ)/%.o, $(notdir $(SRCFILES)))
OBJS := $(patsubst %.cc, %.o, $(notdir $(SRCFILES)))
# Executable Targets
all: $(EXEC)
$(EXEC) : $(OBJS)
$(CC) $(LIBS) $(OBJFILES) -o $(BIN)/$(EXEC)
# Dependencies
%.o: $(SRC)/%.cc
$(CC) $< $(CFLAGS) -o $(OBJ)/$#
# Miscellaneous Targets
clean:
rm -rf $(BIN)/$(EXEC) obj/*.o *~
tgz:
tar cvzf $(HOMEDIR)cppbuild.tgz $(HOMEDIR)cppbuild --exclude=data
cp $(HOMEDIR)cppbuild.tgz $(HOMEDIR)cppbuild.tgz.allow
wdtgz:
tar cvzf $(HOMEDIR)cppbuild.tgz $(HOMEDIR)cppbuild
cp $(HOMEDIR)cppbuild.tgz $(HOMEDIR)cppbuild.tgz.allow
I'm running on Linux 3.0 with gnu make
Is it in the $(EXEC) definition?
My guess is that this recompiles all of the sources even if none changes.
Look at these two rules:
$(EXEC) : $(OBJS)
$(CC) $(LIBS) $(OBJFILES) -o $(BIN)/$(EXEC)
%.o: $(SRC)/%.cc
$(CC) $< $(CFLAGS) -o $(OBJ)/$#
Suppose foo.cc is the only source file. The first rule says that the target depends on foo.o, but actually builds it from obj/foo.o. The second can be invoked to build foo.o (which the first rule demands), but it actually builds obj/foo.o. So the first time you run Make it will build the executable correctly (and obj/foo.o). But every time thereafter, Make sees that foo.o does not exist and attempts to build it and rebuild the executable.
The solution is to rewrite the rules so that they build -- and depend on -- what they claim:
all: $(BIN)/$(EXEC)
$(BIN)/$(EXEC) : $(OBJFILES)
$(CC) $(LIBS) $^ -o $#
$(OBJ)/%.o: $(SRC)/%.cc
$(CC) $< $(CFLAGS) -o $#

Generate object files in subdirectory using a Makefile

I am trying to create a Makefile in order to generate object files in a subdirectory rather than let them in the src/ folder.
Here is the structure of the project:
Trunk
- Server
- src/
- include/
- Common
- src/
- include/
The Makefile is located in Trunk/Server. Source files are located both in Server/src and Common/src, so the Makefile currently has something like this:
SRC = src/main.cpp \
src/Network.cpp \
../Common/src/SQLManager.cpp \
../Common/src/Utils.cpp
I woud like to put generated object files in respective obj folders, so Trunk/Server/obj and Trunk/Common/obj. How can I achieve this? I've found many ways to generate object files in subdirectories (vpath, patsubst and many more) but I can't make any of them work for this folder organization.
Edit: If there is a way to put all object files in Server/obj/, that would be ok too.
Here's the complete Makefile (minus some source files and linked libraries):
Edit2: Updated with Didier Trosset's changes
CXX = g++
RM = rm -vf
NAME = Server
SRC = src/main.cpp \
src/Network.cpp \
../Common/src/SQLManager.cpp \
../Common/src/Utils.cpp
OBJ = $(subst src/,obj/, $(subst .cpp,.o, $(SRC)))
LDFLAGS = -lpthread -lm
CPPFLAGS = -std=c++0x -pedantic -Wextra -Wall -Wconversion -Iinclude -I../Common/include
all: Server
%.o: %.cpp
$(CXX) $< -o $#
Server: $(OBJ)
$(CXX) -o $(NAME) $(OBJ) $(LDFLAGS)
clean:
$(RM) $(OBJ) *~
fclean: clean
$(RM) $(NAME)
re: fclean Server
.PHONY: all clean fclean Server
Given these definitions, subst should be used to substitute the src part of the directory, and the file extension.
OBJ = $(subst src/,bin/,$(subst .cpp,.o,$(SRC)))
Then, you have to add new pattern rules to compile your source files. (You have to write one pattern rule per directory where your source files are.)
obj/%.o: src/%.cpp
$(CXX) -c $< -o $#
../Common/obj/%.o: ../Common/src/%.cpp
$(CXX) -c $< -o $#
I'm not sure that this will work, but I would try something like:
OBJ := $(join $(addsuffix ../obj/,$(dir $(SRC))),$(notdir $(SRC))
# or, as Didier suggested:
# OBJ := $(subst src/,obj/,$(SRC))
%.o: ../src/%.cpp
$(CXX) $< -o $#
It's not clear exactly what you're trying to do, but this should come close:
OBJ = $(subst src/,obj/,$(SRC:.cpp=.o))
obj/%.o : src/%.cpp
$(CXX) $< -o $#
../Common/obj/%.o : ../Common/src/%.cpp
$(CXX) $< -o $#

Resources