0

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.

Rusty
  • 1,086
  • 2
  • 13
  • 27

0 Answers0