summaryrefslogtreecommitdiff
path: root/GNUmakefile
blob: 272306ab052ce427540f5513a692ee7e674467b3 (plain)
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
# GNUmakefile - Main build script for sbc-harness project
#
# Copyright (C) 2024-2025  Luke T. Shumaker <lukeshu@lukeshu.com>
# SPDX-License-Identifier: AGPL-3.0-or-later

# Project configuration ########################################################

linux.git = $(HOME)/src/github.com/torvalds/linux

all: build
.PHONY: all

# Configure GNU Make itself ####################################################

ifeq ($(filter notintermediate,$(.FEATURES)),)
$(error This $(firstword $(MAKEFILE_LIST)) requies GNU Make 4.4 or later for .NOTINTERMEDIATE)
endif

.NOTINTERMEDIATE:
.DELETE_ON_ERROR:

.PHONY: FORCE

# `generate` ###################################################################

generate/files =

generate/files += COPYING.txt
COPYING.txt:
	wget --no-use-server-timestamps -O $@ https://www.gnu.org/licenses/agpl-3.0.txt

generate/files += 3rd-party/COPYING.newlib.txt
3rd-party/COPYING.newlib.txt: /usr/share/licenses/arm-none-eabi-newlib/COPYING.NEWLIB
	cp $< $@

generate/files += libmisc/tests/test_obj_autobox.c
libmisc/tests/test_obj_autobox.c: %: %.gen libmisc/tests/test_obj_nest.c
	$^ $@

generate/files += 3rd-party/linux-errno.txt
3rd-party/linux-errno.txt: lib9p/linux-errno.txt.gen
	$< $(linux.git) $@

generate/files += libmisc/error_generated.c
libmisc/error_generated.c: %: %.gen libmisc/include/libmisc/error.h
	$^ $@

generate/files += lib9p/idl/2010-9P2000.L.9p
lib9p/idl/2010-9P2000.L.9p: %: %.gen 3rd-party/linux-errno.txt
	$^ >$@

generate/files += lib9p/core_generated.c lib9p/core_include/lib9p/_core_generated.h
lib9p/core_generated.c lib9p/core_include/lib9p/_core_generated.h &: lib9p/core.gen lib9p/idl/__init__.py lib9p/core_gen lib9p/core_gen/*.py lib9p/idl lib9p/idl/2010-9P2000.L.9p lib9p/idl/*.9p
	$< $(sort $(filter %.9p,$^))

generate/files += lib9p/srv_generated.c
lib9p/srv_generated.c: %: %.gen libmisc/include/libmisc/error.h
	$^ $@

generate/files += lib9p/tests/test_compile.c
lib9p/tests/test_compile.c: %: %.gen lib9p/core_include/lib9p/_core_generated.h
	$^ $@

generate/files += libusb/include/libusb/tusb_helpers.h 3rd-party/MS-LCID.pdf 3rd-party/MS-LCID.txt
libusb/include/libusb/tusb_helpers.h 3rd-party/MS-LCID.pdf 3rd-party/MS-LCID.txt &: libusb/include/libusb/tusb_helpers.h.gen
	$^

generate/files += build-aux/sources.mk
ifeq ($(INNER),)
nonsource/files = $(generate/files)
nonsource/files += 3rd-party/COPYING.wiznet-dhcp.txt
# 100644 blob/regular file
# 100755 blob/executable file
# 120000 blob/symlink
# 160000 commit (submodule)
# 040000 tree (directory)
build-aux/sources.mk: $(if $(wildcard .git),FORCE)
	git ls-files --format='%(objectmode) %(path)'              \
	| sed -n 's/^100... //p'                                   \
	| grep -vFx $(foreach f,$(nonsource/files),-e $f)          \
	| sed 's,^,$(CURDIR)/,' | xargs editorconfig               \
	| sed -nE -e 's,\[$(CURDIR)/(.*)\],\1,p' -e 's/^_mode=//p' \
	| sed -E '{N;s/(.*)\n(.*)/sources_\2 += \1/;}'             \
	| sort                                                     \
	>$@.tmp
	if ! cmp -s $@.tmp $@; then mv $@.tmp $@; fi
	@echo '################################################################################'
endif

generate:
ifeq ($(INNER),)
generate: $(generate/files)
endif
.PHONY: generate

generate-clean:
	rm -f -- $(generate/files)
.PHONY: generate-clean

# `build` and `check` ##########################################################

# define the matrix

platforms_build = rp2040
platforms_check = host
platforms = $(platforms_build) $(platforms_check)
build_types = Debug Release RelWithDebInfo MinSizeRel

# span the matrix

build: $(foreach t,$(build_types),$(foreach p,$(platforms_build),build/$p-$t/build))
.PHONY: build

build-check: $(foreach t,$(build_types),$(foreach p,$(platforms_check),build/$p-$t/build))
.PHONY: build-check

check: generate
	$(MAKE) -k INNER=t $(foreach t,$(build_types),$(foreach p,$(platforms_check),build/$p-$t/check))
.PHONY: check

# define the cells

# build/{matrix}/Makefile
$(foreach t,$(build_types),$(foreach p,$(platforms),build/$p-$t/Makefile)): build/%/Makefile:
	mkdir -p $(@D) && cd $(@D) && cmake -DPICO_PLATFORM=$(firstword $(subst -, ,$*)) -DCMAKE_BUILD_TYPE=$(lastword $(subst -, ,$*)) ../..

# build/{matrix}/build
$(foreach t,$(build_types),$(foreach p,$(platforms),build/$p-$t/build)): build/%/build: build/%/Makefile generate
	$(MAKE) -C $(<D)
.PHONY: $(foreach t,$(build_types),$(foreach p,$(platforms),build/$p-$t/build))

# build/{matrix}/check
#
# `gcc` writes .gcno
# Running the program writes .gcda (updates existing files, concurrent-safe)
# GCC `gcov` post-processes .gcno+.gcda to .gcov
# `gcovr` is a Python script that calls `gcov` and merges and post-processes the .gcov files to other formats
gcovr_flags  = --txt=$(@D)/coverage.txt
gcovr_flags += --html=$(@D)/coverage.html --html-details --html-single-page=js-enabled
gcovr_flags += --sort uncovered-number --sort-reverse
$(foreach t,$(build_types),$(foreach p,$(platforms_check),build/$p-$t/check)): build/%/check: build/%/build
	./build-aux/gcov-prune $(@D)
	+cd $(@D) && ctest --output-on-failure $(if $(filter --jobserver-auth=%,$(MAKEFLAGS)),--parallel)
	gcovr $(gcovr_flags) -- $(@D)
.PHONY: $(foreach t,$(build_types),$(foreach p,$(platforms_check),build/$p-$t/check))

# `lint` and `format` ##########################################################

-include build-aux/sources.mk
sources_all := $(foreach v,$(filter sources_%,$(.VARIABLES)),$($v))

build-aux/venv: build-aux/requirements.txt
	python3 -m venv $@
	$@/bin/pip install -r $<
	touch --no-create $@

flashimgs = $(patsubst flashimg/%/CMakeLists.txt,%,$(filter flashimg/%/CMakeLists.txt,$(sources_cmake)))

# `lint` ###############################
lint: lint/src .WAIT lint/bin
lint/src:
	$(MAKE) -k INNER=t $(patsubst sources_%,lint/%,$(filter-out sources_all,$(filter sources_%,$(.VARIABLES))))
lint/bin: build build-aux/lint-bin
	./build-aux/lint-bin $(foreach i,$(flashimgs),$(foreach t,$(build_types),$(foreach p,$(platforms_build),build/$p-$t/flashimg/$i/$i.elf)))
$(patsubst sources_%,lint/%,$(filter-out sources_all,$(filter sources_%,$(.VARIABLES)))): build-aux/lint-src
	./build-aux/lint-src $(@F) $(sources_$(@F))
lint/python3: build-aux/venv
.PHONY: lint lint/%

# `format` #############################
# generic ##########
format: $(patsubst sources_%,format/%,$(filter-out sources_all sources_unknown,$(filter sources_%,$(.VARIABLES))))
.PHONY: format format/%
# specific #########
format/c: format/%:
	@: TODO: Adopt a C code-formatter
format/sh format/bash: format/%:
	shfmt --write --case-indent --simplify $(sources_$(@F))
format/python3: ./build-aux/venv
	./build-aux/venv/bin/black $(sources_$(@F))
	./build-aux/venv/bin/isort $(sources_$(@F))
format/make format/cmake format/gitignore format/ini format/9p-idl format/9p-log format/markdown format/pip format/man-cat:
	@: TODO: Write/adopt formatters for these file types