2# +==== BEGIN CatFeeder =================+
4# ..............(..../\\
5# ...............)..(.')
7# ...............\\(__)|
8# Inspired by Joan Stark
9# source https://www.asciiart.eu/
14# CREATION DATE: 18-11-2025
15# LAST Modified: 14:27:23 04-12-2025
17# This is the project in charge of making the connected cat feeder project work.
19# COPYRIGHT: (c) Cat Feeder
20# PURPOSE: The makefile to help easily set up the python environement for the server to start without a hiccup.
22# +==== END CatFeeder =================+
25# The variables in charge of tracking the files for the program
26SRC_DIR = ./backend/src
28SRC = $(SRC_DIR)/server_main.py
30# Coverage report location
32COVERAGE_DIR = ./coverage_data
36NAME = bin_cat_feeder_server
38# Level precision of the build process
42# The name of the python environement that will be used
46# The location in which the dependencies used during the build process
49BUILD_LOCATION = ./build/
51# The location of the final built binary
53BINARY_LOCATION = ./dist/
55# The desired destinations for the binary
57BINARY_DESTINATION_ONE = ./
59BINARY_DESTINATION_TWO = ../../../
62REQUIREMENTS_DIR = ./backend/deps
63REQUIREMENTS = $(REQUIREMENTS_DIR)/requirements.backend.txt
64REQUIREMENTS_DEV = $(REQUIREMENTS_DIR)/requirements.dev.txt
65REQUIREMENTS_TESTING = $(REQUIREMENTS_DIR)/requirements.testing.txt
67# The python binary that is available on the system
69CC = $(shell command -v python3 2>/dev/null || \
70 command -v python 2>/dev/null || \
71 command -v py 2>/dev/null \
74# Break the code if no python instance was found
77 $(error Python interpreter not found. Please install Python.)
80# Search for pip version (bound to the venv)
81MY_PIP_BIN = ./$(ENV_NAME)/bin/python -m pip
83# Break the code if no python instance was found
86 $(error Pip interpreter not found. Please install a pip interpreter.)
89# Silence the outputs we wish not to listen to
93C_BACKGROUND = \033[48;5;16m
94C_RED = \033[38;5;9m$(C_BACKGROUND)
95C_PINK = \033[38;5;206m$(C_BACKGROUND)
96C_CYAN = \033[38;5;87m$(C_BACKGROUND)
97C_BLUE = \033[38;5;45m$(C_BACKGROUND)
98C_WHITE = \033[38;5;15m$(C_BACKGROUND)
99C_GREEN = \033[38;5;46m$(C_BACKGROUND)
100C_RESET = \033[0m$(C_BACKGROUND)
101C_YELLOW = \033[38;5;226m$(C_BACKGROUND)
104all: build_binary update_binary_location
106# This is the all in one version of the setup
107omega: create_environement install_dependencies all
109# Create the python environement
111 @echo -e "$(C_CYAN)Creating python environment$(C_RESET)"
112 $(SILENT) $(CC) -m venv $(ENV_NAME)
114# Install the python dependencies
115install_dependencies: create_environement
116 $(SILENT) echo -e "$(C_CYAN)Upgrading pip$(C_RESET)" && \
117 . $(ENV_NAME)/bin/activate && \
118 $(MY_PIP_BIN) install --upgrade pip wheel setuptools && \
120 $(MY_PIP_BIN) list && \
121 echo -e "$(C_CYAN)Installing python dependencies$(C_RESET)" &&\
123 $(MY_PIP_BIN) install -r $(REQUIREMENTS)
125# Install the dev python dependencies
126install_dev_dependencies: install_dependencies
127 $(SILENT) echo -e "$(C_CYAN)Upgrading pip$(C_RESET)" && \
128 . $(ENV_NAME)/bin/activate && \
130 echo -e "$(C_CYAN)Installing python dependencies$(C_RESET)" &&\
131 $(MY_PIP_BIN) install -r $(REQUIREMENTS_DEV)
133# Install the test python dependencies
134install_test_dependencies: install_dev_dependencies
135 $(SILENT) echo -e "$(C_CYAN)Upgrading pip$(C_RESET)" && \
136 . $(ENV_NAME)/bin/activate && \
138 echo -e "$(C_CYAN)Installing python dependencies$(C_RESET)" &&\
139 $(MY_PIP_BIN) install -r $(REQUIREMENTS_TESTING)
141# Activate the python environement (
142# this is a shortcut to help you keep your
143# environement up to date and also avoid mistakes in the name or process
145activate_environement: install_dependencies
146 @echo -e "$(C_PINK)Activating environement '$(ENV_NAME)'$(C_RESET)"
147 $(SILENT) . ./$(ENV_NAME)/bin/activate && \
148 export PYTHONPATH=.:$$PYTHONPATH; \
149 echo "Environement activated" && \
152 echo "Environement deactivated" && \
153 echo "Exit code: $$STATUS" && \
156activate: activate_environement
158# Build the python code as a binary
160 @echo -e "$(C_BLUE)Building binary '$(C_YELLOW)$(NAME)$(C_BLUE)'$(C_RESET)"
161 $(SILENT) mkdir -p "$(BINARY_DESTINATION_ONE)" "$(BINARY_DESTINATION_TWO)"
162 $(SILENT) . ./$(ENV_NAME)/bin/activate && \
165 --workpath $(BUILD_LOCATION) --distpath $(BINARY_LOCATION) \
166 --onefile --noconfirm \
168 --log-level=$(LOG_LEVEL) \
170 @echo -ne "$(C_BLUE)Binary '$(C_YELLOW)$(NAME)$(C_BLUE)' "
171 @echo -e "$(C_GREEN)built$(C_RESET)"
173# Update the location of the binary so that it can be easily accessed
174update_binary_location:
175 @echo -e "$(C_PINK)Updating binary locations$(C_RESET)"
176 $(SILENT) mkdir -p "$(BINARY_DESTINATION_ONE)" "$(BINARY_DESTINATION_TWO)"
177 $(SILENT) cp -vf "$(BINARY_LOCATION)$(NAME)" "$(BINARY_DESTINATION_ONE)"
178 $(SILENT) cp -vf "$(BINARY_LOCATION)$(NAME)" "$(BINARY_DESTINATION_TWO)"
179 @echo -e "$(C_PINK)Binary locations $(C_GREEN)updated$(C_RESET)"
181# This is a rebind for the main makefile
182build: build_binary update_binary_location
185# Clean the cache projects
188 @echo -e "$(C_YELLOW)Cleaning $(C_CYAN)cache and build data$(C_RESET)"
189# Removing the spec files that were used for the executable
190 $(SILENT) rm -vf *.spec
191# Removing the build and distribution folder of the executable
192 $(SILENT) rm -rvf $(BUILD_LOCATION)
193 $(SILENT) rm -rvf $(BINARY_LOCATION)
194# Removing python runtime cache
195 $(SILENT) find . -type d -name __pycache__ -exec rm -rvf {} +
196 @echo -e "$(C_GREEN)Cleaned $(C_CYAN)cache and build data$(C_RESET)"
198# Clean the binaries produced
200 @echo -ne "$(C_YELLOW)Cleaning $(C_CYAN)environement "
201 @echo -e "'$(C_RED)$(ENV_NAME)$(C_CYAN)'$(C_RESET)"
202 $(SILENT) rm -rf ./$(ENV_NAME)
203 @echo -ne "$(C_CYAN)Environement '$(C_RED)$(ENV_NAME)$(C_CYAN)' "
204 @echo -e "$(C_GREEN)cleaned$(C_RESET)"
206# Clean the coverage produced
208 @echo -e "$(C_YELLOW)Cleaning coverage$(C_RESET)"
209 $(SILENT) rm -rf $(COVERAGE_DIR)
210 $(SILENT) rm -rf .coverage
211 @echo -e "$(C_GREEN)Coverage cleaned$(C_RESET)"
215 @echo -e "$(C_YELLOW)Cleaning docker cache$(C_RESET)"
216 $(SILENT) rm -rf .core
217 $(SILENT) rm -rf .docker
218 $(SILENT) rm -rf .lesshst
219 $(SILENT) rm -rf .bash_history
220 $(SILENT) rm -rf .mysql_history
221 $(SILENT) rm -rf .python_history
222 @echo -e "$(C_GREEN)Docker cache cleaned$(C_RESET)"
224# Proceed to a full environement wipe (
225# ex: usefull when changing python version
227fclean: clean clean_coverage
228 $(SILENT) rm -vf $(BINARY_DESTINATION_ONE)$(NAME)
229 $(SILENT) rm -vf $(BINARY_DESTINATION_TWO)$(NAME)
231# Function in charge of doing a full clean
232ffclean: fclean clean_env clean_docker
234# Run the tests for the programs
235tests_run: install_test_dependencies
236 @echo -e "$(C_RED)Running unit tests$(C_RESET)"
237# Updating the path for python to find the imports
238 $(SILENT) export PYTHONPATH=.:$$PYTHONPATH; \
239 . ./$(ENV_NAME)/bin/activate && \
241 @echo -e "$(C_RED)Unit tests $(C_GREEN)run$(C_RESET)"
243# Check the coverage for the programs
244coverage: install_test_dependencies
245 @echo -e "$(C_CYAN)Generating coverage report$(C_RESET)"
246 $(SILENT) mkdir -p $(COVERAGE_DIR)
247 $(SILENT) . ./$(ENV_NAME)/bin/activate && \
249 COVERAGE_FILE=$(COVERAGE_DIR)/.coverage pytest --cov --cov-report=term --cov-report=html:$(COVERAGE_DIR)/html_report --cov-report=xml:$(COVERAGE_DIR)/coverage.xml && \
251 coverage report --data-file=$(COVERAGE_DIR)/.coverage > $(COVERAGE_DIR)/report.txt && \
252 cat $(COVERAGE_DIR)/report.txt && \
254 COVERAGE_FILE=$(COVERAGE_DIR)/.coverage_branch pytest --cov --cov-branch --cov-report=term --cov-report=html:$(COVERAGE_DIR)/branch_html_report --cov-report=xml:$(COVERAGE_DIR)/branch_coverage.xml && \
256 coverage report --data-file=$(COVERAGE_DIR)/.coverage_branch > $(COVERAGE_DIR)/branch_report.txt && \
257 cat $(COVERAGE_DIR)/branch_report.txt
258 @echo -e "$(C_CYAN)Coverage report $(C_GREEN)generated$(C_RESET)"
260# Create the debug versions for the program (no idea what to put in it)
264# Rule to re-build everything
268# Disable silent build
270 @echo -e "$(C_PINK)Silent mode is $(C_RED)inactive$(C_RESET)"
272 $(eval LOG_LEVEL=INFO)
274# This is a no operation function, it is used
275# by the parent makefile for silent builds
277 @echo -e "$(C_PINK)Silent mode is $(C_GREEN)active$(C_RESET)"
279 $(eval LOG_LEVEL=WARN)
283# The source code in production mode
285 $(SILENT) echo -e "$(C_CYAN) Activating environement $(C_RESET)" && \
286 . ./$(ENV_NAME)/bin/activate && \
287 export PYTHONPATH=.:$$PYTHONPATH && \
288 echo -e "$(C_CYAN) Starting program $(C_RESET)" && \
289 ./$(ENV_NAME)/bin/python $(SRC) && \
291 echo -e "$(C_CYAN) Environement deactivated $(C_RESET)"
293# Run the source code in production mode
296# The .PHONY to to avoid functions being overridden
299 all omega create_environement \
300 install_dependencies install_dev_dependencies install_test_dependencies \
301 activate_environement activate \
302 build build_binary update_binary_location \
303 clean clean_env clean_coverage clean_docker \