1#!/usr/bin/make -f
2
3include /usr/share/dpkg/pkg-info.mk
4include /usr/share/dpkg/vendor.mk
5
6# See debhelper(7) (uncomment to enable)
7# output every command that modifies files on the build system.
8#export DH_VERBOSE = 1
9
10# python packages do not contain any tests
11export PYBUILD_DISABLE=test
12
13export MAKEFLAGS = --no-print-directory
14
15# helper to compare strings
16strequ=$(if $(subst x$1,,x$2)$(subst x$2,,x$1),,1)
17
18bold := $(shell which tput >/dev/null 2>&1 && tput bold 2>/dev/null)
19sgr0 := $(shell which tput >/dev/null 2>&1 && tput sgr0 2>/dev/null)
20
21# special characters
22empty :=
23space := $(empty) $(empty)
24comma := ,
25
26# helper to create comma separated list from space separated list
27commasep = $(subst $(space),$(comma)$(space),$1)
28# recursive wildcard
29rwildcard=$(foreach d,$(wildcard $(1:=/*)),$(call rwildcard,$d,$2) $(filter $(subst *,%,$2),$d))
30
31# remove double quotes
32unquote = $(subst $\",,$1)
33
34# set these variables to define build of certain boards/scenarios, e.g.
35ACRN_BOARDLIST ?=
36ACRN_SCENARIOLIST ?=
37
38# for now build the debug versions
39# set to y for RELEASE build
40export RELEASE ?= n
41
42# eventually add-in locally contributed configurations
43-include debian/configs/configurations.mk
44debian/configs/configurations.mk:
45	@:
46
47# misc/config_tools/data: contains ACRN supported configuration
48# debian/configs: add additional, unsupported configurations here!
49CONFIGDIRS ?= misc/config_tools/data debian/configs
50CONFIGXMLS := $(call rwildcard,$(CONFIGDIRS),*.xml)
51
52# get relevant data from acrn-config attributes of an XML
53#
54# This evaluates the attributes of acn-config tag got from xmllint (after unquoting).
55# It create the following variables:
56#  * boardlist: accumulated list of all board configurations detected
57#  * scenariolist_<board>: accumulated list of sceanrios for the given <board>
58#  * config_<board>: respective board configuration file
59#  * config_<board>_<scenario>: respective scenario configuration file
60define get-xml-data
61$(eval $(call unquote,$(shell xmllint --xpath '/acrn-config/@board' $1 2>/dev/null)))
62$(eval $(if $(board),                                                                     \
63    $(eval config_$(board) := $1)                                                         \
64    $(eval boardlist := $(sort $(boardlist) $(board)))                                    \
65    $(foreach f,$(wildcard $(addprefix $(dir $1),*.xml)),                                 \
66        $(if $(strip $(shell xmllint --xpath '/acrn-config/@board' $f 2>/dev/null)),,     \
67            $(if $(subst scenario.xml,,$(notdir $f)),                                     \
68                $(eval scenario = $(basename $(notdir $f))),                              \
69                $(eval scenario = $(notdir $(abspath $(dir $f)))))                        \
70            $(eval config_$(board)_$(scenario) := $f)                                     \
71            $(eval scenariolist_$(board) := $(sort $(scenariolist_$(board)) $(scenario))) \
72        )                                                                                 \
73    )                                                                                     \
74))
75$(eval undefine scenario)
76$(eval undefine board)
77endef
78
79# get all XML data
80$(foreach xml,$(CONFIGXMLS),$(call get-xml-data,$(xml)))
81
82# honor variable ACRN_BOARDLIST by filtering the discovered board configurations accordingly
83ifneq ($(ACRN_BOARDLIST),)
84boardlist := $(sort $(filter $(boardlist),$(ACRN_BOARDLIST)))
85endif
86
87# honor variable ACRN_SCENARIOLIST by filtering the discovered scenario configurations
88ifneq ($(ACRN_SCENARIOLIST),)
89$(foreach b,$(boardlist),$(eval scenariolist_$(b) := $(filter $(scenariolist_$(b)),$(ACRN_SCENARIOLIST))))
90endif
91
92# only keep boards with at least one valid scenario configuration
93boardlist := $(foreach b,$(boardlist),$(if $(scenariolist_$(b)),$b))
94# assert nonempty boardlist
95ifeq ($(boardlist),)
96$(error No valid board/scenario configurations specified/found)
97endif
98
99# board config name -> board config file
100bfile = $(abspath $(config_$1))
101# board/scenario config name -> scenario config file
102sfile = $(abspath $(config_$1_$2))
103
104# uncomment for debugging purposes
105# $(info boardlist: $(boardlist))
106# $(foreach b,$(boardlist),$(info scenariolist_$(b): $(scenariolist_$(b))))
107# $(foreach b,$(boardlist),$(info config_$(b): $(config_$(b))))
108# $(foreach b,$(boardlist),$(foreach s,$(scenariolist_$(b)),$(info config_$(b)_$(s): $(config_$(b)_$(s)))))
109
110# get version data for ACRN
111include VERSION
112export ACRNVERSION := $(MAJOR_VERSION).$(MINOR_VERSION)
113
114# set paths (see also paths.make)
115export prefix = /usr
116export bindir = $(prefix)/bin
117export libdir = $(prefix)/lib/$(DEB_HOST_MULTIARCH)
118export nonarchlibdir = $(prefix)/lib
119export datadir = $(prefix)/share
120export includedir = $(prefix)/include
121export systemd_unitdir = /lib/systemd
122export docdir = $(datadir)/doc
123export sysconfdir = /etc
124
125export BUILD_VERSION = "$(DEB_VERSION_UPSTREAM)"
126export BUILD_TAG = "$(DEB_VENDOR)/$(DEB_VERSION)"
127
128# set iASL compiler
129ifeq ($(ASL_COMPILER),)
130export ASL_COMPILER:=$(shell which iasl)
131ifeq ($(ASL_COMPILER),)
132$(error ASL_COMPILER missing)
133endif
134endif
135
136# let make verbosity be controlled by DH_VERBOSE
137ifeq ($(DH_VERBOSE),1)
138  Q=
139  echo-verbose = echo "   $@$(if $1,: $(bold)$1$(sgr0))"
140  echo-silent = true
141  devnull =
142else
143  Q=@
144  echo-verbose = true
145  echo-silent = echo "   $@$(if $1,: $(bold)$1$(sgr0))"
146  devnull = >/dev/null
147endif
148
149### dh_installdeb ############################################################
150
151# create acrntools.install for debug build
152ifeq ($(RELEASE),n)
153
154debian/acrn-tools.install: debian/acrn-tools.install.debug
155	@$(call echo-verbose)
156	@$(call echo-silent,CREATE $@)
157	$(Q)cp $< $@
158
159override_dh_install: debian/acrn-tools.install
160	$(Q)dh_install
161
162endif
163
164### dh_installdeb ############################################################
165debian/acrn-hypervisor.postinst: debian/acrn-hypervisor.postinst.in
166	@$(call echo-verbose)
167	@$(call echo-silent,CREATE $@)
168	$(Q)sed -e 's/@acrnversion@/$(ACRNVERSION)/g' \
169		-e 's%@acrndir@%$(libdir)/acrn%g' $< > $@
170
171debian/acrn-hypervisor.postrm: debian/acrn-hypervisor.postrm.in
172	@$(call echo-verbose)
173	@$(call echo-silent,CREATE $@)
174	$(Q)sed -e 's/@acrnversion@/$(ACRNVERSION)/g' $< > $@
175
176debian/acrn-hypervisor.prerm: debian/acrn-hypervisor.prerm.in
177	@$(call echo-verbose)
178	@$(call echo-silent,CREATE $@)
179	$(Q)sed -e 's/@acrnversion@/$(ACRNVERSION)/g' $< > $@
180
181override_dh_installdeb: debian/acrn-hypervisor.postinst debian/acrn-hypervisor.postrm debian/acrn-hypervisor.prerm
182	$(Q)dh_installdeb
183
184### dh_installdebconf-arch ###################################################
185debian/acrn-hypervisor.templates: debian/acrn-hypervisor.templates.in
186	@$(call echo-verbose)
187	@$(call echo-silent,CREATE $@)
188	$(Q)sed -e 's/@boardlist@/$(call commasep,$(boardlist))/g' $< > $@
189
190debian/acrn-hypervisor.config: debian/acrn-hypervisor.config.in
191	@$(call echo-verbose)
192	@$(call echo-silent,CREATE $@)
193	@# create scenarios as bash associative array
194	$(Q)sed -e 's%@acrndir@%$(libdir)/acrn%g' \
195	        -e 's%@scenarios@%($(foreach b,$(boardlist),[$b]="$(call commasep,$(scenariolist_$b))"))%g' $< > $@
196
197override_dh_installdebconf-arch: debian/acrn-hypervisor.templates debian/acrn-hypervisor.config
198	$(Q)dh_installdebconf -a
199
200### build-arch ###############################################################
201override_dh_auto_build-arch: O=build
202override_dh_auto_build-arch:
203	@$(call echo-verbose)
204	@# Only build lifemngr here, since other parts are built during
205	@# dh_auto_install (even if built here). This is deficiency
206	@# of ACRN's makefile structure, e.g. make hypervisor-install
207	@# always rebuilds the hypervisor, even if built with
208	@# make hypervisor in a previous step.
209	$(Q)set -e; $(call echo-silent,BUILD life_mngr)
210	$(Q)mkdir -p $(O)/common/misc
211	$(Q)$(MAKE) -C misc						\
212		OUT_DIR=$(abspath $(O)/common/misc)			\
213		life_mngr $(devnull)
214
215### build-indep ##############################################################
216ifeq ($(EXTRA_VERSION),)
217ACRN_DOC_VERSION := $(DEB_VERSION_UPSTREAM)
218else
219ACRN_DOC_VERSION := latest
220endif
221
222build/documentation/html/index.html: debian/acrn-doc-index-html.in
223	@$(call echo-verbose)
224	@$(call echo-silent,BUILD documentation)
225	$(Q)mkdir -p $(@D)
226	$(Q)sed -e 's/@acrnversion@/$(ACRN_DOC_VERSION)/g' $< > $@
227
228override_dh_auto_build-indep: build/documentation/html/index.html
229	@$(call echo-verbose)
230	@$(call echo-silent,BUILD acrn-board-inspector)
231	$(Q)export PYBUILD_NAME=acrn_board_inspector; \
232	dh_auto_build \
233	    --buildsystem=pybuild \
234	    --package=python3-acrn-board-inspector \
235	    --sourcedirectory=debian/acrn-board-inspector $(devnull)
236
237### binary-arch ##############################################################
238
239# check_post_launched <configfile>
240# Checks if there is a POST_LAUNCHED_VM configured in the given config file
241# returns empty string (i.e. false) if there is no POST_LAUNCHED_VM detected
242check_post_launched=$(strip $(shell xmllint --xpath '//vm[load_order="POST_LAUNCHED_VM"]/@id' $1 2>/dev/null || true))
243
244# helper to determine if there are any POST_LAUNCHED VMs in any configuration
245check_any_post_launched=$(strip $(foreach b,$(boardlist),$(foreach s,$(scenariolist_$b),$(call check_post_launched,$(call sfile,$b,$s)))))
246
247# dynamically generate acrn-hypervisor.install to conditionally add launch script directory
248debian/acrn-hypervisor.install:
249	@$(call echo-verbose)
250	@$(call echo-silent,CREATE $@)
251	$(Q)echo "usr/lib/x86_64-linux-gnu/acrn/*" >$@
252	$(Q)if [ -n "$(call check_any_post_launched)" ]; then echo "usr/share/acrn/launch-scripts/" >>$@; fi
253
254.PHONY: debian/acrn-hypervisor.install
255
256override_dh_auto_install-arch: O=build
257override_dh_auto_install-arch: DESTDIR=$(abspath debian/tmp)
258override_dh_auto_install-arch: debian/acrn-hypervisor.install
259	@$(call echo-verbose)
260	$(Q)set -e;$(foreach b,$(boardlist),$(foreach s,$(scenariolist_$b),         \
261		$(call echo-silent,BUILD & INSTALL hypervisor for $b:$s);           \
262		$(MAKE) O=$(O)/$b/$s                                                \
263			BOARD=$(call bfile,$b)                                      \
264			SCENARIO=$(call sfile,$b,$s)                                \
265			DESTDIR=$(DESTDIR)				            \
266			hypervisor-install $(devnull);			            \
267		install -d $(DESTDIR)$(libdir)/acrn/$b/$s;		            \
268		rm -f $(DESTDIR)$(libdir)/acrn/*.out;			            \
269		mv $(DESTDIR)$(libdir)/acrn/*.bin			            \
270			$(DESTDIR)$(libdir)/acrn/$b/$s;			            \
271		if [ -d $(DESTDIR)$(sysconfdir) ]; then			            \
272			mv $(DESTDIR)$(sysconfdir)			            \
273				$(DESTDIR)$(libdir)/acrn/$b/$s;		            \
274		fi;							            \
275		if [ -d $(DESTDIR)$(libdir)/acrn/acpi ]; then		            \
276			mv $(DESTDIR)$(libdir)/acrn/acpi		            \
277				$(DESTDIR)$(libdir)/acrn/$b/$s;		            \
278		fi;							            \
279		cp $(O)/$b/$s/hypervisor/configs/config.mk		            \
280			$(DESTDIR)$(libdir)/acrn/$b/$s/acrn.$b.$s.config;           \
281		cp $(O)/$b/$s/hypervisor/acrn.map			            \
282			$(DESTDIR)$(libdir)/acrn/$b/$s/acrn.$b.$s.map;	            \
283		chmod 644 $(DESTDIR)$(libdir)/acrn/$b/$s/*.bin;		            \
284		if [ -d $(DESTDIR)$(libdir)/acrn/$b/$s/acpi ]; then                 \
285			chmod 644 $(DESTDIR)$(libdir)/acrn/$b/$s/acpi/*;            \
286		fi;                                                                 \
287		cp $(call sfile,$b,$s) $(DESTDIR)$(libdir)/acrn/$b/$s/scenario.xml; \
288		if [ -n "$(call check_post_launched,$(call sfile,$b,$s))" ]; then   \
289			$(call echo-silent,CREATE launch scripts in $(datadir)/acrn/launch-scripts/$b/$s/); \
290			mkdir -p $(DESTDIR)$(datadir)/acrn/launch-scripts/$b/$s/;   \
291			misc/config_tools/launch_config/launch_cfg_gen.py           \
292			    --board $(call bfile,$b) --scenario $(call sfile,$b,$s) \
293			    --out $(DESTDIR)$(datadir)/acrn/launch-scripts/$b/$s    \
294			    $(devnull) 2>&1;                          \
295			chmod a+x $(DESTDIR)$(datadir)/acrn/launch-scripts/$b/$s/*; \
296		fi;                                                                 \
297	) cp $(call bfile,$b) $(DESTDIR)$(libdir)/acrn/$b/board.xml;)
298	@:
299	@# install devicemodel & tools
300	@$(call echo-silent,BUILD & INSTALL devicemodel & tools)
301	$(Q)$(MAKE) O=$(O)/common DESTDIR=$(DESTDIR) devicemodel-install $(devnull)
302	$(Q)$(MAKE) O=$(O)/common DESTDIR=$(DESTDIR) tools-install $(devnull)
303	@:
304	@# install life_mngr
305	@$(call echo-silent,INSTALL life_mngr)
306	$(Q)mkdir -p $(O)/common/misc
307	$(Q)$(MAKE) -C misc                             \
308		DESTDIR=$(DESTDIR)                      \
309		OUT_DIR=$(abspath $(O)/common/misc)     \
310		acrn-life-mngr-install $(devnull)
311	@# rename to acrn-lifemngr
312	$(Q)mv $(DESTDIR)$(bindir)/life_mngr $(DESTDIR)$(bindir)/acrn-lifemngr
313	@# install config file templates
314	$(Q)install -d $(DESTDIR)$(datadir)/acrn-lifemngr
315	$(Q)mv $(DESTDIR)$(sysconfdir)/life_mngr/life_mngr.conf \
316	       $(DESTDIR)$(datadir)/acrn-lifemngr/life_mngr.conf.service_vm
317	$(Q)install -m 0644 debian/lifemngr/life_mngr.conf.user_vm $(DESTDIR)$(datadir)/acrn-lifemngr
318	@# install invocation helper
319	$(Q)install -m 0755 debian/lifemngr/start-acrn-lifemngr.sh $(DESTDIR)$(datadir)/acrn-lifemngr
320	@# adapt life_mngr.service
321	$(Q)mv $(DESTDIR)$(systemd_unitdir)/system/life_mngr.service \
322	       $(DESTDIR)$(systemd_unitdir)/system/acrn-lifemngr.service
323	$(Q)sed -i -e 's#^ExecStart=.*#ExecStart=$(datadir)/acrn-lifemngr/start-acrn-lifemngr.sh#' \
324	        $(DESTDIR)$(systemd_unitdir)/system/acrn-lifemngr.service
325	@:
326	@# move/adapt network configs as examples only
327	$(Q)mkdir -p $(DESTDIR)$(docdir)/acrnd/examples
328	$(Q)cp $(DESTDIR)$(systemd_unitdir)/network/*				\
329		$(DESTDIR)$(docdir)/acrnd/examples
330	$(Q)sed -i 's/acrn_tap\* //g'						\
331		$(DESTDIR)$(docdir)/acrnd/examples/50-acrn.network
332	@:
333	@# adapt systemd services for tools (available in DEBUG build only)
334	$(if $(call strequ,${RELEASE},n),					\
335		$(Q)sed -i -e '/telemd.socket/d' -e '/prepare.service/d'	\
336			$(DESTDIR)$(systemd_unitdir)/system/acrnprobe.service;	\
337		sed -i '/telemd/d'						\
338			$(DESTDIR)$(systemd_unitdir)/system/usercrash.service;	\
339		install -d $(DESTDIR)$(datadir)/defaults/telemetrics;		\
340		install -m 0644 -t $(DESTDIR)$(datadir)/defaults/telemetrics	\
341			misc/debug_tools/acrn_crashlog/data/acrnprobe.xml;	\
342		install -d $(DESTDIR)$(datadir)/acrn/scripts;			\
343		cp -a misc/debug_tools/acrn_trace/scripts/*			\
344			$(DESTDIR)$(datadir)/acrn/scripts;			\
345		install -d $(DESTDIR)$(sysconfdir)/default;			\
346		cp debian/acrnlog/acrnlog.default				\
347			$(DESTDIR)$(sysconfdir)/default/acrnlog;		\
348		sed -i -e 's#ExecStart=.*#EnvironmentFile=$(sysconfdir)/default/acrnlog\nExecStart=$(bindir)/acrnlog $${ACRNLOG_ARGS}#' \
349			$(DESTDIR)$(systemd_unitdir)/system/acrnlog.service	\
350	)
351
352### binary-indep #############################################################
353override_dh_auto_install-indep: O=build
354override_dh_auto_install-indep: DESTDIR=$(abspath debian/tmp)
355override_dh_auto_install-indep:
356	@$(call echo-verbose)
357	@$(call echo-silent,INSTALL acrn-board-inspector)
358	$(Q)export PYBUILD_NAME=acrn_board_inspector; \
359	dh_auto_install \
360	    --buildsystem=pybuild \
361	    --package=python3-acrn-board-inspector \
362	    --sourcedirectory=debian/acrn-board-inspector $(devnull)
363	@:
364	@$(call echo-silent,INSTALL documentation)
365	$(Q)mkdir -p ${DESTDIR}$(docdir)/acrn/
366	$(Q)cp -a $(O)/documentation/html ${DESTDIR}$(docdir)/acrn/
367
368### dh_missing ###############################################################
369override_dh_missing:
370	$(Q)dh_missing --fail-missing
371
372### dh_installsystemd ########################################################
373# do not start services at install, since they are most likely installed on a
374# non-ACRN system
375override_dh_installsystemd:
376	$(Q)dh_installsystemd --no-start
377
378### dh_strip #################################################################
379# only strip release variant binaries
380override_dh_strip: DESTDIR=$(abspath debian/tmp)
381override_dh_strip:
382	$(Q)dh_strip -X.out -X.bin
383	$(Q)strip --strip-debug							\
384		--remove-section=.comment					\
385		--remove-section=.note						\
386		--enable-deterministic-archives					\
387		$(DESTDIR)$(libdir)/libacrn-mngr.a;
388
389### clean ####################################################################
390override_dh_auto_clean:
391	@echo "Building ACRN $(ACRNVERSION) for boards: $(bold)$(call commasep,$(boardlist))$(sgr0)"
392	@echo "The scenarios used are:"
393	@$(foreach b,$(boardlist),echo "  $b: $(bold)$(call commasep,$(scenariolist_$b))$(sgr0)";)
394	@$(call echo-verbose)
395	@$(call echo-silent,CLEAN)
396	$(Q)rm -rf .pybuild/
397	$(Q)find . -type d -name __pycache__ | xargs rm -rf
398	$(Q)rm -f debian/acrn-hypervisor.install
399	$(Q)rm -f debian/acrn-hypervisor.config
400	$(Q)rm -f debian/acrn-hypervisor.postinst
401	$(Q)rm -f debian/acrn-hypervisor.postrm
402	$(Q)rm -f debian/acrn-hypervisor.prerm
403	$(Q)rm -f debian/acrn-tools.install
404	$(Q)rm -f debian/acrn-hypervisor.templates
405	$(Q)rm -rf debian/acrn-board-inspector/build
406	$(Q)rm -rf debian/acrn-board-inspector/acrn_board_inspector.egg-info
407	$(Q)dh_auto_clean $(devnull)
408
409### others ###################################################################
410%:
411	$(Q)dh $@ --with python3
412