-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathMakefile
338 lines (253 loc) · 11.6 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
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
-include devutils/Makefile.common
include Makefile.common
.DEFAULT_GOAL := all
VERBOSE ?= @
TEST_PROCS ?= $(shell nproc)
RECORDFLUX_ORIGIN ?= https://github.com/AdaCore
GNATCOLL_ORIGIN ?= https://github.com/AdaCore
LANGKIT_ORIGIN ?= https://github.com/AdaCore
ADASAT_ORIGIN?= https://github.com/AdaCore
VERSION ?= $(shell python3 -c "import setuptools_scm; print(setuptools_scm.get_version())")
SDIST ?= dist/RecordFlux-$(VERSION).tar.gz
VSIX ?= ide/vscode/recordflux.vsix
GENERATED_DIR = generated
BUILD_GENERATED_DIR := $(MAKEFILE_DIR)/$(BUILD_DIR)/$(GENERATED_DIR)
PYTHON_PACKAGES = bin doc/language_reference/conf.py doc/user_guide/conf.py examples/apps ide language rflx tests tools stubs setup.py
DEVUTILS_HEAD = 5a36842e2cb29287acfea5b84393df0879f5bd1a
GNATCOLL_HEAD = 25459f07a2e96eb0f28dcfd5b03febcb72930987
LANGKIT_HEAD = 65e2dab678b2606e3b0eada64b7ef4fd8cae91bb
ADASAT_HEAD = f948e2271aec51f9313fa41ff3c00230a483f9e8
SHELL = /bin/bash
PYTEST = python3 -m pytest -n$(TEST_PROCS) -vv --timeout=7200
APPS := $(filter-out __init__.py,$(notdir $(wildcard examples/apps/*)))
export PYTHONPATH := $(MAKEFILE_DIR)
# Switch to a specific revision of the git repository.
#
# @param $(1) directory of the git repository
# @param $(2) commit id
define checkout_repo
$(shell test -d $(1) && git -C $(1) fetch && git -C $(1) -c advice.detachedHead=false checkout $(2) > /dev/null)
endef
# Get the HEAD revision of the git repository.
#
# @param $(1) directory of the git repository
# @param $(2) default value
repo_head = $(shell test -d $(1) && git -C $(1) rev-parse HEAD || echo $(2))
# Switch to the expected revision of the git repository, if the current HEAD is not the expected one.
#
# @param $(1) directory of the git repository
# @param $(2) expected revision
reinit_repo = $(if $(filter-out $(2),$(call repo_head,$(1),$(2))),$(call checkout_repo,$(1),$(2)),)
# Remove the git repository, if no changes are present.
#
# The function looks for changed and untracked files as well as commits that are not pushed to a
# remote branch. If the repository is unchanged, it will be removed completely.
#
# @param $(1) directory of the git repository
define remove_repo
$(if
$(or
$(shell test -d $(1) && git -C $(1) status --porcelain),
$(shell test -d $(1) && git -C $(1) log --branches --not --remotes --format=oneline)
),
$(info Keeping $(1) due to local changes),
$(shell rm -rf $(1))
)
endef
$(shell $(call reinit_repo,devutils,$(DEVUTILS_HEAD)))
$(shell $(call reinit_repo,contrib/gnatcoll-bindings,$(GNATCOLL_HEAD)))
$(shell $(call reinit_repo,contrib/langkit,$(LANGKIT_HEAD)))
$(shell $(call reinit_repo,contrib/adasat,$(ADASAT_HEAD)))
.PHONY: all
all: check test prove
.PHONY: init deinit
init: devutils contrib/gnatcoll-bindings contrib/langkit contrib/adasat
$(VERBOSE)$(call checkout_repo,devutils,$(DEVUTILS_HEAD))
$(VERBOSE)$(call checkout_repo,contrib/gnatcoll-bindings,$(GNATCOLL_HEAD))
$(VERBOSE)$(call checkout_repo,contrib/langkit,$(LANGKIT_HEAD))
$(VERBOSE)$(call checkout_repo,contrib/adasat,$(ADASAT_HEAD))
$(VERBOSE)rm -f contrib/langkit/langkit/py.typed
$(VERBOSE)ln -sf devutils/pyproject.toml
deinit:
$(VERBOSE)$(call remove_repo,devutils)
$(VERBOSE)$(call remove_repo,contrib/gnatcoll-bindings)
$(VERBOSE)$(call remove_repo,contrib/langkit)
$(VERBOSE)$(call remove_repo,contrib/adasat)
$(VERBOSE)rm -f pyproject.toml
devutils:
$(VERBOSE)git clone $(RECORDFLUX_ORIGIN)/RecordFlux-devutils.git devutils
contrib/gnatcoll-bindings:
$(VERBOSE)mkdir -p contrib
$(VERBOSE)git clone $(GNATCOLL_ORIGIN)/gnatcoll-bindings.git contrib/gnatcoll-bindings
contrib/langkit:
$(VERBOSE)mkdir -p contrib
$(VERBOSE)git clone $(LANGKIT_ORIGIN)/langkit.git contrib/langkit
contrib/adasat:
$(VERBOSE)mkdir -p contrib
$(VERBOSE)git clone $(ADASAT_ORIGIN)/adasat.git contrib/adasat
.PHONY: check check_dependencies check_contracts check_doc
check: check_dependencies common_check check_contracts check_doc
check_dependencies:
tools/check_dependencies.py
check_contracts:
pyicontract-lint $(PYTHON_PACKAGES)
check_doc:
tools/check_doc.py -d doc -x doc/user_guide/gfdl.rst
.PHONY: test test_coverage test_unit_coverage test_property test_tools test_ide test_optimized test_compilation test_binary_size test_specs test_installation test_apps
test: test_coverage test_unit_coverage test_language_coverage test_property test_tools test_ide test_optimized test_compilation test_binary_size test_specs test_installation test_apps
# A separate invocation of `coverage report` is needed to exclude `$(GENERATED_DIR)` in the coverage report.
# Currently, pytest's CLI does not allow the specification of omitted directories
# (cf. https://github.com/pytest-dev/pytest-cov/issues/373).
test_coverage:
timeout -k 60 7200 $(PYTEST) --cov=rflx --cov=tests/unit --cov=tests/integration --cov-branch --cov-fail-under=0 --cov-report= tests/unit tests/integration
coverage report --fail-under=100 --show-missing --skip-covered --omit="$(GENERATED_DIR)/*"
test_unit_coverage:
timeout -k 60 7200 $(PYTEST) --cov=rflx --cov=tests/unit --cov=tools --cov-branch --cov-fail-under=0 --cov-report= tests/unit tests/tools
coverage report --fail-under=94.68 --show-missing --skip-covered --omit="$(GENERATED_DIR)/*"
test_language_coverage:
timeout -k 60 7200 $(PYTEST) --cov=rflx_lang --cov-branch --cov-fail-under=73.8 --cov-report=term-missing:skip-covered tests/language
test_property:
$(PYTEST) tests/property
test_tools:
$(PYTEST) tests/tools
test_ide:
$(PYTEST) tests/ide
# TODO(eng/recordflux/RecordFlux#1361): Execute `test` instead of `build`
$(MAKE) -C ide/vscode build
test_optimized:
PYTHONOPTIMIZE=1 $(PYTEST) tests/unit tests/integration tests/compilation
test_apps:
$(foreach app,$(APPS),$(MAKE) -C examples/apps/$(app) test || exit;)
test_compilation:
# Skip test for FSF GNAT to prevent violations of restriction "No_Secondary_Stack" in AUnit units
[[ "${GNAT}" == fsf* ]] || $(MAKE) -C tests/spark build_strict
$(MAKE) -C tests/spark clean
$(MAKE) -C tests/spark test
$(MAKE) -C examples/apps/ping build
$(MAKE) -C examples/apps/dhcp_client build
$(MAKE) -C examples/apps/spdm_responder lib
$(PYTEST) tests/compilation
$(MAKE) -C tests/spark test NOPREFIX=1
$(MAKE) -C tests/spark clean
$(MAKE) -C tests/spark test_optimized
test_binary_size:
$(MAKE) -C examples/apps/dhcp_client test_binary_size
$(MAKE) -C examples/apps/spdm_responder test_binary_size
test_specs:
$(PYTEST) tests/examples/specs_test.py
test_installation: export PYTHONPATH=
test_installation: $(SDIST)
rm -rf $(BUILD_DIR)/venv $(BUILD_DIR)/test_installation
mkdir -p $(BUILD_DIR)/test_installation
python3 -m venv $(BUILD_DIR)/venv
$(BUILD_DIR)/venv/bin/pip install $(SDIST)
$(BUILD_DIR)/venv/bin/rflx --version
HOME=$(BUILD_DIR)/test_installation $(BUILD_DIR)/venv/bin/rflx install gnatstudio
test -f $(BUILD_DIR)/test_installation/.gnatstudio/plug-ins/recordflux.py
.PHONY: prove prove_tests prove_python_tests prove_apps prove_property_tests
prove: prove_tests prove_python_tests prove_apps
prove_tests: $(GNATPROVE_CACHE_DIR)
$(MAKE) -C tests/spark prove
prove_python_tests: export GNATPROVE_PROCS=1
prove_python_tests: $(GNATPROVE_CACHE_DIR)
$(PYTEST) tests/verification
prove_apps: $(GNATPROVE_CACHE_DIR)
$(foreach app,$(APPS),$(MAKE) -C examples/apps/$(app) prove || exit;)
prove_property_tests: $(GNATPROVE_CACHE_DIR)
$(PYTEST) tests/property_verification
.PHONY: install_build_deps install install_devel upgrade_devel install_devel_edge install_git_hooks install_gnat printenv_gnat
install_build_deps:
pip3 install -U "pip>=22.2"
pip3 install packaging setuptools_scm wheel build contrib/langkit
install: install_build_deps $(SDIST)
$(MAKE) -C devutils install_devel
pip3 install --force-reinstall "$(SDIST)[devel]"
install_devel: install_build_deps parser
$(MAKE) -C devutils install_devel
rm -rf $(BUILD_DIR)/__editable__.*
pip3 install --force-reinstall -e ".[devel]" --config-settings editable_mode=strict
install_devel_edge: install_devel
$(MAKE) -C devutils install_devel_edge
install_git_hooks:
install -m 755 tools/pre-{commit,push} .git/hooks/
install_gnat: FSF_GNAT_VERSION ?= 11.2.4
install_gnat: GPRBUILD_VERSION ?= 22.0.1
install_gnat:
test -d build/alire || ( \
mkdir -p build && \
cd build && \
alr -n init --lib alire && \
cd alire && \
alr toolchain --select --local gnat_native=$(FSF_GNAT_VERSION) gprbuild=$(GPRBUILD_VERSION) && \
alr -n with aunit gnatcoll_iconv gnatcoll_gmp \
)
printenv_gnat:
@test -d build/alire && (\
cd build/alire && \
alr printenv \
) || true
.PHONY: generate generate_apps
generate:
tools/generate_spark_test_code.py
generate_apps:
$(foreach app,$(APPS),$(MAKE) -C examples/apps/$(app) generate || exit;)
.PHONY: doc html_doc pdf_doc
doc: html_doc pdf_doc
html_doc: check_doc build_html_doc
pdf_doc: check_doc build_pdf_doc
.PHONY: build_doc build_doc_user_guide build_doc_language_reference
build_doc: build_html_doc build_pdf_doc
build_doc_user_guide: build_html_doc_user_guide build_pdf_doc_user_guide
build_doc_language_reference: build_html_doc_language_reference build_pdf_doc_language_reference
.PHONY: build_html_doc build_html_doc_language_reference build_html_doc_user_guide
build_html_doc: build_html_doc_language_reference build_html_doc_user_guide
build_html_doc_language_reference:
$(MAKE) -C doc/language_reference html
build_html_doc_user_guide:
$(MAKE) -C doc/user_guide html
.PHONY: build_pdf_doc build_pdf_doc_language_reference build_pdf_doc_user_guide
build_pdf_doc: build_pdf_doc_language_reference build_pdf_doc_user_guide
build_pdf_doc_language_reference:
$(MAKE) -C doc/language_reference latexpdf
build_pdf_doc_user_guide:
$(MAKE) -C doc/user_guide latexpdf
.PHONY: dist anod_dist
dist: $(SDIST)
$(SDIST): $(GENERATED_DIR)/python/librflxlang $(VSIX) pyproject.toml setup.py MANIFEST.in $(wildcard bin/*) $(wildcard rflx/*)
python3 -m build --sdist
anod_dist: $(GENERATED_DIR)/python/librflxlang pyproject.toml setup.py MANIFEST.in $(wildcard bin/*) $(wildcard rflx/*)
python3 -m build
$(GENERATED_DIR)/python/librflxlang: export PYTHONPATH=$(MAKEFILE_DIR)
$(GENERATED_DIR)/python/librflxlang: $(wildcard language/*.py)
mkdir -p $(BUILD_GENERATED_DIR)
language/generate.py $(BUILD_GENERATED_DIR) $(VERSION)
cp -a $(MAKEFILE_DIR)/contrib/langkit $(BUILD_GENERATED_DIR)/
cp -a $(MAKEFILE_DIR)/contrib/gnatcoll-bindings $(BUILD_GENERATED_DIR)/
cp -a $(MAKEFILE_DIR)/contrib/adasat $(BUILD_GENERATED_DIR)/
rm -rf $(GENERATED_DIR)
mv $(BUILD_GENERATED_DIR) $(GENERATED_DIR)
$(VSIX):
@echo $(VSIX)
$(MAKE) -C ide/vscode dist
.PHONY: parser
parser: $(GENERATED_DIR)/python/librflxlang/librflxlang.so
$(GENERATED_DIR)/python/librflxlang/librflxlang.so: export GPR_PROJECT_PATH := \
$(GPR_PROJECT_PATH):$(GENERATED_DIR)/langkit/langkit/support:$(GENERATED_DIR)/gnatcoll-bindings/gmp:$(GENERATED_DIR)/gnatcoll-bindings/iconv:$(GENERATED_DIR)/adasat
$(GENERATED_DIR)/python/librflxlang/librflxlang.so: export GNATCOLL_ICONV_OPT := -v
$(GENERATED_DIR)/python/librflxlang/librflxlang.so: $(wildcard language/*.py) | $(GENERATED_DIR)/python/librflxlang
gprbuild -p -j0 -P$(GENERATED_DIR)/librflxlang.gpr \
-XLIBRARY_TYPE=static-pic \
-XLIBRFLXLANG_LIBRARY_TYPE=relocatable \
-XLIBRFLXLANG_STANDALONE=encapsulated
cp $(GENERATED_DIR)/lib/relocatable/dev/librflxlang.so $@
.PHONY: clean clean_all
clean:
rm -rf $(BUILD_DIR)/[^_]* $(GENERATED_DIR) .coverage .coverage.* .hypothesis .mypy_cache .pytest_cache .ruff_cache
$(MAKE) -C examples/apps/ping clean
$(MAKE) -C examples/apps/dhcp_client clean
$(MAKE) -C examples/apps/spdm_responder clean
$(MAKE) -C doc/language_reference clean
$(MAKE) -C doc/user_guide clean
$(MAKE) -C ide/vscode clean
clean_all: clean
rm -rf $(BUILD_DIR)/*