blob: 140a1b4cda6873f6d7d3b010bb2b5bb63ea262b2 (
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
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
|
.PHONY: all build install doc clean html deb pkg bintar sdist
.PHONY: profile-build profile-rgl-time profile-rgl-memory profile-rgl-clean
.PHONY: bench-build bench-rgl bench-rgl-pre-pmcfg bench-rgl-clean
.PHONY: test-pmcfg test-pmcfg-core test-pmcfg-equivalence test-pmcfg-rgl-equivalence test-pmcfg-clean
# This gets the numeric part of the version from the cabal file
VERSION=$(shell sed -ne "s/^version: *\([0-9.]*\).*/\1/p" gf.cabal)
# Check if stack is installed
STACK=$(shell if hash stack 2>/dev/null; then echo "1"; else echo "0"; fi)
# Check if cabal >= 2.4 is installed (with v1- and v2- commands)
CABAL_NEW=$(shell if cabal v1-repl --help >/dev/null 2>&1 ; then echo "1"; else echo "0"; fi)
ifeq ($(STACK),1)
CMD=stack
else
CMD=cabal
ifeq ($(CABAL_NEW),1)
CMD_PFX=v1-
endif
endif
# Profiling configuration.
#
# The profiling targets intentionally use Stack even when the normal build falls
# back to cabal, because Stack's --work-dir makes it easy to keep profiled and
# unprofiled build products separate. The default RGL target is German, which
# is complex and a good compiler stress test; override
# RGL_PROFILE_MODULES or RGL_PROFILE_GF_OPTIONS for different experiments.
PROFILE_STACK_WORK ?= .stack-work-profile
PROFILE_GHC_OPTIONS ?= -fprof-auto -fprof-cafs
PROFILE_DIR ?= $(CURDIR)/profile
RGL_DIR ?= ../gf-rgl
RGL_PROFILE_DIR ?= $(PROFILE_DIR)/rgl
RGL_PROFILE_GFO_DIR ?= $(RGL_PROFILE_DIR)/gfo
RGL_PROFILE_PGF_DIR ?= $(RGL_PROFILE_DIR)/pgf
RGL_PROFILE_MODULES ?= $(RGL_DIR)/src/german/LangGer.gf
RGL_PROFILE_IMPORT_DIRS ?= $(RGL_DIR)/src/api
RGL_PROFILE_IMPORT_OPTIONS = $(foreach dir,$(RGL_PROFILE_IMPORT_DIRS),-i $(dir))
RGL_PROFILE_GF_OPTIONS ?= --make --quiet --src --preproc=mkPresent --gf-lib-path=$(RGL_PROFILE_GFO_DIR) --gfo-dir=$(RGL_PROFILE_GFO_DIR) --output-dir=$(RGL_PROFILE_PGF_DIR) --name=RGLProfile $(RGL_PROFILE_IMPORT_OPTIONS)
RGL_PROFILE_GF = stack --stack-yaml $(CURDIR)/stack.yaml --work-dir $(PROFILE_STACK_WORK) exec --profile gf --
RGL_TIME_STEM ?= $(RGL_PROFILE_DIR)/rgl-time
RGL_MEMORY_STEM ?= $(RGL_PROFILE_DIR)/rgl-memory
RGL_MEMORY_RTS ?= -hc
RGL_HEAP_SAMPLE_INTERVAL ?= 0.1
BENCH_STACK_WORK ?= $(PROFILE_STACK_WORK)
BENCH_PROFILE_FLAGS ?= --profile
BENCH_GHC_OPTIONS ?= $(PROFILE_GHC_OPTIONS)
BENCH_TARGET ?= gf:bench:gf-compiler-bench
BENCH_TASTY_OPTIONS ?=
BENCH_PRE_PMCFG_FLAG ?= --flag gf:pre-pmcfg
BENCH_PRE_PMCFG_STACK_WORK ?= .stack-work-profile-pre-pmcfg
RGL_BENCH_DIR ?= $(PROFILE_DIR)/rgl-bench
RGL_BENCH_GFO_DIR ?= $(RGL_BENCH_DIR)/gfo
RGL_BENCH_PGF_DIR ?= $(RGL_BENCH_DIR)/pgf
RGL_BENCH_NAME ?= RGLBench
RGL_BENCH_MODULES ?=
RGL_BENCH_IMPORT_DIRS ?= $(RGL_PROFILE_IMPORT_DIRS) $(RGL_DIR)/src/prelude
RGL_BENCH_PRE_PMCFG_DIR ?= $(PROFILE_DIR)/rgl-bench-pre-pmcfg
RGL_BENCH_PRE_PMCFG_NAME ?= RGLBenchPrePmcfg
BENCH_RTS_OPTIONS ?= +RTS -T -RTS
BENCH_STACK = stack --stack-yaml $(CURDIR)/stack.yaml --work-dir $(BENCH_STACK_WORK)
PMCFG_TEST_CORE_STACK_WORK ?= .stack-work-pmcfg-test-hooks
PMCFG_TEST_STACK_WORK ?= .stack-work-pmcfg-test
PMCFG_TEST_PRE_STACK_WORK ?= .stack-work-pmcfg-test-pre
PMCFG_TEST_DIR ?= $(PROFILE_DIR)/pmcfg-test
PMCFG_EQ_DIR ?= $(PMCFG_TEST_DIR)/equivalence
PMCFG_EQ_NAME ?= PMCFGEquiv
PMCFG_TEST_IMPORT_DIRS ?= testsuite/canonical/grammars
PMCFG_TEST_IMPORT_OPTIONS = $(foreach dir,$(PMCFG_TEST_IMPORT_DIRS),-i $(dir))
PMCFG_TEST_MODULES ?= testsuite/pmcfg/fixtures/PmcfgDiffCnc.gf testsuite/compiler/params/paramsCnc.gf testsuite/runtime/parser/LiteralsCnc.gf testsuite/runtime/parser/DummyNatCnc.gf testsuite/runtime/linearize/TestCnc.gf testsuite/compiler/check/lins/linsCnc.gf testsuite/canonical/gold/FoodsFin.gf
PMCFG_TEST_GF_OPTIONS ?= --make --quiet --src $(PMCFG_TEST_IMPORT_OPTIONS)
RGL_PMCFG_TEST_MODULES ?= $(RGL_DIR)/src/german/LangGer.gf $(RGL_DIR)/src/finnish/LangFin.gf $(RGL_DIR)/src/swedish/LangSwe.gf
RGL_PMCFG_TEST_GF_OPTIONS ?= --make --quiet --src --preproc=mkPresent $(RGL_PROFILE_IMPORT_OPTIONS)
all: build
dist/setup-config: gf.cabal Setup.hs WebSetup.hs
ifneq ($(STACK),1)
cabal ${CMD_PFX}configure
endif
build: dist/setup-config
${CMD} ${CMD_PFX}build
profile-build:
stack --work-dir $(PROFILE_STACK_WORK) build --profile --ghc-options "$(PROFILE_GHC_OPTIONS)"
profile-rgl-time: profile-build
@test -n "$(RGL_PROFILE_MODULES)" || { echo "No RGL modules found. Set RGL_DIR or RGL_PROFILE_MODULES."; exit 1; }
@command -v ghc-prof-flamegraph >/dev/null || { echo "Missing ghc-prof-flamegraph."; exit 1; }
rm -rf $(RGL_PROFILE_GFO_DIR) $(RGL_PROFILE_PGF_DIR)
mkdir -p $(RGL_PROFILE_DIR) $(RGL_PROFILE_GFO_DIR) $(RGL_PROFILE_PGF_DIR)
rm -f $(RGL_TIME_STEM).prof $(RGL_TIME_STEM).svg $(RGL_TIME_STEM).log
$(RGL_PROFILE_GF) $(RGL_PROFILE_GF_OPTIONS) $(RGL_PROFILE_MODULES) +RTS -s -p -po$(RGL_TIME_STEM) -RTS > $(RGL_TIME_STEM).log 2>&1 || { tail -n 80 $(RGL_TIME_STEM).log; exit 1; }
ghc-prof-flamegraph $(RGL_TIME_STEM).prof --output $(RGL_TIME_STEM).svg
profile-rgl-memory: profile-build
@test -n "$(RGL_PROFILE_MODULES)" || { echo "No RGL modules found. Set RGL_DIR or RGL_PROFILE_MODULES."; exit 1; }
@command -v hp2ps >/dev/null || { echo "Missing hp2ps."; exit 1; }
rm -rf $(RGL_PROFILE_GFO_DIR) $(RGL_PROFILE_PGF_DIR)
mkdir -p $(RGL_PROFILE_DIR) $(RGL_PROFILE_GFO_DIR) $(RGL_PROFILE_PGF_DIR)
rm -f $(RGL_MEMORY_STEM).hp $(RGL_MEMORY_STEM).ps $(RGL_MEMORY_STEM).aux $(RGL_MEMORY_STEM).tmp.ps $(RGL_MEMORY_STEM).log
$(RGL_PROFILE_GF) $(RGL_PROFILE_GF_OPTIONS) $(RGL_PROFILE_MODULES) +RTS -s $(RGL_MEMORY_RTS) -i$(RGL_HEAP_SAMPLE_INTERVAL) -po$(RGL_MEMORY_STEM) -RTS > $(RGL_MEMORY_STEM).log 2>&1 || { tail -n 80 $(RGL_MEMORY_STEM).log; exit 1; }
cd $(dir $(RGL_MEMORY_STEM)) && hp2ps $(notdir $(RGL_MEMORY_STEM)).hp
@if command -v gs >/dev/null 2>&1; then \
gs -q -dNOPAUSE -dBATCH -sOutputFile=$(RGL_MEMORY_STEM).tmp.ps -sDEVICE=ps2write -c "<</Orientation 1>> setpagedevice" -- $(RGL_MEMORY_STEM).ps && mv $(RGL_MEMORY_STEM).tmp.ps $(RGL_MEMORY_STEM).ps; \
else \
echo "Missing gs; leaving $(RGL_MEMORY_STEM).ps without orientation fix."; \
fi
profile-rgl-clean:
rm -rf $(RGL_PROFILE_DIR)
bench-build:
$(BENCH_STACK) build $(BENCH_TARGET) --bench --no-run-benchmarks $(BENCH_PROFILE_FLAGS) --ghc-options "$(BENCH_GHC_OPTIONS)"
bench-rgl: bench-build
@test -d "$(RGL_DIR)" || { echo "Missing RGL_DIR: $(RGL_DIR)"; exit 1; }
rm -rf $(RGL_BENCH_GFO_DIR) $(RGL_BENCH_PGF_DIR)
mkdir -p $(RGL_BENCH_GFO_DIR) $(RGL_BENCH_PGF_DIR)
GF_BENCH_RGL_DIR="$(RGL_DIR)" GF_BENCH_NAME="$(RGL_BENCH_NAME)" GF_BENCH_GFO_DIR="$(RGL_BENCH_GFO_DIR)" GF_BENCH_PGF_DIR="$(RGL_BENCH_PGF_DIR)" GF_BENCH_MODULES="$(RGL_BENCH_MODULES)" GF_BENCH_IMPORT_DIRS="$(RGL_BENCH_IMPORT_DIRS)" $(BENCH_STACK) bench $(BENCH_TARGET) $(BENCH_PROFILE_FLAGS) --ghc-options "$(BENCH_GHC_OPTIONS)" --benchmark-arguments "$(BENCH_TASTY_OPTIONS) $(BENCH_RTS_OPTIONS)"; \
status=$$?; \
if test -f gf-compiler-bench.prof; then mv gf-compiler-bench.prof "$(RGL_BENCH_DIR)/gf-compiler-bench.prof"; fi; \
exit $$status
bench-rgl-pre-pmcfg:
$(MAKE) bench-rgl BENCH_STACK_WORK="$(BENCH_PRE_PMCFG_STACK_WORK)" RGL_BENCH_DIR="$(RGL_BENCH_PRE_PMCFG_DIR)" RGL_BENCH_NAME="$(RGL_BENCH_PRE_PMCFG_NAME)" BENCH_PROFILE_FLAGS="$(BENCH_PROFILE_FLAGS) $(BENCH_PRE_PMCFG_FLAG)"
bench-rgl-clean:
rm -rf $(RGL_BENCH_DIR) $(RGL_BENCH_PRE_PMCFG_DIR)
test-pmcfg: test-pmcfg-core test-pmcfg-equivalence
test-pmcfg-core:
stack --work-dir $(PMCFG_TEST_CORE_STACK_WORK) test gf:pmcfg-tests --flag gf:pmcfg-test-hooks
test-pmcfg-equivalence:
stack --work-dir $(PMCFG_TEST_STACK_WORK) build
stack --work-dir $(PMCFG_TEST_PRE_STACK_WORK) build --flag gf:pre-pmcfg
rm -rf $(PMCFG_EQ_DIR)
mkdir -p $(PMCFG_EQ_DIR)
@set -e; \
i=0; \
for module in $(PMCFG_TEST_MODULES); do \
i=$$((i+1)); \
case_name=$$(basename "$$module" .gf); \
case_dir="$(PMCFG_EQ_DIR)/$$i-$$case_name"; \
new_gfo="$$case_dir/new-gfo"; \
new_pgf="$$case_dir/new-pgf"; \
pre_gfo="$$case_dir/pre-gfo"; \
pre_pgf="$$case_dir/pre-pgf"; \
mkdir -p "$$new_gfo" "$$new_pgf" "$$pre_gfo" "$$pre_pgf"; \
echo "PMCFG equivalence: $$module"; \
stack --work-dir $(PMCFG_TEST_STACK_WORK) exec gf -- $(PMCFG_TEST_GF_OPTIONS) --gfo-dir="$$new_gfo" --output-dir="$$new_pgf" --name=$(PMCFG_EQ_NAME) "$$module"; \
stack --work-dir $(PMCFG_TEST_PRE_STACK_WORK) exec gf -- $(PMCFG_TEST_GF_OPTIONS) --gfo-dir="$$pre_gfo" --output-dir="$$pre_pgf" --name=$(PMCFG_EQ_NAME) "$$module"; \
test -f "$$new_pgf/$(PMCFG_EQ_NAME).pgf"; \
test -f "$$pre_pgf/$(PMCFG_EQ_NAME).pgf"; \
cmp "$$new_pgf/$(PMCFG_EQ_NAME).pgf" "$$pre_pgf/$(PMCFG_EQ_NAME).pgf" || { echo "PMCFG output differs for $$module; artifacts kept in $$case_dir"; exit 1; }; \
done
test-pmcfg-rgl-equivalence:
@test -d "$(RGL_DIR)" || { echo "Missing RGL_DIR: $(RGL_DIR)"; exit 1; }
$(MAKE) test-pmcfg-equivalence PMCFG_TEST_MODULES="$(RGL_PMCFG_TEST_MODULES)" PMCFG_TEST_GF_OPTIONS="$(RGL_PMCFG_TEST_GF_OPTIONS)" PMCFG_EQ_DIR="$(PMCFG_TEST_DIR)/rgl-equivalence"
test-pmcfg-clean:
rm -rf $(PMCFG_TEST_DIR)
install:
ifeq ($(STACK),1)
stack install
else
cabal ${CMD_PFX}copy
cabal ${CMD_PFX}register
endif
doc:
${CMD} ${CMD_PFX}haddock
clean:
${CMD} ${CMD_PFX}clean
bash bin/clean_html
html::
bash bin/update_html
# Make a debian package. First add a suitable entry with the correct GF version
# number to the top of debian/changelog.
# (Tested on Ubuntu 15.04. You need to install dpkg-dev & debhelper.)
deb:
dpkg-buildpackage -b -uc -d
# Make a macOS installer package
pkg:
FMT=pkg bash bin/build-binary-dist.sh
# Make a binary tar distribution
bintar:
bash bin/build-binary-dist.sh
#sdist:
# cabal sdist
# Make a source tar.gz distribution using git to make sure that everything is included.
# We put the distribution in dist/ so it is removed on `make clean`
# sdist:
# test -d dist || mkdir dist
# git archive --format=tar.gz --output=dist/gf-${VERSION}.tar.gz HEAD
|