-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathMakefile
315 lines (232 loc) · 9.87 KB
/
Makefile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
# This file is part of the Home2L project.
#
# (C) 2015-2024 Gundolf Kiefer
#
# Home2L is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Home2L is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Home2L. If not, see <https://www.gnu.org/licenses/>.
# This is the master Makefile for the Home2L build system.
############################## Configuration ###################################
# Preset modules (sub-projects), drivers, architectures, and non-standard compile-time settings ...
# By default, all compile-time-settings are preset to '1' in the module Makefile.
# For a complete build (no configuration set), all architectures are activated.
# In all other cases, the build is performed for the current native architecture.
ifeq ($(CFG),minimal)
# Minimal set ...
MODS ?= tools showcase resources
DRVS ?=
ARCHS ?= $(shell dpkg --print-architecture)
export WITH_PYTHON ?= 0
export WITH_READLINE ?= 0
else ifeq ($(CFG),basic)
# Basic set ...
MODS ?= tools showcase resources brownies
DRVS ?= gpio mqtt brownies weather
ARCHS ?= $(shell dpkg --print-architecture)
# (the following WallClock settings presently have no effect, since WallClock is excluded from the basic build)
export WITH_ANDROID ?= 0
export WITH_PHONE ?= 0
export WITH_CALENDAR ?= 0
export WITH_MUSIC ?= 0
export WITH_GSTREAMER ?= 0
else ifeq ($(CFG),demo)
# Modules for the demo image ...
MODS ?= tools showcase resources brownies wallclock locales
DRVS ?= demo gpio mqtt brownies weather mpd
ARCHS ?= $(shell dpkg --print-architecture)
export WITH_ANDROID ?= 0
export WITH_PHONE ?= 0
export WITH_GSTREAMER ?= 0
else
# Default: All modules, drivers and architectures ...
MODS ?= tools showcase resources brownies wallclock locales doorman doc
DRVS ?= $(shell ls drivers)
ARCHS ?= amd64 armhf i386
endif
# Preset release build...
export DEBUG ?= 0
##### Wrap up ... #####
# Handle single module/driver invocation ...
ifdef MOD
MODS := $(MOD)
DRVS :=
endif
ifdef DRV
MODS :=
DRVS := $(DRV)
endif
# Add DRVS to MODS ...
PREP_DRVS := $(DRVS:%=drivers/%)
# put "driver/" in front of every driver name (absolute and relative)
PREP_DRVS := $(PREP_DRVS:drivers//%=/%)
# remove "driver/" again, if the path name was absolute
############################## Setup ###########################################
# Export and preset build and install target directories...
# PREFIX is accepted as INSTALL for compatibility reasons.
ifdef BUILD
HOME2L_BUILD := $(BUILD)
endif
ifdef INSTALL
HOME2L_INSTALL := $(INSTALL)
endif
ifdef PREFIX
HOME2L_INSTALL := $(PREFIX)
endif
# Report to sub-makes that they are called from the main build system ...
export HOME2L_BUILDSYSTEM := 1
# Include setup file ...
include Setup.mk
############################## Help ############################################
all: build
debug:
@echo MODS=$(MODS)
@echo DRVS=$(DRVS)
@echo PREP_DRVS=$(PREP_DRVS)
help:
@echo
@echo "This is the master Makefile of the Home2L build system."
@echo
@echo "Targets:"
@echo " help: Print this help"
@echo
@echo " build: Build everything (default target)"
@echo " install: Install to \$$HOME2L_INSTALL [ /opt/home2l ]"
@echo " clean: Clean everything (except binary doc files to be checked into the repository)"
@echo " veryclean: Clean really everything"
@echo " uninstall: Remove \$$HOME2L_INSTALL [ /opt/home2l ]"
@echo
@echo " docker: Build the docker showcase image locally (current working directory)"
@echo " docker-master: Build the docker showcase image for the master branch"
@echo " docker-run: Run the docker showcase image (latest)"
@echo
@echo "Variables:"
@echo " ARCHS: List of architectures to build for (available: amd64 armhf i386) [ all ]"
@echo " MODS: Modules (sub-projects) to build (space-separated list of directory names) [ all ]"
@echo " MOD: If set, build only the given module (overrides MODS, DRVS)."
@echo " DRVS: Drivers to build [ all integrated ]"
@echo " DRV: If set, build only the given driver (overrides MODS, DRVS). It is allowed to pass an absolute path."
@echo " CFG: Configuration preset"
@echo " 'minimal' = only the very basic tools and module 'resources' for the host architecture"
@echo " 'basic' = same as 'minimal', but with python support and GPIO driver"
@echo " 'demo' = most common modules (including WallClock) for the host architecture"
@echo " INSTALL: Target directory for the installation [ $(HOME2L_INSTALL) ]"
@echo " This can be preset by the environment variable HOME2L_INSTALL."
@echo " BUILD: Directory for intermediate files when building [ $(HOME2L_BUILD) ]"
@echo " This can be preset by the environment variable HOME2L_BUILD."
@echo " DEBUG: Compile with optimizations (0), for debugging (1) or with profiling information (2) [ 0 ]"
@echo
@echo "Examples:"
@echo " > make CFG=demo install # Build and install everything for the demo"
@echo " > make # Build everything (full build)"
@echo " > make MODS=doorman install # Build and install only the DoorMan for all architectures"
@echo
@echo "A basic configuration (CFG=basic) is perfectly sufficient to run and develop"
@echo "drivers and automation rules."
@echo
@echo "A full build may have additional requirements and may not work out-of-the-box."
############################## Docker Image ####################################
DOCKER_IMAGE=gkiefer/home2l
DOCKER_MASTER=https://github.com/gkiefer/home2l.git
# Build from local working directory ...
.PHONY: docker
docker:
@TAG="$(BUILD_VERSION)"; TAG=$${TAG%\-*}; [[ "$$TAG" != "" ]] || TAG=work; \
echo DOCKER $(DOCKER_IMAGE):$$TAG && \
docker build --build-arg BUILD_VERSION=$$TAG -t $(DOCKER_IMAGE):$$TAG -t $(DOCKER_IMAGE):latest .
# Build from local master branch ...
.PHONY: docker-master
docker-master:
@rm -fr $(HOME2L_BUILD)/docker && mkdir -p $(HOME2L_BUILD)/docker && \
git clone -b master --single-branch file://$$PWD $(HOME2L_BUILD)/docker/home2l && \
export BUILD_VERSION= && \
$(MAKE) -C $(HOME2L_BUILD)/docker/home2l docker
# Run the container (latest) ...
# NOTE [2024-05-24]: The option '--ipc=host' is required to avoid WallClock crashes
# but it reduces container isolation. See also:
# - https://github.com/jessfraz/dockerfiles/issues/359
# - https://github.com/libsdl-org/SDL/issues/4078
.PHONY: docker-run
docker-run:
@xhost +local: && \
docker run -ti --rm --tmpfs /tmp --name home2l-showcase --hostname home2l-showcase \
-e DISPLAY=$$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix --ipc=host --device /dev/snd \
gkiefer/home2l
######################### Update Copyright Notices #############################
.PHONY: update-copyright
update-copyright: clean
tools/update-copyright.sh
############################## Main targets ####################################
# The following targets are equivalent to the targets of subprojects and
# build all subprojects for all architectures.
# Export directories and other global settings ...
export HOME2L_BUILD
export HOME2L_INSTALL
export BUILD_VERSION := $(BUILD_VERSION)
# Note: In the 'build' target, we must pre-generate all directories inside the 'build'
# tree. Otherwise, files shared be different modules will unnecessarily by re-compiled,
# ultimately resulting in compilations during 'install' (perhaps as root) even after
# a full successful build run!
#
# Example:
# 1. Mod 'tools' compiles '../common/base.C' to 'build/tools/../common/base.o'.
# 2. Mod 'resources' checks 'build/resources/../common/base.o', which will be an identical
# file. However, the subdir 'resources' does not exist yet, so the .o file is not found!
# 3. It is now (unnecessarily) re-compiled, leading to an unnecessary re-linking
build:
@for A in $(ARCHS); do \
for P in $(MODS) $(PREP_DRVS); do \
mkdir -p $(HOME2L_BUILD)/$$A/$$P; \
done; \
done
@for P in $(MODS) $(PREP_DRVS); do \
echo -e "\n\n\n############################################################"; \
echo -e "#\n# $$P\n#\n############################################################"; \
echo -e "\n\n#### Building '$$P' - common files...\n"; \
$(MAKE) -C $$P build-indep || exit 1; \
echo; \
for A in $(ARCHS); do \
echo -e "\n\n#### Building '$$P' for '$$A'...\n"; \
$(MAKE) -C $$P HOME2L_MOD=$$P ARCH=$$A build-arch || exit 1; \
echo; \
done; \
done
install:
@mkdir -p $(HOME2L_INSTALL); \
for P in $(MODS) $(PREP_DRVS); do \
echo -e "\n\n\n############################################################"; \
echo -e "#\n# $$P\n#\n############################################################"; \
echo -e "\n\n#### Installing '$$P' - common files...\n"; \
$(MAKE) -C $$P install-indep || exit 1; \
echo; \
for A in $(ARCHS); do \
echo -e "\n\n#### Installing '$$P' for '$$A'...\n"; \
$(MAKE) -C $$P HOME2L_MOD=$$P ARCH=$$A install-arch || exit 1; \
done; \
done
install-clean:
cd $(HOME2L_INSTALL); \
rm -fr README VERSION env.sh bin/ lib/ share/ install/ locale/ doc/
clean: clean-build
@for P in $(MODS) $(PREP_DRVS); do \
echo -e "\n\n#### Cleaning '$$P'...\n"; \
$(MAKE) -C $$P HOME2L_MOD=$$P clean || exit 1; \
echo; \
done
veryclean:
@for P in $(MODS) $(PREP_DRVS); do \
echo -e "\n\n#### Cleaning '$$P' very thoroughly ...\n"; \
$(MAKE) -C $$P HOME2L_MOD=$$P veryclean || exit 1; \
echo; \
done
#~ $(MAKE) -C doc veryclean
uninstall:
rm -fr $(HOME2L_INSTALL)