Why this makefile is always recompiling? - c++

I've done a makefile for a project I'm working on andd my code is allways getting recompiled, and I don't know why... I've tried adding the .PHONY to the all target but didn't work. Here is the makefile:
TARGET = csv2sqlite
CXX = g++
CXXFLAGS = -std=c++11 -Wall -I $(INCDIR) -fdiagnostics-color=always -D_DEBUG
OBJECTS = csv.o main.o
BINDIR = bin
OBJDIR = obj
INCDIR = inc
SRCDIR = src
.PHONY:default
default: $(OBJECTS) $(TARGET)
%.o: $(SRCDIR)/%.cpp
#echo "Compiling dependecies..."
$(CXX) $(CXXFLAGS) -c $< -o $(OBJDIR)/$#
#echo "Done compiling $#"
$(TARGET): $(addprefix $(OBJDIR)/, $(OBJECTS))
#echo "Linking $# file..."
$(CXX) $(CXXFLAGS) $^ -o $(BINDIR)/$#
#echo "Linking $# file..."
run:
bin/$(TARGET)
clean:
rm -f obj/* bin/$(TARGET)
And the directory tree is:
project
├── inc
│ └── csv.hpp
├── src
│ ├── csv.cpp
│ └── main.cpp
├── obj
│ ├── csv.o
│ └── main.o
├── bin
│ └── csv2sqlite
└── makefile
Here is the complete project if you wanna see it. Also, what kind of improves I can do it?
Thanks!

Here:
%.o: $(SRCDIR)/%.cpp
...
$(CXX) $(CXXFLAGS) -c $< -o $(OBJDIR)/$#
#echo "Done compiling $#"
No, you're not. You didn't build foo.o, you built obj/foo.o, so the next time you tell Make to build foo.o, it will see that foo.o does not exist and attempt to rebuild it-- with this rule, which doesn't do what it claims to do. Likewise:
$(TARGET): $(addprefix $(OBJDIR)/, $(OBJECTS))
#echo "Linking $# file..."
$(CXX) $(CXXFLAGS) $^ -o $(BINDIR)/$#
#echo "Linking $# file..."
This doesn't build $(TARGET), it builds $(BINDIR)/$(TARGET), so Make runs this rule every time it's told to build $(TARGET).
The fix is simple:
OBJECTS = $(addprefix $(OBJDIR)/, csv.o main.o)
$(OBJDIR)/%.o: $(SRCDIR)/%.cpp
...
$(CXX) $(CXXFLAGS) -c $< -o $#
#echo "Done compiling $#"
TARGET = $(BINDIR)/csv2sqlite
$(TARGET): $(OBJECTS)
#echo "Linking $# file..."
$(CXX) $(CXXFLAGS) $^ -o $#
#echo "Linking $# file..."

Related

C++ Makefile with source in multiple directories and multiple executables

I have a small project for school and I want to write a decent Makefile, I have seen some examples of using Makefile with multiple source directories and multiple executables but still could not implement it properly to my Makefile.
Here is the directory structure:
.
├── bin (this is where i want the executables)
├── build (this is where i want the .o)
├── extern
│ └── doctest.h
├── include
│ ├── file1.hpp
│ └── file2.hpp
├── src
│ ├── file1.cpp
│ └── file2.cpp
├── tests
│ ├── file1-test.cpp
│ └── file2-test.cpp
└── Makefile
PS: I'm using doctest for the unit testing (and i can't change).
Here is my Makefile for the moment:
BIN_DIR = ./bin/
BUILD_DIR = ./build/
EXTERN_DIR = ./extern/
INCLUDE_DIR = ./include/
SOURCE_DIR = ./src/
TESTS_DIR = ./tests/
CXX = clang++-7
CXXFLAGS = -Wall -std=c++11 -g -O3 -I$(INCLUDE_DIR)
EXEC_FILES = file1 file2
BIN = $(addprefix $(BIN_DIR), $(EXEC_FILES))
all: $(BIN)
$(BIN_DIR) $(BUILD_DIR):
mkdir -p $#
$(BUILD_DIR)%.o: $(SOURCE_DIR)%.cpp | $(BUILD_DIR)
$(CXX) $(CXXFLAGS) -c -o $# $^
$(BUILD_DIR)%.o: $(TESTS_DIR)%.cpp | $(BUILD_DIR)
$(CXX) $(CXXFLAGS) -I$(EXTERN_DIR) -c -o $# $^
$(BIN_DIR)file1-test: $(BUILD_DIR)file1.o $(BUILD_DIR)file1-test.o | $(BIN_DIR)
$(CXX) -o $# $^
$(BIN_DIR)file2-test: $(BUILD_DIR)file1.o $(BUILD_DIR)file2.o $(BUILD_DIR)file2-test.o | $(BIN_DIR)
$(CXX) -o $# $^
clean:
rm -f $(BIN_DIR)* $(BUILD_DIR)*
It's working well but I feel like it's doing useless stuff that i could avoid with more knownledge in the Makefile art, sadly I don't have much time.
My goal:
I want to run make and compile all the units tests (all the .cpp in the tests/ directory) and the main program (see PS below).
I want all the executables in the bin/ directory and all the binary files in the build/ directory.
PS: I don't have my main executable yet but it should be stored in the src/ directory at the very end (and be compiled as well while running make).
EDIT 1:
Basically, my question is: How can I write generic rules to prevent copying this (see below) for every new executable in my project ?
$(BIN_DIR)file2-test: $(BUILD_DIR)file1.o $(BUILD_DIR)file2.o $(BUILD_DIR)file2 test.o | $(BIN_DIR)
$(CXX) -o $# $^
EDIT 2:
After some changes, I ended up with this:
BIN_DIR = ./bin/
BUILD_DIR = ./build/
EXTERN_DIR = ./extern/
INCLUDE_DIR = ./include/
SOURCE_DIR = ./src/
TESTS_DIR = ./tests/
vpath %.cpp $(SOURCE_DIR) $(TESTS_DIR)
CXX = clang++-7
CXXFLAGS = -Wall -std=c++11 -g -O3 -I$(INCLUDE_DIR) -I$(EXTERN_DIR)
EXEC_FILES = file1-test file2-test
BIN = $(addprefix $(BIN_DIR), $(EXEC_FILES))
all: $(BIN) | $(BIN_DIR)
$(BUILD_DIR)%.o: %.cpp | $(BUILD_DIR)
#$(CXX) $(CXXFLAGS) -c -o $# $^
# The problem is here
$(BIN_DIR)%: $(BUILD_DIR)%.o
#$(CXX) -o $# $^
$(BIN_DIR) $(BUILD_DIR):
#mkdir -p $#
clean:
-#rm -f $(BIN_DIR)* $(BUILD_DIR)*
I understand this rule (see below) like this: Compile every target in EXEC_FILES to the bin/ directory, from his equivalent .o (obj) in the build/ directory.
$(BIN_DIR)%: $(BUILD_DIR)%.o
#$(CXX) -o $# $^
But in fact I need a rule that will: Compile every target in EXEC_FILES to the bin/ directory, from all their related .o (obj) in the build/ directory.

Running Makefile not completely

I am a rookie to MaKefile and I've been learning it recently.
However, I got trouble when I tried to run make command on my terminal.
Here's my Makefile:
CC = g++
CFLAGS = -g -Wall
bin = ./bin/
makedir:
#echo "build ./bin"
mkdir $(bin)
all: algo
OBJS = $(patsubst %.o, $(bin)%.o, BB.o BF.o method.o algo.o)
algo: BB.o BF.o method.o algo.o
$(CC) -o algo $(OBJS)
BB.o: BB.cpp
$(CC) $(CFLAGS) -c $^ -o $(bin)$#
BF.o: BF.cpp
$(CC) $(CFLAGS) -c $^ -o $(bin)$#
method.o: method.cpp
$(CC) $(CFLAGS) -c method.cpp -o $(bin)$#
algo.o: algo.cpp method.hpp
$(CC) $(CFLAGS) -c algo.cpp -o $(bin)$#
clean:
-rm -f $(bin)*
-rmdir $(bin)
-rm -f algo
I tried to put object files in bin directory.
But, the terminal only shows:
build ./bin
mkdir bin
And here's the problem. Only a empty directory named bin being created.
It seems like it didn't do anything after mkdir command.
For more details, it's my directory structure before running make command:
├── algo.cpp
├── BB.cpp
├── BF.cpp
├── Makefile
├── method.cpp
├── method.hpp
I have no idea about it at all, and tried to find any way to solve it but useless.
By the way, I am also a rookie to Stackoverflow.
If I don't ask questions at a good way, let me know and I will get better. Thank you so much!
When you run make without arguments, the recipe for the first target in the Makefile is followed.
Your first target is makedir, whose recipe performs those two commands and nothing else. So, the computer is doing what you asked it to do.
I recommend that you put the all target first, and make makedir a prerequisite of the targets that actually do rely on it:
CC = g++
CFLAGS = -g -Wall
bin = ./bin/
all: algo
OBJS = $(patsubst %.o, $(bin)%.o, BB.o BF.o method.o algo.o)
algo: BB.o BF.o method.o algo.o
$(CC) -o algo $(OBJS)
BB.o: makedir BB.cpp
$(CC) $(CFLAGS) -c $^ -o $(bin)$#
BF.o: makedir BF.cpp
$(CC) $(CFLAGS) -c $^ -o $(bin)$#
method.o: makedir method.cpp
$(CC) $(CFLAGS) -c method.cpp -o $(bin)$#
algo.o: makedir algo.cpp method.hpp
$(CC) $(CFLAGS) -c algo.cpp -o $(bin)$#
makedir:
#echo "build ./bin"
mkdir $(bin)
clean:
-rm -f $(bin)*
-rmdir $(bin)
-rm -f algo
There are better ways to handle build output directory creation, though (example).

makefile: pattern rules for subdirectory

Here is my project:
project
|--- main.cpp
|--- makefile
|--- test
|--- Test.cpp
|--- Test.h
Here is the makefile:
g++1x:=g++ -std=c++14 -stdlib=libc++ -MMD -MP
cflags:= -Wall -lncurses
PATHS:=./ ./test/
TARGET:=matrix.out
SRC:=$(foreach PATH,$(PATHS),$(wildcard $(PATH)/*.cpp))
OBJDIR:=.obj
OBJ:=$(addprefix $(OBJDIR)/,$(notdir $(SRC:.cpp=.o)))
.PHONY: install
install: $(OBJDIR) $(TARGET)
$(OBJDIR):
mkdir -p $(OBJDIR)
$(TARGET): $(OBJ)
$(g++1x) $(cflags) -o $# $^ -g
$(OBJDIR)/%.o: %.cpp
$(g++1x) -c -o $# $< -g
$(OBJDIR)/%.o: ./test/%.cpp
$(g++1x) -c -o $# $< -g
-include $(addprefix $(OBJDIR)/,$(notdir $(SRC:.cpp=.d)))
.PHONY: clean
clean:
rm -f $(TARGET)
rm -rf $(OBJDIR)
It works well but I have two questions:
1) Is it possible to avoid foreach for PATHS so that I can use the same makefile for all of cpp projects?
2) As you see, to generate main.o and Test.o I write two blocks:
$(OBJDIR)/%.o: ./test/%.cpp and $(OBJDIR)/%.o: %.cpp.
Is it possible to write only once?
I've tried as below but it doesn't work:
$(OBJDIR)/%.o: $(foreach PATH,$(PATHS),$(wildcard $(PATH)/%.cpp))
$(g++1x) -c -o $# $< -g
I've even tried like this but it doesn't work still:
$(OBJDIR)/%.o: %.cpp ./test/%.cpp
$(g++1x) -c -o $# $< -g
You should keep the source tree into your object tree. This way it will be easier to create global rules and keep dependencies.
# Use the shell find command to get the source tree
SOURCES := $(shell find * -type f -name "*.c")
OBJDIR := .objects
# Keep the source tree into the objects tree
OBJECTS := $(addprefix $(OBJDIR)/,$(SOURCES:.c=.o))
all: mytarget
mytarget: $(OBJECTS)
$(CC) $^ -o $#
# As we keep the source tree we have to create the
# needed directories for every object
$(OBJECTS): $(OBJDIR)/%.o: %.c
mkdir -p $(#D)
$(CC) -MMD -MP -c $< -o $#
-include $(OBJECTS:.o=.d)
$ make
mkdir -p .objects
cc -MMD -MP -c main.c -o .objects/main.o
mkdir -p .objects/test
cc -MMD -MP -c test/test.c -o .objects/test/test.o
cc .objects/main.o .objects/test/test.o -o mytarget
$ tree -a
.
├── main.c
├── Makefile
├── mytarget
├── .objects
│   ├── main.d
│   ├── main.o
│   └── test
│   ├── test.d
│   └── test.o
└── test
├── test.c
└── test.h
3 directories, 9 files
EDIT: You can reduce the number of mkdir to the minimum by adding the object directory as an order only prerequisites:
# Do not create the directory
$(OBJECTS): $(OBJDIR)/%.o: %.c
$(CC) -MMD -MP -c $< -o $#
# Every target finishing with "/" is a directory
$(OBJDIR)%/:
mkdir -p $#
# Add the "directory/" as an order only prerequisite
$(foreach OBJECT,$(OBJECTS),$(eval $(OBJECT): | $(dir $(OBJECT))))
Because I can't edit jmlemetayer's answer, here's how to extend the commands for projects with both C and CPP source:
Firstly to generate the object list, just apply the patsubst twice, once for each extension:
SRC_LST := $(patsubst %.c,%.o,$(patsubst %.cpp,%.o,$(SOURCES)))
OBJECTS := $(addprefix $(OBJDIR)/,$(SRC_LST))
Then to handle both .cpp and .c files in the implicit rule for compiling:
.SECONDEXPANSION:
$(OBJECTS): $(OBJDIR)/%.o: $$(wildcard %.c*)
mkdir -p $(#D)
ifeq "$(suffix $<)" ".cpp"
$(CPP) -MMD -MP -c $< -o $#
else
$(CC) -MMD -MP -c $< -o $#
endif
If there is a better way I'm happy to update this.

Modify the makefile to include subdirectories

I'm working with a small program in c++ to learn the makefile.
The program has 2 source files (main.cpp and classf.cpp) and one header file (classf.h). All files are included in the project directory which is called "testmake". This is the generated makefile by eclipse on windlows:
CXXFLAGS = -O2 -g -Wall -fmessage-length=0
OBJS = main.o classf.o
LIBS =
TARGET = createPddl.exe
$(TARGET): $(OBJS)
$(CXX) -o $(TARGET) $(OBJS) $(LIBS)
all: $(TARGET)
clean:
rm -f $(OBJS) $(TARGET)
I would like to modify the makefile to accept new sub-directories, e.g, when I add a folder called "testmake/src" and move the file main.cpp inside it, folder called "testmake/csource" and move the classf.cpp inside it, and create a folder called "testmake/cheader" and move the classf.h inside it.
This makefile was genereated automatically by eclipse, and does not accept any changes. There for i have created manually a make file which is working with any c++ project that has a structure as tree.
I actually use this Makefile in general
CC := g++ # This is the main compiler
SRCDIR := src
BUILDDIR := build
TARGETDIR :=bin/
TARGET := pddlcrate
DATADIR := data
SRCEXT := cpp
SOURCES := $(shell find $(SRCDIR) -type f -name *.$(SRCEXT))
OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(SOURCES:.$(SRCEXT)=.o))
CFLAGS := -g # -Wall
#LIB := -pthread -lmongoclient -L lib -lboost_thread-mt -lboost_filesystem-
mt -lboost_system-mt
INC := -I include
$(TARGET): $(OBJECTS)
#echo " Linking..."
#echo " $(CC) $^ -o $(TARGETDIR)$(TARGET) $(LIB)"; $(CC) $^ -o
$(TARGETDIR)$(TARGET) $(LIB)
$(BUILDDIR)/%.o: $(SRCDIR)/%.$(SRCEXT)
#mkdir -p $(BUILDDIR)
#echo " $(CC) $(CFLAGS) $(INC) -c -o $# $<"; $(CC) $(CFLAGS) $(INC) -c - o $# $<
clean:
#echo " Cleaning...";
#echo " $(RM) -r $(BUILDDIR) $(TARGET)"; $(RM) -r $(BUILDDIR) $(TARGET)
for any c++ project with this tree structure
$ tree .
├── Makefile
├── bin
>exefile
├── include
> *.h files
├── obj
> *.o files
├── src
>*.cpp

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