Why is Makefile relinking? - makefile

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).

Related

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

How to avoid my makefile to relink

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!

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 $#

Getting make to create object files in a specific directory

GNU Make 3.82
gcc 4.7.2
c89
I have the following make file:
INC_PATH=-I/home/dev_tools/apr/include/apr-1
LIB_PATH=-L/home/dev_tools/apr/lib
LIBS=-lapr-1 -laprutil-1
RUNTIME_PATH=-Wl,-rpath,/home/dev_tools/apr/lib
CC=gcc
CFLAGS=-Wall -Wextra -g -m32 -O2 -D_DEBUG -D_THREAD_SAFE -D_REENTRANT -D_LARGEFILE64_SOURCE $(INC_PATH)
SOURCES=$(wildcard src/*.c)
OBJECTS=$(patsubst %.c, %.o, $(SOURCES))
EXECUTABLE=bin/to
all: build $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(CFLAGS) -o $# $(RUNTIME_PATH) $(OBJECTS) $(LIB_PATH) $(LIBS)
$(OBJECTS): $(SOURCES)
$(CC) $(CFLAGS) -c $(SOURCES) $(LIB_PATH) $(LIBS)
build:
#mkdir -p bin
clean:
rm -rf $(EXECUTABLE) $(OBJECTS) bin
find . -name "*~" -exec rm {} \;
find . -name "*.o" -exec rm {} \;
My directory structure is like this project/src project/bin. My Makefile is in the project (root) folder, and all my *.h and *.c are in the src directory. Currently I have only one source file called timeout.c
I get this error:
gcc: error: src/timeout.o: No such file or directory
I have used this to get all the source files:
SOURCES=$(wildcard src/*.c)
And the object files:
OBJECTS=$(patsubst %.c, %.o, $(SOURCES))
However, the make seems to create the object file in the project root folder where the Makefile is. Should it not put it in the src directory?
You have two problems in this rule (well, three):
$(OBJECTS): $(SOURCES)
$(CC) $(CFLAGS) -c $(SOURCES) $(LIB_PATH) $(LIBS)
You haven't noticed yet, but the rule makes each object dependent on all sources, and tries to build that way. Not a problem as long as you have only one source. Easy to fix with a static pattern rule and an automatic variable:
$(OBJECTS): src/%.o : src/%.c
$(CC) $(CFLAGS) -c $< $(LIB_PATH) $(LIBS)
Also, the command ("$(CC)...") doesn't specify an output file name, so gcc will infer it from the source file name; if you give it src/timeout.c, it will produce timeout.o (in the working directory, project/). So you should specify the desired path to the output file. Easy to do with another automatic variable:
$(OBJECTS): src/%.o : src/%.c
$(CC) $(CFLAGS) -c $< $(LIB_PATH) $(LIBS) -o $#
Use gcc's -o option to write the output file to a particular location. For instance, you could say:
$(CC) $(CFLAGS) -c $(SOURCES) $(LIB_PATH) $(LIBS) -o $(OBJECTS)
Unfortunately, there's a problem with this line: if there is more than one source file in $(SOURCES), it won't work, since $(OBJECTS) will also contain multiple file names, and the -o option only binds to the first argument.
A way to compile each file in a list of source code files is to use implicit rules. In gmake, you would write:
$(EXECUTABLE): $(OBJECTS)
$(CC) $(CFLAGS) -o $# $(RUNTIME_PATH) $(OBJECTS) $(LIB_PATH) $(LIBS)
%.o : %.c
$(CC) $(CFLAGS) -c $< -o $#
where $< is replaced with name of the input file and $# is replaced with the name out the output file.
I solved this request and here is my Makefile and directory tree.
PROJECT := main.exe
DIR_SRC += .
DIR_SRC += ./src
DIR_INC += -lpthread
DIR_INC += -I./inc
DIR_INC += $(addprefix -I, $(DIR_SRC))
SRC_C += $(wildcard $(addsuffix /*.c, $(DIR_SRC)))
#OBJ := $(filter %.o, $(SRC_C:.c=.o))
OBJ := $(patsubst %.c, %.o, $(SRC_C))
EXE := $(PROJECT)
CC_PREFIX :=
CC := $(CC_PREFIX)gcc
CFLAG =
CLIB = -L .
.PHONY:all
all:$(OBJ) $(EXE)
%.o: %.c
$(CC) $(CFLAG) $(DIR_INC) -c $< -o $#
$(EXE): $(OBJ)
$(CC) $(CFLAG) $(CLIB) $(OBJ) -o $#
clean:
rm -r $(EXE) $(OBJ)
See my directory tree:

clever linker dependncies

My project is compiled with make and have recently added the boost library for unit testing.
The directory structure is as follows:
Project/
main.cpp
main.hpp
Makefile
sources/
classA.cpp
includes/
classA.hpp
objects/
test/
Makefile
unit_test_classA.cpp
In the folder Project directory I run:
$ make test
Everything works fine except that I don't know how to tell to make to run test/Makefile and look for dependencies in ../object dir automatically.
I'm trying to keep the makefile generic because I build many objects and want to separate my development and testing.
the question is: I need a makefile rule for looking automatically .o files into a especific dir
The Makefiles
# Project/Makefile
BUILD = snake
LDFLAGS =
LDLIBS = -lsfml-graphics -lsfml-window -lsfml-audio -lsfml-system
CXXFLAGS = -Wall -I./includes
RM = rm -rf
OBJ_DIR = objects/
SRC_DIR = sources/
OBJS = $(patsubst $(SRC_DIR)%, \
$(OBJ_DIR)%, \
$(patsubst %.cpp,%.o,$(wildcard $(SRC_DIR)*.cpp)))
OBJECTS = main.o $(OBJS)
all: $(BUILD)
test:
cd test; $(MAKE)
$(BUILD): $(OBJECTS)
$(CXX) $(LDFLAGS) $(LDLIBS) $(OBJECTS) -o $#
$(OBJ_DIR)%.o: $(SRC_DIR)%.cpp $(OBJ_DIR)
$(CXX) $(CXXFLAGS) -c $< -o $#
clean:
$(RM) $(OBJECTS) $(OBJ_DIR)
mkdir $(OBJ_DIR)
.PHONY: test
# Project/test/Makefile
BUILD = boost_test
LDFLAGS =
LDLIBS = -lboost_unit_test_framework
CXXFLAGS = -Wall -I./../includes
RM = rm -rf
OBJS = $(patsubst %.cpp,%.o,$(wildcard *.cpp))
OBJECTS = $(OBJS)
all: clean $(BUILD)
./$(BUILD)
$(BUILD): $(OBJECTS)
$(CXX) $(LDFLAGS) $(LDLIBS) $(OBJECTS) -o $#
%.o: %.cpp
$(CXX) $(CXXFLAGS) -c $< -o $#
clean:
$(RM) $(OBJECTS)
.PHONY: $(BUILD)

Resources