makefile to link each other - c++

I have multiple unit test files in a dir test, say "test_a.cc" "test_b.cc" "test_c.cc"(each one has its main function), and want to build every one into a executable file, then I will get "test_a", "test_b", "test_c", each one is a executable file.So how to write a general makefile to achieve my goal?
Currently, I am using a makefile like this, I want to discard the '.out' suffix:
SOURCES = $(shell find . -name '*.cc')
OBJECTS = $(SOURCES:.cc=.o)
EXECUTABLE = $(SOURCES:.cc=.out)
all : $(EXECUTABLE)
%.out:%.cc
$(CC) $(CFLAGS) $< -o $#

"I want to discard the '.out' suffix"
The simplest way to achieve this would be renaming the executable file after it was build:
%.out:%.cc
$(CC) $(CFLAGS) $< -o $#
mv $# $(patsubst %.out,%,$#)
Another way would be to leave out the .out
SOURCES = $(shell find . -name '*.cc')
OBJECTS = $(SOURCES:.cc=.o)
EXECUTABLE = $(SOURCES:.cc=)
all : $(EXECUTABLE)
% : %.cc
$(CC) $(CFLAGS) $< -o $#

Related

Echo make my Makefile relink on every Make

I'm working on a Makefile that i can use on most of my school projects.
I only did basics makefile before and never had a problem, but for this one i wanted to put some colors etc...
And it relink everytime i make it.
I think the relink come from my echos ? But i'm not sure.
Here is my makefile :
#GENERAL
CC = clang++
FLAGS = -Wall -Wextra -Werror -std=c++98
RM = rm -rf
#PROJET
EXEC = ClapTrap
#FILES
SRCS = ClapTrap.cpp main.cpp
OBJS = $(SRCS:.cpp=.o)
OBJSDIR = objects/
#REGLES
.cpp.o: $(SRCS)
mkdir -p $(OBJSDIR)
echo "$(BLUE)Compiling $^ ..$(CLEAR)"
$(CC) $(FLAGS) -c $< -o $(addprefix $(OBJSDIR), $#)
echo " $(YELLOW)$(addprefix $(OBJSDIR), $#)$(CLEAR) [$(GREEN)OK$(CLEAR)]"
all: $(EXEC)
$(EXEC): $(OBJS)
echo "$(BLUE)========================================$(CLEAR)"
echo "$(BLUE) Compiling binary file ..$(CLEAR)"
echo "$(BLUE)========================================$(CLEAR)"
$(CC) -o $(EXEC) $(addprefix $(OBJSDIR), $^) $(FLAGS)
echo "$(YELLOW)$(EXEC)$(GREEN) is now ready to use !$(CLEAR)"
clean:
#$(RM) $(OBJSDIR)
#echo "$(RED)Cleaning up..$(CLEAR)"
fclean: clean
#$(RM) $(EXEC)
#echo -n "$(RED)$(EXEC)$(CLEAR)"
re: fclean all
.PHONY: all
Thank's for reading !
EDIT :
So i removed SRCS from my .cpp.o rules dependencies, but still relinking.
Here the updated Makefile :
#FILES
SRCS = ClapTrap.cpp main.cpp
OBJS = $(SRCS:.cpp=.o)
OBJSDIR = objects
#REGLES
.cpp.o:
echo "$(BLUE)Compiling $(YELLOW)$^$(BLUE) ..$(CLEAR)"
mkdir -p $(OBJSDIR)
$(CC) $(FLAGS) -c $< -o $#
mv $# $(OBJSDIR)
echo "$(BLUE) - $(YELLOW)$#$(CLEAR) [$(GREEN)OK$(CLEAR)]"
all: $(EXEC)
$(EXEC): $(OBJS)
echo "$(BLUE)========================================$(CLEAR)"
echo "$(BLUE) Compiling binary file ..$(CLEAR)"
echo "$(BLUE)========================================$(CLEAR)"
$(CC) $(FLAGS) $(STD) $(addprefix $(OBJSDIR)/, $(OBJS)) -o $(EXEC)
echo "$(YELLOW)$(EXEC)$(GREEN) is now ready to use !$(CLEAR)"
This is wrong:
$(CC) $(FLAGS) -c $< -o $#
mv $# $(OBJSDIR)
When make runs your recipe it will put the file it expects you to build into the $# automatic variable. If your makefile builds some OTHER file, not the one it asked you to build, then the next time you run make it will see that the file it wants doesn't exist (because you didn't build it, you build some other file) and so it's always out of date.
Your rules must always build exactly the file $#, not some other file.
It's not actually possible to write a makefile that puts targets in a different directory, using suffix rules. They can only create files in the same directory. That's (one reason) why GNU make supports pattern rules which are much more flexible.
If you have to write a POSIX conforming makefile that doesn't support pattern rules, and you want to put the object files in some other directory, all you can do is write out all the targets and their rules explicitly.

Getting wrong file name while pattern matching in makefile

The directory structure of my project is something like this:
|-build
|-src
|-lib
|-libfile1.hpp
|-libfile1.cpp
|-libfile2.hpp
|-libfile2.cpp
|-libfile3.hpp
|-Makefile(lib)
|-examples
|-pingpong
|-main.cpp
|-ping.cpp
|-ping.hpp
|-Makefile(ping)
My goal is to have many examples in the examples folder which all use the libfiles but are independent of each other. Hence I wanted to use separate makefiles in each of the example folders to link to objects of libfiles.
To that goal, here's makefile(lib):
SRC = .
BLD = ../../build
SOURCE = $(wildcard $(SRC)/*.cpp)
INCLUDE = $(wildcard $(SRC)/*.hpp)
OBJECT = $(patsubst %,$(BLD)/%, $(notdir $(SOURCE:.cpp=.o)))
CC = g++
#flags went here, removed for brevity
all: $(OBJECT)
$(BLD)/%.o: $(SRC)/%.cpp $(SRC)/%.hpp
mkdir -p $(dir $#)
$(CC) -c $< -o $#
.PHONY: clean
clean:
$(RM) -r $(BLD)
And here's makefile(ping), where I try to build local objects and pass the library object build pattern to makefile(lib):
TARGET = mainpingpong.out
SRC = ../../actorlib
BLD = ../../../build
LIBSOURCE = $(wildcard $(SRC)/*.cpp)
LIBINCLUDE = $(wildcard $(SRC)/*.hpp)
LIBOBJECT = $(patsubst %,$(BLD)/%, $(notdir $(LIBSOURCE:.cpp=.o)))
LOCSOURCE = $(wildcard *.cpp)
LOCINCLUDE = $(wildcard *.hpp)
LOCOBJECT = $(patsubst %,$(BLD)/%, $(notdir $(LOCSOURCE:.cpp=.o)))
CC = g++
$(TARGET) : $(LIBOBJECT) $(LOCOBJECT)
$(CC)-o $# $^
$(LOCOBJECT): $(LOCSOURCE) $(LOCINCLUDE)
mkdir -p $(dir $#)
$(CC) -c $< -o $#
$(LIBOBJECT): $(LIBSOURCE) $(LIBINCLUDE)
cd $(SRC) && $(MAKE)
.PHONY: clean
clean :
cd $(SRC) && $(MAKE) clean
The error occurs in my local file matching, where it associates both main.o and ping.o with main.cpp (everything else works fine):
mkdir -p ../../../build/
g++ -c main.cpp -o ../../../build/main.o
mkdir -p ../../../build/
g++ -c main.cpp -o ../../../build/ping.o
How do I correctly do what I'm trying to do? Should I have a different rule or target? Or is there a correct way to get the filename from the variable?
I want the .o files to end up in the same place but the executable to stay in the examples directory.
The problem is here:
$(LOCOBJECT): $(LOCSOURCE) $(LOCINCLUDE)
mkdir -p $(dir $#)
$(CC) -c $< -o $#
LOCSOURCE contains main.cpp ping.cpp, so this rule makes both source files prerequisites of each target. Whether Make is trying to build main.o or ping.o, the prerequisite list is the same: main.cpp ping.cpp ping.hpp. So the automatic variable $< always expands to main.cpp (since that is the first filename in the list).
One way to solve this is by means of a static pattern rule:
$(LOCOBJECT): $(BLD)/%.o: %.cpp $(LOCINCLUDE)
mkdir -p $(dir $#)
$(CC) -c $< -o $#
This is still imperfect, in that all local header files are prerequisites of each object from a local source. If you have a paddle.cpp and you modify ping.hpp, Make will rebuild paddle.o, even if paddle.cpp does not depend on ping.hpp in any way. This is not a serious problem, it simply means that Make will do some extra work, rebuilding things when there is no reason to. If you want to solve it, you can either write the dependencies into the makefile by hand, or use a more sophisticated method like automatic dependency generation.

Error when executing make

I am trying to create a makefile for my project, but i seem to run into some errors, as I am testing new things. My file structure is as such:
~/main #root project folder
~/main/include #header files (mostly class headers)
~/main/src #source files
~/main/src/obj #object files
Makefile
(Makefile is in the root project folder)
Makefile:
CC=g++
IDIR=include
SDIR=src
ODIR=src/obj
DEPS=$(IDIR)/%.h
OBJS=$(ODIR)/%.o
SRCS=$(SDIR)/%.cpp
CFLAGS=-Wall -std=c++11 -I$(IDIR)
$(OBJS): $(SRCS) $(DEPS)
$(CC) -c -o $# $< $(CFLAGS)
all: $(OBJS)
gcc -o run $^ $(CFLAGS)
.PHONY: clean
clean:
rm -f $(OBJS)
For testing purposes I have a single main.cpp in src folder and a random header file in include folder. The error I am getting when running the simple make command is the following:
make: *** No rule to make target `src/obj/%.o', needed by `all'. Stop.
EDIT : With the help of the guys below i came up with the solution
CC=g++
IDIR=include
SDIR=src
ODIR=src/obj
CFLAGS=-Wall -std=c++11 -I$(IDIR)
_DEPS = yo.h
DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS))
_OBJ = main.o
OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))
_SRC = main.cpp
SRC = $(patsubst %,$(SDIR)/%,$(_SRC))
$(ODIR)/%.o: $(SRC) $(DEPS)
$(CC) -c -o $# $< $(CFLAGS)
all: $(OBJ)
$(CC) -o run $^ $(CFLAGS) $(LIBS)
.PHONY: clean
clean:
rm -f $(OBJS)
There is a difference in using % in your two cases. When you write:
$(ODIR)/%.o : $(SDIR)/%.cpp $(IDIR)/%.h
that will do pattern substitution, and create a bunch of rules like:
$(ODIR)/foo.o : $(SDIR)/foo.cpp $(SDIR)/foo.h
So it's fine there, although you should use the % explicitly there so it's clear to see what the rule is doing.
But when you use it here:
all : $(ODIR)/%.o
That is literally looking for the target $(ODIR)/%.o for which you don't have a rule. There's no substitution. And you don't have a rule to make that target - hence the error. What you meant to do was have all depend on all the actual objects, for which you'll want to use the wildcard function:
SOURCES = $(wildcard $(SDIR)/*.cpp)
OBJECTS = $(SOURCES:$(SDIR)/%.cpp=$(ODIR)/%.o)
all : $(OBJECTS)
gcc -o run $^ $(CFLAGS)
When you use
OBJS=$(ODIR)/%.o
The %.o part does not expand to anything meaningful. It just remains as the literal value %.o. Same problem exists for DEPS and SRCS as well.
You need to use the wildcard and patsub functions. Instead of
DEPS=$(IDIR)/%.h
OBJS=$(ODIR)/%.o
SRCS=$(SDIR)/%.cpp
use
DEPS=$(wildcard $(IDIR)/*.h)
SRCS=$(wildcard $(SDIR)/*.cpp)
OBJS=$(patsub %.cpp,%.o,$(SRCS))

object files need to be placed in different directory

I would appreciate if anyone could help me with the Makefile error. I would like to compile a C++ application into a shared library and place the compiled object *.o files in ./sobjs directory like below. I followed several examples to do this, however I still have the problem to get this correct compilation and linker.
Makefile:
OBJS = a1.o a2.o a3.o a4.o a5.o
objects = sobj/$(OBJS)
all: $(objects)
$(CXX) $(CXX_FLAGS) $(objects) -shared -o libname.so
$(objects) : | sobjs
sobjs:
#mkdir -p $#
sobjs/%.o: %.cpp
#echo $<
$(CXX) -fPIC -c -o $# $< $(CXX_FLAGS) $(MY_FLAGS) $(INCLUDE_DIRS)
I made a mistake. Replace this
objects = sobj/$(OBJS)
with this
objects = $(patsubst %.o, sobjs/%.o,$(OBJS))
and it will now compile files correctly.

a couple of Makefile issues

I've got this Makefile:
CFLAGS = -c -Wall
CC = g++
EXEC = main
SOURCES = main.cpp listpath.cpp Parser.cpp
OBJECTS = $(SOURCES: .cpp=.o)
EXECUTABLE = tp
DIR_SRC = /src/
DIR_OBJ = /obj/
all: $(SOURCES) $(OBJECTS)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(CFLAGS) $(OBJECTS) -o $#
.cpp.o:
$(CC) $(CFLAGS) $< -o $#
clean:
rm $(OBJECTS) $(EXECUTABLE)
Note this:
I'm in the directory "." which contains the makefile
The folder "./src" EXISTS, and has all the .h and .cpp files
The folder "./obj" doesn't exist, I want makefile to create it and put all the .o there
The error I get is:
No rules to build "main.cpp", necessary for "all". Stopping.
Help!
All right, from the top:
CFLAGS = -c -Wall
CC = g++
# EXEC = main never used, not needed
SOURCES = main.cpp listpath.cpp Parser.cpp
So far, so good. Note that this SOURCES doesn't mention DIR_SRC, so we'll have to make that connection later (and $(DIR_SRC)$(SOURCES) won't work, because the path must be appended to each member of the list). But OBJECTS really needs paths (e.g. /obj/main.o):
OBJECTS = $(patsubst %.cpp, $(DIR_OBJ)%.o, $(SOURCES))
EXECUTABLE = tp
DIR_SRC = /src/
DIR_OBJ = /obj/
(Personally I don't like putting the trailing slash in the variable, but it's a matter of taste.) The first target is the default target, so it should build what you actually want built:
all: $(EXECUTABLE)
Don't worry about listing the sources as prerequisites; they will sort themselves out later.
$(EXECUTABLE): $(OBJECTS)
$(CC) $(CFLAGS) $^ -o $# # <-- note the automatic variable $^
The .cpp.o convention doesn't really work here; we'll have to spell it out. And we must tell Make to search $(DIR_SRC) for .cpp files:
$(OBJECTS): $(DIR_OBJ)%.o: %.cpp $(DIR_OBJ)
$(CC) $(CFLAGS) $< -o $#
$(DIR_OBJ):
mkdir $#
vpath %.cpp $(DIR_SRC)
And tell Make that clean is not a real target, just to be safe:
.PHONY: clean
clean:
rm $(OBJECTS) $(EXECUTABLE)
EDIT:
I shouldn't have attempted so much in one step. Let's try something simpler:
$(DIR_OBJ)%.o: $(DIR_SRC)%.cpp $(DIR_OBJ)
$(CC) $(CFLAGS) $< -o $#
Edit the SOURCES to include the source directory (e.g. src/main.cpp etc.).
For the object files, consider something like this:
OBJECTS = $(subst src/,obj/,$(SOURCES:%.cpp=%.o))
# ...
all: $(SOURCES) build
.PHONY: build
build: pre_build $(EXECUTABLE)
.PHONY: pre_build
pre_build: obj
obj:
-mkdir obj
$(EXECUTABLE): $(OBJECTS)
$(CC) $(CFLAGS) $^ -o $#