1# Copyright 2018 The Hafnium Authors.
2#
3# Use of this source code is governed by a BSD-style
4# license that can be found in the LICENSE file or at
5# https://opensource.org/licenses/BSD-3-Clause.
6
7# Select the project to build.
8PROJECT ?= reference
9
10TOOLCHAIN_LIB := $(shell clang --print-resource-dir)
11
12ENABLE_ASSERTIONS ?= 1
13
14PLATFORM ?= default
15
16LIST_SEPARATOR := ,
17PLATFORM_LIST := $(subst $(LIST_SEPARATOR), ,$(PLATFORM))
18
19GN_ARGS := project="$(PROJECT)"
20GN_ARGS += toolchain_lib="$(TOOLCHAIN_LIB)"
21ifeq ($(filter $(ENABLE_ASSERTIONS), 1 0),)
22         $(error invalid value for ENABLE_ASSERTIONS, should be 1 or 0)
23endif
24GN_ARGS += enable_assertions="$(ENABLE_ASSERTIONS)"
25
26# If HAFNIUM_HERMETIC_BUILD is "true" (not default), invoke `make` inside
27# a container. The 'run_in_container.sh' script will set the variable value to
28# 'inside' to avoid recursion.
29ifeq ($(HAFNIUM_HERMETIC_BUILD),true)
30
31# TODO: This is not ideal as (a) we invoke the container once per command-line
32# target, and (b) we cannot pass `make` arguments to the script. We could
33# consider creating a bash alias for `make` to invoke the script directly.
34
35# Need to define at least one non-default target.
36all:
37	@$(CURDIR)/build/run_in_container.sh make PROJECT=$(PROJECT) \
38		ENABLE_ASSERTIONS=$(ENABLE_ASSERTIONS) $@
39
40# Catch-all target.
41.DEFAULT:
42	@$(CURDIR)/build/run_in_container.sh make PROJECT=$(PROJECT) \
43		ENABLE_ASSERTIONS=$(ENABLE_ASSERTIONS) $@
44
45else  # HAFNIUM_HERMETIC_BUILD
46
47# Set path to prebuilts used in the build.
48UNAME_S := $(shell uname -s | tr '[:upper:]' '[:lower:]')
49UNAME_M := $(shell uname -m)
50
51ifeq ($(UNAME_M),x86_64)
52UNAME_M := x64
53endif
54
55PREBUILTS := $(CURDIR)/prebuilts/$(UNAME_S)-$(UNAME_M)
56GN ?= $(PREBUILTS)/gn/gn
57NINJA ?= $(PREBUILTS)/ninja/ninja
58
59CHECKPATCH := $(CURDIR)/third_party/linux/scripts/checkpatch.pl \
60	--ignore BRACES,SPDX_LICENSE_TAG,VOLATILE,SPLIT_STRING,AVOID_EXTERNS,USE_SPINLOCK_T,NEW_TYPEDEFS,INITIALISED_STATIC,FILE_PATH_CHANGES,EMBEDDED_FUNCTION_NAME,SINGLE_STATEMENT_DO_WHILE_MACRO,MACRO_WITH_FLOW_CONTROL,PREFER_PACKED,PREFER_ALIGNED,INDENTED_LABEL,SPACING,PREFER_PRINTF --quiet
61
62# Specifies the grep pattern for ignoring specific files in checkpatch.
63# C++ headers, *.hh, are automatically excluded.
64# Separate the different items in the list with a grep or (\|).
65# debug_el1.c : uses XMACROS, which checkpatch doesn't understand.
66# perfmon.c : uses XMACROS, which checkpatch doesn't understand.
67# feature_id.c : uses XMACROS, which checkpatch doesn't understand.
68CHECKPATCH_IGNORE := "src/arch/aarch64/hypervisor/debug_el1.c\|src/arch/aarch64/hypervisor/perfmon.c\|src/arch/aarch64/hypervisor/feature_id.c"
69
70OUT ?= out/$(PROJECT)
71OUT_DIR = out/$(PROJECT)
72
73.PHONY: all
74all: $(OUT_DIR)/build.ninja
75ifeq ($(PLATFORM),default)
76	@$(NINJA) -C $(OUT_DIR)
77else
78	@build/check_platform_exists.py $(PROJECT) $(PLATFORM_LIST) || (exit 1)
79	@for PLAT in $(PLATFORM_LIST); do \
80		$(NINJA) -C $(OUT_DIR) project/$(PROJECT):$$PLAT; \
81	done
82endif
83
84$(OUT_DIR)/build.ninja:
85	@$(GN) --export-compile-commands gen --args='$(GN_ARGS)' $(OUT_DIR)
86
87doc:
88	@echo "  BUILD DOCUMENTATION"
89	make --no-print-directory -C docs html
90
91.PHONY: clean
92clean:
93	@$(NINJA) -C $(OUT_DIR) -t clean
94
95.PHONY: clobber
96clobber:
97	rm -rf $(OUT)
98
99# see .clang-format.
100.PHONY: format
101format:
102	@echo "Formatting..."
103	@find src/ -name \*.c -o -name \*.cc -o -name \*.h | xargs -r clang-format -style file -i
104	@find inc/ -name \*.c -o -name \*.cc -o -name \*.h | xargs -r clang-format -style file -i
105	@find test/ -name \*.c -o -name \*.cc -o -name \*.h | xargs -r clang-format -style file -i
106	@find project/ -name \*.c -o -name \*.cc -o -name \*.h | xargs -r clang-format -style file -i
107	@find vmlib/ -name \*.c -o -name \*.cc -o -name \*.h | xargs -r clang-format -style file -i
108	@find . \( -name \*.gn -o -name \*.gni \) | xargs -n1 $(GN) format
109
110.PHONY: checkpatch
111checkpatch:
112	@find src/ -name \*.c -o -name \*.h | grep -v $(CHECKPATCH_IGNORE) | xargs $(CHECKPATCH) -f
113	@find inc/ -name \*.c -o -name \*.h | grep -v $(CHECKPATCH_IGNORE) | xargs $(CHECKPATCH) -f
114	# TODO: enable for test/
115	@find project/ -name \*.c -o -name \*.h | grep -v $(CHECKPATCH_IGNORE) | xargs $(CHECKPATCH) -f
116
117# see .clang-tidy.
118.PHONY: tidy
119tidy: $(OUT_DIR)/build.ninja
120	@$(NINJA) -C $(OUT_DIR)
121	@echo "Tidying..."
122	# TODO: enable readability-magic-numbers once there are fewer violations.
123	# TODO: enable for c++ tests as it currently gives spurious errors.
124	@find src/ \( -name \*.c \) | xargs clang-tidy -p $(OUT_DIR) -fix
125	@find test/ \( -name \*.c \) | xargs clang-tidy -p $(OUT_DIR) -fix
126
127.PHONY: check
128check: $(OUT_DIR)/build.ninja
129	@$(NINJA) -C $(OUT_DIR)
130	@echo "Checking..."
131	# TODO: enable for c++ tests as it currently gives spurious errors.
132	@find src/ \( -name \*.c \) | xargs clang-check -p $(OUT_DIR) -analyze -fix-what-you-can
133	@find test/ \( -name \*.c \) | xargs clang-check -p $(OUT_DIR) -analyze -fix-what-you-can
134
135.PHONY: license
136license:
137	@find build/ -name \*.S -o -name \*.c -o -name \*.cc -o -name \*.h -o -name \*.dts -o -name \*.ld | xargs -n1 python3 build/license.py --style c
138	@find inc/ -name \*.S -o -name \*.c -o -name \*.cc -o -name \*.h -o -name \*.dts | xargs -n1 python3 build/license.py --style c
139	@find src/ -name \*.S -o -name \*.c -o -name \*.cc -o -name \*.h -o -name \*.dts | xargs -n1 python3 build/license.py --style c
140	@find test/ -name \*.S -o -name \*.c -o -name \*.cc -o -name \*.h -o -name \*.dts | xargs -n1 python3 build/license.py --style c
141	@find vmlib/ -name \*.S -o -name \*.c -o -name \*.cc -o -name \*.h -o -name \*.dts | xargs -n1 python3 build/license.py --style c
142	@find build/ -name \*.py -o -name \*.sh -o -name \*.inc -o -name Dockerfile* | xargs -n1 python3 build/license.py --style hash
143	@find kokoro/ -name \*.sh -o -name \*.cfg | xargs -n1 python3 build/license.py --style hash
144	@find test/ -name \*.py| xargs -n1 python3 build/license.py --style hash
145	@find . \( -path ./driver/linux -o -path ./third_party \) -prune -o \( -name \*.gn -o -name \*.gni \) -print | xargs -n1 python3 build/license.py --style hash
146
147.PHONY: update-prebuilts
148update-prebuilts: prebuilts/linux-aarch64/linux/vmlinuz
149
150prebuilts/linux-aarch64/linux/vmlinuz: $(OUT_DIR)/build.ninja
151	@$(NINJA) -C $(OUT_DIR) "third_party/linux"
152	cp out/reference/obj/third_party/linux/linux.bin $@
153
154.PHONY: list
155list:
156	@build/check_platform_exists.py $(PROJECT)
157
158endif  # HAFNIUM_HERMETIC_BUILD
159