My folder structure for C++ project is:
└── compiler
├── Makefile
├── README.md
├── build
└── src
├── components
│ ├── lexer
│ │ ├── lexer.cpp
│ │ ├── lexer.h
│ │ └── tokens
│ │ ├── tokens.cpp
│ │ └── tokens.h
│ └── parser
│ ├── parser.cpp
│ ├── parser.h
│ └── syntax
│ ├── syntax.cpp
│ └── syntax.h
├── main.cpp
└── utilities
└── evaluator
├── evaluator.cpp
└── evaluator.h
I want to write my Makefile
in such a way that it recompiles only changed .cpp
and .h
files on command make
. My Makefile is:
# Flags
flags_linker = -g -Wall -std=c++11 -lm -ldl -fPIC -rdynamic
flags_compiler = -g -Wall -std=c++11 -fPIC
# Directories and files
# Filenames and paths
main = main
lexer = lexer
tokens = tokens
parser = parser
syntax = syntax
evaluator = evaluator
# Source directories
source_dir = ./src
source_components_dir = $(source_dir)/components
source_lexer_dir = $(source_components_dir)/$(lexer)
source_tokens_dir = $(source_lexer_dir)/$(tokens)
source_parser_dir = $(source_components_dir)/$(parser)
source_syntax_dir = $(source_parser_dir)/$(syntax)
source_utilities_dir = $(source_dir)/utilities
source_evaluator_dir = $(source_utilities_dir)/$(evaluator)
# Build directories
build_dir = ./build
build_components_dir = $(build_dir)/components
build_lexer_dir = $(build_components_dir)/$(lexer)
build_tokens_dir = $(build_lexer_dir)/$(tokens)
build_parser_dir = $(build_components_dir)/$(parser)
build_syntax_dir = $(build_parser_dir)/$(syntax)
build_utilities_dir = $(build_dir)/utilities
build_evaluator_dir = $(build_utilities_dir)/$(evaluator)
run: $(build_dir)/$(main)
$(build_dir)/$(main)
$(build_dir)/$(main):
make executable
executable: compile
g++ $(flags_linker) -v $(build_dir)/$(main).o $(build_lexer_dir)/$(lexer).o $(build_tokens_dir)/$(tokens).o $(build_parser_dir)/$(parser).o $(build_syntax_dir)/$(syntax).o $(build_evaluator_dir)/$(evaluator).o -o $(build_dir)/$(main)
compile: $(main) $(lexer) $(parser) $(evaluator)
$(main): $(source_dir)/$(main).cpp $(lexer) $(parser)
g++ $(flags_compiler) -c $< -o $(build_dir)/$@.o
$(lexer): $(source_lexer_dir)/$(lexer).cpp $(build_lexer_dir) $(tokens)
g++ $(flags_compiler) -c $< -o $(build_lexer_dir)/$@.o
$(tokens): $(source_tokens_dir)/$(tokens).cpp $(build_tokens_dir)
g++ $(flags_compiler) -c $< -o $(build_tokens_dir)/$@.o
$(parser): $(source_parser_dir)/$(parser).cpp $(build_parser_dir) $(syntax)
g++ $(flags_compiler) -c $< -o $(build_parser_dir)/$@.o
$(syntax): $(source_syntax_dir)/$(syntax).cpp $(build_syntax_dir) $(lexer)
g++ $(flags_compiler) -c $< -o $(build_syntax_dir)/$@.o
$(evaluator): $(source_evaluator_dir)/$(evaluator).cpp $(build_evaluator_dir) $(syntax)
g++ $(flags_compiler) -c $< -o $(build_evaluator_dir)/$@.o
$(build_lexer_dir):
mkdir -p $(build_lexer_dir)
$(build_tokens_dir):
mkdir -p $(build_tokens_dir)
$(build_parser_dir):
mkdir -p $(build_parser_dir)
$(build_syntax_dir):
mkdir -p $(build_syntax_dir)
$(build_evaluator_dir):
mkdir -p $(build_evaluator_dir)
clean:
rm -rf ./build/*
My when I run make
command, it doesn't recompile the project but just runs the executable. I have just started using Makefiles and not able to figure out what should I change.