Echo make my Makefile relink on every Make - c++

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.

Related

Mult-output files with Makefile

I am a cuda programmer and new in vscode and Makefile environment.
For a better programming, I use multiple .cu files for my functions. Thus, for the pull_model and build_meshgrid functions, the makefile becomes:
# Target rules
all: build
build: kernel
check.deps:
ifeq ($(SAMPLE_ENABLED),0)
#echo "Launch file will be waived due to the above missing dependencies"
else
#echo "Launch file is ready - all dependencies have been met"
endif
kernel: kernel.o Engine/Engine.o Engine/pull_model.o Engine/build_meshgrid.o
$(EXEC) $(NVCC) $(ALL_LDFLAGS) $(GENCODE_FLAGS) -o $# $+ $(LIBRARIES)
$(EXEC) mkdir -p bin/$(TARGET_ARCH)/$(TARGET_OS)/$(BUILD_TYPE)
$(EXEC) cp $# bin/$(TARGET_ARCH)/$(TARGET_OS)/$(BUILD_TYPE)
%.o: %.cu
$(EXEC) $(NVCC) $(INCLUDES) $(ALL_CCFLAGS) $(GENCODE_FLAGS) -o $# -c $<
run: build
$(EXEC) ./kernel
testrun: build
clean:
rm -f kernel *.o Engine/*.o
rm -rf bin/$(TARGET_ARCH)/$(TARGET_OS)/$(BUILD_TYPE)/kernel
clobber: clean
I need to reduce the kernel somehow, like this:
kernel: kernel.o Engine/*.o
$(EXEC) $(NVCC) $(ALL_LDFLAGS) $(GENCODE_FLAGS) -o $# $+ $(LIBRARIES)
$(EXEC) mkdir -p bin/$(TARGET_ARCH)/$(TARGET_OS)/$(BUILD_TYPE)
$(EXEC) cp $# bin/$(TARGET_ARCH)/$(TARGET_OS)/$(BUILD_TYPE)
So, all .cu files under Engine folder are targed.
Best Regards!
Well, you can't use Engine/*.o because when you run your makefile, no object files exist and so this wildcard will expand to nothing, then nothing will be built (except kernel.o).
It's a catch-22 because you can't just tell make "build all the object files that you would build if you knew which objects to build!"
If what you want is to build object files for all source files in the Engine directory, you can tell make to do that:
SRCS := $(wildcard Engine/*.c)
OBJS := $(SRCS:%.c=%.o)
kernel: kernel.o $(OBJS)
....

How to use C++ modules with a Makefile?

I have a Makefile which is minimal, yet complete. It is the following:
OUT = example
INSTALL_DIR = /usr/local/bin
OBJECT = ./obj
SOURCE = ./src
SRC := $(shell find $(SOURCE) -name *.cc)
OBJ := $(SRC:%=$(OBJECT)/%.o)
DEPS := $(OBJ:.o=.d)
INC_DIRS := $(shell find $(SOURCE) -type d)
INC_FLAGS := $(addprefix -I,$(INC_DIRS))
CC = gcc
CFLAGS = -pipe -fmodules-ts -std=c++2a
DEBUG_FLAGS := $(CFLAGS) -g -Wall -Wextra
RELEASE_FLAGS := $(CFLAGS) -O3 -flto
debug: $(OBJ)
#echo "Building the DEBUG binary..."
#$(CC) $(OBJ) -o $(OUT) $(DEBUG_FLAGS)
#echo "The binary was built successfully!"
release: $(OBJ)
#echo "Building the RELEASE binary..."
#$(CC) $(OBJ) -o $(OUT) $(RELEASE_FLAGS)
#echo "The binary was built successfully!"
install: $(OUT)
#cp $(OUT) $(INSTALL_DIR)
uninstall:
#rm $(INSTALL_DIR)/$(OUT)
$(OBJECT)/%.cc.o: %.cc
#mkdir -p $(dir $#)
#echo "Building $#..."
#$(CC) $(CFLAGS) -c $< -o $#
.PHONY: clean
clean:
rm -rf $(OBJECT) $(OUT)
-include $(DEPS)
There is a directory called "src" which includes the source files. When I'm running make, I will get a compilation error about having to first create modules before using them. If I do create them manually, then I will be able to use "Make" and it will work then it will work. Is there a way to automatically create them?
I recommend using g++-11 instead of just gcc, since versions <=10 do not really include module support asides from the deprecated TS. Then also, use flag -std=c++20.
Also, I have (painful) experience using dependency files with gcc, since that particular feature is not really fully implemented. Last I checked (beginning of nov '21) the dependency files don't actually do anything as pertains to modules.
That being said, what you write should work. And it would, if the compiler-support for modules was finished.

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.

Makefile: compile objects to different directory and build from there

My Makefile:
CXX = clang++
CXXFLAGS = -g -Wall -std=c++14
LDFLAGS = -lboost_system -lcrypto -lssl -lcpprest -lpthread
OBJDIR = obj
SRCDIR = .
SRC := $(shell find $(SRCDIR) -name "*.cpp")
OBJ := $(SRC:%.cpp=%.o)
APP = run
all: $(APP)
$(APP): $(OBJ)
#echo "== LINKING EXECUTABLE $(APP)"
#$(CXX) $^ $(LDFLAGS) -o $(APP)
%.o: %.cpp
#echo "COMPILING SOURCE $< INTO OBJECT $#"
#$(CXX) -c $(CXXFLAGS) $< -o $#
clean:
find . -name *.o -delete
rm -f $(APP)
Directory structure:
Makefile
sources/
directory1
...cpp
directory2
...cpp
...
main.cpp
obj/
I try to make make create *.o files in a directory obj/ and then compile the final executable from there. I tried various approaches and they fail because of the project structure that stores *.cpp files in sub-directories. Particularly, I've tried the following: https://stackoverflow.com/a/26032630/2042546
I've also tried to manipulate the command itself clang++ $< -o obj/$# but it breaks whole idea of make and it's dependency management.
If I modify OBJ via patsubstr and notdir, make becomes unable to deduce dependency of a *.o on a corresponding *.cpp by it's path, cause *.o's path loses it's directory part and becomes unable to find it's *.cpp file when executing %.o:%.cpp rule (I hope I managed to write down my thoughts correctly).
If you want objects to live in the same source directory structure but under obj, then simply change your pattern rule (and how you generate the object files). And you should create the directory first:
OBJ := $(SRC:%.cpp=$(OBJDIR)/%.o)
...
$(OBJDIR)/%.o: %.cpp
#echo "COMPILING SOURCE $< INTO OBJECT $#"
#mkdir -p '$(#D)'
#$(CXX) -c $(CXXFLAGS) $< -o $#

Makefile Confusion

I'm new to makefiles, but I finally managed to get one working for a project I'm working on. The original goal was to search the folder "Source" for any CPP files, then create an Object file in the folder Products/Objs. Instead, it finds the CPP files, but OBJECT_FILES is the same as SOURCE_FILES, and I'm not sure how it's working. It doesn't generate any .o files (that I could see), but still compiles successfully. Super confused but would love some help. Thanks!
##########################################
# Editable options #
##########################################
# Program Name
EXECUTABLE=net
# Compiler options
CC=g++
CFLAGS=
LDFLAGS=
# Folders
SRC=Source
OBJ=Products/Objs
#########################################################
# Do Not Touch This #
#########################################################
SOURCE_FILES := $(shell find $(SRC)/ -type f -name '*.cpp')
## This should not work
OBJECT_FILES := $(SOURCE_FILES: $(SRC)/%.cpp=%.o)
## Like at all --> It's the same as SOURCE_FILES
## But I guess???
build: $(EXECUTABLE)
## Deletes the executable (assumes small compile time)
clean:
#rm -r -f $(shell find $(SRC)/ -type f -name '*.o')
#rm $(EXECUTABLE)
.PHONY: build clean
$(EXECUTABLE): $(OBJECT_FILES)
#$(CC) $(LDFLAGS) -o $# $^
#echo "Build successful!"
$(OBJECTS_FILES): %.o : $(SRC)/%.cpp
#$(CC) $(CFLAGS) -o -c $# $^
Well first you have a typo; you create a variable OBJECT_FILES:
OBJECT_FILES := $(SOURCE_FILES: $(SRC)/%.cpp=%.o)
Also you shouldn't use spaces here (after the :). Then you use a variable named OBJECTS_FILES instead:
$(OBJECTS_FILES): %.o : $(SRC)/%.cpp
That variable is empty so this is essentially a no-op.
Your compiler invocation is wrong. The word after the -o option is the file the output should go to; yours is:
#$(CC) $(CFLAGS) -o -c $# $^
which means that the output of this command is going to the file -c. Then the input is an object file that doesn't exist... most likely you'll get an error. Also you only want to pass the source file to the compiler, not all the other prerequisites (headers etc.) This should be:
#$(CC) $(CFLAGS) -c -o $# $<