How to prevent my makefile to relink due to static library - c++

I have a Makefile which works well when there is not static library to compile:
CC = g++ -std=c++11
RM = rm -f
NAME = hello
SRCS = Main.cpp \
srcs/Controller.cpp \
...
srcs/Parser.cpp
OBJS = $(SRCS:.cpp=.o)
CPPFLAGS += -W -Wall -Wextra -Werror
all : $(NAME)
$(NAME) : $(OBJS)
$(CC) $(CPPFLAGS) $(CFLAGS) -o $(NAME) $(OBJS) -I./inc
clean :
$(RM) $(OBJS)
fclean : clean
$(RM) $(NAME)
re : fclean all
.PHONY : all clean fclean re
This makefile works and doesn't relink (when I type twice "make", it doesn't recompile and output "Nothing to be done for all")
But when I want to compile a static library, the "make" command recompile the library without outputing "Nothing to be done for all", here is the new Makefile containing the static lib:
CC = g++ -std=c++11
RM = rm -f
NAME = hello
LIBNAME = libhello.a
SRCS = srcs/Controller.cpp \
...
srcs/Parser.cpp
OBJS = $(SRCS:.cpp=.o)
CPPFLAGS += -W -Wall -Wextra -Werror
all : $(NAME)
$(NAME) : $(OBJS)
ar rc $(LIBNAME) $(OBJS)
$(CC) $(CPPFLAGS) $(CFLAGS) -o $(NAME) $(LIBNAME) Main.cpp -I./inc
clean :
$(RM) $(OBJS)
$(RM) $(LIBNAME)
fclean : clean
$(RM) $(NAME)
re : fclean all
.PHONY : all clean fclean re
How could I fix that problem to prevent the makefile to recompile when the static library has already been compiled and doesn't need to be recompiled ?
Thank you very much

regarding this recipe:
$(NAME) : $(OBJS)
$(CC) $(CPPFLAGS) $(CFLAGS) -o $(NAME) $(OBJS) -I./inc
it is expecting that the default compile statement will be used to generate the object files and make will generate those object files before executing the rule. and since it is not performing any compiles in this recipe, the parameter -I./inc is unneeded.
Without the header files being listed in the dependencies, changing a header file will fail to cause the associated source files to be recompiled.
Suggest:
HEADERS := ..
$(name): $(OBJS)
<tab> $(CC) -o $# $(OBJS) $(LFLAGS)
%.o:%.cpp $(HEADERS)
<tab> $(CC) $(CPPFLAGS) -c $< -o $# -I./inc
Note in the line:
CPPFLAGS += -W -Wall -Wextra -Werror
the -W turns off all the previously enabled warnings, probably not what you want, suggest removing that parameter.
Similar considerations need to be applied when creating the static library, similar to:
this line:
$(NAME) : $(OBJS)
ar rc $(LIBNAME) $(OBJS)
$(CC) $(CPPFLAGS) $(CFLAGS) -o $(NAME) $(LIBNAME) Main.cpp -I./inc
becomes:
HEADER := ...
all: $(LIBNAME) $(NAME)
$(LIBNAME): $(OBJS)
<tab> ar rc -o $# $^
%.o:%.cpp
<tab> $(CC) $(CPPFLAGS) -c $< -o $# -I./inc
$(NAME): main.o $(LIBNAME)
<tab> $(CC) $< -o $# $(LFLAGS) -l$(LIBNAME)

The issue is that $NAME is a phony target due to this rule:
all : $(NAME)
I think the issue can be resolved by instead changing it to an actual target:
all : $(LIBNAME)
Also, you have this rule:
$(NAME) : $(OBJS)
ar rc $(LIBNAME) $(OBJS)
$(CC) $(CPPFLAGS) $(CFLAGS) -o $(NAME) $(LIBNAME) Main.cpp -I./inc
It is a bit confusing: The library is built as $LIBNAME, but then it goes on to link an executable named $NAME. So everytime you make a change to Main.cpp, the library has to be rebuilt.

Your rule for $(NAME) doesn't actually make a file called $(NAME) (i.e. hello), so make will try and remake it every time. The recipe must match the rule (and this is why you should use automatic variables as in the last example below):
all: $(LIBNAME)
$(LIBNAME): $(OBJS)
ar rc $(LIBNAME) $(OBJS)
GNU make also has built-in archive functionality, although it doesn't play well with parallel make:
ARFLAGS := rc
all: $(LIBNAME)($(OBJS))
A more idiomatic, parallel-safe way would be something like
ARFLAGS := rc
.PHONY: all
all: $(LIBNAME)
$(LIBNAME): $(OBJS)
$(AR) $(ARFLAGS) $# $^

Related

Library not loaded: #rpath/libMatlabEngine.dylib

I'm pretty much a novice when it comes to coding.
I'm trying to visualize a game in C++ using Matlab.
The makefile was partially given as part of the exercise.
I tried fixing the problem by using this: https://de.mathworks.com/help/matlab/matlab_external/custom-linking-to-required-api-libraries.html
The code works but when trying to implement the "GUI" this error comes up:
dyld[45987]: Library not loaded: #rpath/libMatlabEngine.dylib
Reason: tried: '/Applications/MATLAB_R2020a.app/bin/maci64/libMatlabEngine.dylib' (no such file), '/Applications/MATLAB_R2020a.app/sys/os/maci64/libMatlabEngine.dylib' (no such file), '/libMatlabEngine.dylib' (no such file), '/usr/local/lib/libMatlabEngine.dylib' (no such file), '/usr/lib/libMatlabEngine.dylib' (no such file)
MATLAB_ROOT=/Applications/MATLAB_R2020a.app
Gpp=g++
LD=g++
CPPFLAGS=-MMD -MP -std=c++11 -Wpedantic \
-I ${MATLAB_ROOT}/extern/include/ -pthread
LDFLAGS=-L ${MATLAB_ROOT}/extern/bin/maci64/ -pthread
LDLIBS=-lMatlabDataArray -lMatlabEngine
srcs = $(wildcard *.cpp)
objs = $(srcs:.cpp=.o)
deps = $(srcs:.cpp=.d)
targets = viergewinnt
default: viergewinnt
run: viergewinnt
LD_LIBRARY_PATH=\
${MATLAB_ROOT}extern/bin/maci64:${LD_LIBRARY_PATH} \
./viergewinnt
viergewinnt: viergewinnt.o cviergewinnt.o cviergewinntGUI.o
$(LD) $(LDFLAGS) -o $# $^ $(LDLIBS)
%.o: %.cpp
$(Gpp) $(CPPFLAGS) -c $< -o $#
.PHONY: clean
clean:
$(RM) $(targets) $(objs) $(deps) *~
-include $(deps)

Using Makefile compile multiple .cpp in diferent folders to a single build/ directory [duplicate]

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:

How to write specific rule for a target in makefile?

I know the title is quite ambiguous but I just don't know how to describe my problem concisely. Please edit that if you want.
Currently my makefile is like the following:
CC = g++
CFLAGS = -Wall -g
TARGET = foobar
SRC_FILES = foo.cpp bar.cpp main.cpp
OBJ_FILES := $(SRC_FILES:.cpp=.o)
$(TARGET): $(OBJ_FILES)
$(CC) $(CFLAGS) $^ -o $#
%.o: %.cpp %.h
$(CC) $(CFLAGS) -c $<
clean:
rm -rf *.o $(TARGET)
The problem is that this structure requires main.cpp to have a main.h header file, which I don't really have. How can I handle this nicely?
GCC (and probably Clang) can build a list of dependencies for you; This way, you can simply make your object files from their source (cpp) file:
depend: .depend
.depend: $(SRC_FILES)
rm -f ./.depend
$(CC) $(CFLAGS) -MM $^ -MF ./.depend;
include .depend
%.o: %.cpp
$(CC) $(CFLAGS) -c $<
You might also find interest in the makedepend tool.

Automating my Makefile

I am learning to create a makefile. My folder structure looks like this..
Project
bin //this is where the executable "e" is kept
e
obj //this is where the obj files generated are kept
Node.o
Node1.o
src //this is where .cpp files resides
Folder
Node.cpp
Folder2
Node1.cpp
include //this is where .hhp files resides
Folder
Node.hpp
Folder2
Node1.hpp
makefile
I am using Ubuntu 12.04 and trying to compile it using g++. The makefile resides in the project folder along with folders: src, include, obj and bin
My makefile looks like this
CC = g++
DEBUG = -g
CFLAGS = -Wall -c $(DEBUG)
LFLAGS = -Wall $(DEBUG)
TARGET = bin/
OBJ = obj/
INCLUDE = include/
SRC = src/
SOURCES=$(wildcard $(SRC)**/*.cpp $(SRC)*.cpp)
HEADERS=$(wildcard include/**/*.hpp include/*.hpp)
OBJECTS=$(patsubst %.cpp,$(OBJ)%.o,$(notdir $(SOURCES)))
All : $(TARGET)e
$(TARGET)e : make_dir $(OBJECTS)
$(CC) $(LFLAGS) $(OBJECTS) -o $#
$(OBJ)Node.o : $(SRC)Folder/Node.cpp $(HEADERS)
$(CC) $(CFLAGS) -I$(INCLUDE) $< -o $#
$(OBJ)Node1.o : $(SRC)Folder2/Node1.cpp $(HEADERS)
$(CC) $(CFLAGS) -I$(INCLUDE) $< -o $#
make_dir:
mkdir -p obj bin
clean :
-rm -rf bin
-rm -rf obj
-rm -f e *.o *~
This piece of code runs just fine but what I would like to do is to replace the below code snippets
$(OBJ)Node.o : $(SRC)Folder/Node.cpp $(HEADERS)
$(CC) $(CFLAGS) -I$(INCLUDE) $< -o $#
$(OBJ)Node1.o : $(SRC)Folder2/Node1.cpp $(HEADERS)
$(CC) $(CFLAGS) -I$(INCLUDE) $< -o $#
with some thing more like
%.o : %.cpp $(HEADERS)
$(CC) $(CFLAGS) -I$(INCLUDE) $< -o $#
Something that generalizes the whole feeding and mapping. In other words, automate the makefile in a way I shouldn't worry or edit until the hierarchy is disturbed.
$(OBJ)/%.o : $(SRC)Folder/%.cpp $(HEADERS)
$(CC) $(CFLAGS) -I$(INCLUDE) $< -o $#

How to change my makefile to build into a separate folder

I have the following makefile:
CC=g++
CCOPTS=-Wall -Wextra -g
OBJS = manager.o tcpcon.o
TARGETS = manager
.PHONY: all clean
$(TARGETS) : $(OBJS)
$(CC) -o $# $^ $(CFLAGS) $(LIBS)
all: $(TARGETS) $(OBJS)
clean:
rm -f $(TARGETS) $(OBJS)
%: %.cpp
$(CC) $(CCOPTS) -o $# $<
Is there a way I can make my .o and bin files be built into a directory called build? I tried going through some tutorials, but I guess I just don't fully understand makefiles..
Don't feel too bad; I'm not sure anyone fully understands makefiles.
BUILD_DIR = build
OBJS = $(BUILD_DIR)/manager.o $(BUILD_DIR)/tcpcon.o
TARGETS = $(BUILD_DIR)/manager
...
$(BUILD_DIR)/%.o: %.cpp
$(CC) -c $(CCOPTS) -o $# $<