8 @echo
'make "IMPL" # build all steps of IMPL'
9 @echo
'make "IMPL^STEP" # build STEP of IMPL'
11 @echo
'make "test" # test all implementations'
12 @echo
'make "test^IMPL" # test all steps of IMPL'
13 @echo
'make "test^STEP" # test STEP for all implementations'
14 @echo
'make "test^IMPL^STEP" # test STEP of IMPL'
16 @echo
'make "perf" # run microbenchmarks for all implementations'
17 @echo
'make "perf^IMPL" # run microbenchmarks for IMPL'
19 @echo
'make "repl^IMPL" # run stepA of IMPL'
20 @echo
'make "repl^IMPL^STEP" # test STEP of IMPL'
22 @echo
'make "clean" # run 'make
clean' for all implementations'
23 @echo
'make "clean^IMPL" # run 'make
clean' for IMPL'
25 @echo
'make "stats" # run 'make stats
' for all implementations'
26 @echo
'make "stats-lisp" # run 'make stats-lisp
' for all implementations'
27 @echo
'make "stats^IMPL" # run 'make stats
' for IMPL'
28 @echo
'make "stats-lisp^IMPL" # run 'make stats-lisp
' for IMPL'
30 @echo
'Options/Settings:'
32 @echo
'make MAL_IMPL=IMPL "test^mal..." # use IMPL for self-host tests'
33 @echo
'make REGRESS=1 "test..." # test with previous step tests too'
34 @echo
'make DOCKERIZE=1 ... # to dockerize above rules/targets'
35 @echo
'make TEST_OPTS="--opt ..." # options to pass to runtest.py'
39 @echo
'make "docker-build^IMPL" # build docker image for IMPL'
41 @echo
'make "docker-shell^IMPL" # start bash shell in docker image for IMPL'
45 # Command line settings
52 # clj or cljs (Clojure vs ClojureScript/lumo)
56 # python, js, cpp, or neko
60 # python, python2 or python3
62 # scheme (chibi, kawa, gauche, chicken, sagittarius, cyclone, foment)
64 # wasmtime js node wace_libc wace_fooboot
67 # Path to loccount for counting LOC stats
70 # Extra options to pass to runtest.py
73 # Test with previous test files not just the test files for the
74 # current step. Step 0 and 1 tests are special and not included in
81 # Run target/rule within docker image for the implementation
86 # Implementation specific settings
89 IMPLS
= ada ada
.2 awk bash basic c chuck clojure coffee common-lisp
cpp crystal cs d dart \
90 elisp elixir elm erlang es6 factor fantom forth fsharp go groovy gnu-smalltalk \
91 guile haskell haxe hy io java js julia kotlin livescript logo lua make mal \
92 matlab miniMAL nasm nim objc objpascal ocaml perl perl6 php picolisp plpgsql \
93 plsql powershell ps python r racket rexx rpython ruby rust scala scheme skew \
94 swift swift3 swift4 tcl ts vala vb vhdl vimscript wasm yorick
99 step1
= step1_read_print
102 step4
= step4_if_fn_do
110 argv_STEP
= step6_file
113 regress_step0
= step0
114 regress_step1
= step1
115 regress_step2
= step2
116 regress_step3
= $(regress_step2
) step3
117 regress_step4
= $(regress_step3
) step4
118 regress_step5
= $(regress_step4
) step5
119 regress_step6
= $(regress_step5
) step6
120 regress_step7
= $(regress_step6
) step7
121 regress_step8
= $(regress_step7
) step8
122 regress_step9
= $(regress_step8
) step9
123 regress_stepA
= $(regress_step9
) stepA
125 step5_EXCLUDES
+= bash
# never completes at 10,000
126 step5_EXCLUDES
+= basic
# too slow, and limited to ints of 2^16
127 step5_EXCLUDES
+= logo
# too slow for 10,000
128 step5_EXCLUDES
+= make
# no TCO capability (iteration or recursion)
129 step5_EXCLUDES
+= mal
# host impl dependent
130 step5_EXCLUDES
+= matlab
# never completes at 10,000
131 step5_EXCLUDES
+= plpgsql
# too slow for 10,000
132 step5_EXCLUDES
+= plsql
# too slow for 10,000
133 step5_EXCLUDES
+= powershell
# too slow for 10,000
134 step5_EXCLUDES
+= $(if
$(filter cpp,$(haxe_MODE
)),haxe
,) # cpp finishes 10,000, segfaults at 100,000
137 # TODO: still need to implement dist
138 dist_EXCLUDES
+= guile io julia matlab swift
141 # Extra options to pass to runtest.py
142 logo_TEST_OPTS
= --start-timeout
60 --test-timeout
120
143 mal_TEST_OPTS
= --start-timeout
60 --test-timeout
120
144 miniMAL_TEST_OPTS
= --start-timeout
60 --test-timeout
120
145 perl6_TEST_OPTS
= --test-timeout
=60
146 plpgsql_TEST_OPTS
= --start-timeout
60 --test-timeout
180
147 plsql_TEST_OPTS
= --start-timeout
120 --test-timeout
120
148 vimscript_TEST_OPTS
= --test-timeout
30
149 ifeq ($(MAL_IMPL
),vimscript
)
150 mal_TEST_OPTS
= --start-timeout
60 --test-timeout
180
151 else ifeq ($(MAL_IMPL
),powershell
)
152 mal_TEST_OPTS
= --start-timeout
60 --test-timeout
180
157 # Implementation specific utility functions
160 basic_STEP_TO_PROG_cbm
= basic
/$($(1)).bas
161 basic_STEP_TO_PROG_qbasic
= basic
/$($(1))
163 clojure_STEP_TO_PROG_clj
= clojure
/target
/$($(1)).jar
164 clojure_STEP_TO_PROG_cljs
= clojure
/src
/mal
/$($(1)).cljc
166 haxe_STEP_TO_PROG_neko
= haxe
/$($(1)).n
167 haxe_STEP_TO_PROG_python
= haxe
/$($(1)).py
168 haxe_STEP_TO_PROG_cpp
= haxe
/cpp/$($(1))
169 haxe_STEP_TO_PROG_js
= haxe
/$($(1)).js
171 scheme_STEP_TO_PROG_chibi
= scheme
/$($(1)).scm
172 scheme_STEP_TO_PROG_kawa
= scheme
/out
/$($(1)).class
173 scheme_STEP_TO_PROG_gauche
= scheme
/$($(1)).scm
174 scheme_STEP_TO_PROG_chicken
= scheme
/$($(1))
175 scheme_STEP_TO_PROG_sagittarius
= scheme
/$($(1)).scm
176 scheme_STEP_TO_PROG_cyclone
= scheme
/$($(1))
177 scheme_STEP_TO_PROG_foment
= scheme
/$($(1)).scm
179 # Map of step (e.g. "step8") to executable file for that step
180 ada_STEP_TO_PROG
= ada
/$($(1))
181 ada
.2_STEP_TO_PROG
= ada
.2/$($(1))
182 awk_STEP_TO_PROG
= awk
/$($(1)).awk
183 bash_STEP_TO_PROG
= bash
/$($(1)).sh
184 basic_STEP_TO_PROG
= $(basic_STEP_TO_PROG_
$(basic_MODE
))
185 c_STEP_TO_PROG
= c
/$($(1))
186 chuck_STEP_TO_PROG
= chuck
/$($(1)).ck
187 clojure_STEP_TO_PROG
= $(clojure_STEP_TO_PROG_
$(clojure_MODE
))
188 coffee_STEP_TO_PROG
= coffee
/$($(1)).coffee
189 common-lisp_STEP_TO_PROG
= common-lisp
/$($(1))
190 cpp_STEP_TO_PROG
= cpp/$($(1))
191 crystal_STEP_TO_PROG
= crystal
/$($(1))
192 cs_STEP_TO_PROG
= cs
/$($(1)).exe
193 d_STEP_TO_PROG
= d
/$($(1))
194 dart_STEP_TO_PROG
= dart
/$($(1)).dart
195 elisp_STEP_TO_PROG
= elisp
/$($(1)).el
196 elixir_STEP_TO_PROG
= elixir
/lib
/mix
/tasks
/$($(1)).ex
197 elm_STEP_TO_PROG
= elm
/$($(1)).js
198 erlang_STEP_TO_PROG
= erlang
/$($(1))
199 es6_STEP_TO_PROG
= es6
/$($(1)).mjs
200 factor_STEP_TO_PROG
= factor
/$($(1))/$($(1)).factor
201 fantom_STEP_TO_PROG
= fantom
/lib
/fan
/$($(1)).pod
202 forth_STEP_TO_PROG
= forth
/$($(1)).fs
203 fsharp_STEP_TO_PROG
= fsharp
/$($(1)).exe
204 go_STEP_TO_PROG
= go
/$($(1))
205 groovy_STEP_TO_PROG
= groovy
/$($(1)).groovy
206 gnu-smalltalk_STEP_TO_PROG
= gnu-smalltalk
/$($(1)).st
207 guile_STEP_TO_PROG
= guile
/$($(1)).scm
208 haskell_STEP_TO_PROG
= haskell
/$($(1))
209 haxe_STEP_TO_PROG
= $(haxe_STEP_TO_PROG_
$(haxe_MODE
))
210 hy_STEP_TO_PROG
= hy
/$($(1)).hy
211 io_STEP_TO_PROG
= io
/$($(1)).io
212 java_STEP_TO_PROG
= java
/target
/classes
/mal
/$($(1)).class
213 js_STEP_TO_PROG
= js
/$($(1)).js
214 julia_STEP_TO_PROG
= julia
/$($(1)).jl
215 kotlin_STEP_TO_PROG
= kotlin
/$($(1)).jar
216 livescript_STEP_TO_PROG
= livescript
/$($(1)).js
217 logo_STEP_TO_PROG
= logo
/$($(1)).lg
218 lua_STEP_TO_PROG
= lua
/$($(1)).lua
219 make_STEP_TO_PROG
= make
/$($(1)).mk
220 mal_STEP_TO_PROG
= mal
/$($(1)).mal
221 matlab_STEP_TO_PROG
= matlab
/$($(1)).m
222 miniMAL_STEP_TO_PROG
= miniMAL
/$($(1)).json
223 nasm_STEP_TO_PROG
= nasm
/$($(1))
224 nim_STEP_TO_PROG
= nim
/$($(1))
225 objc_STEP_TO_PROG
= objc
/$($(1))
226 objpascal_STEP_TO_PROG
= objpascal
/$($(1))
227 ocaml_STEP_TO_PROG
= ocaml
/$($(1))
228 perl_STEP_TO_PROG
= perl
/$($(1)).pl
229 perl6_STEP_TO_PROG
= perl6
/$($(1)).pl
230 php_STEP_TO_PROG
= php
/$($(1)).php
231 picolisp_STEP_TO_PROG
= picolisp
/$($(1)).l
232 plpgsql_STEP_TO_PROG
= plpgsql
/$($(1)).sql
233 plsql_STEP_TO_PROG
= plsql
/$($(1)).sql
234 powershell_STEP_TO_PROG
= powershell
/$($(1)).ps1
235 ps_STEP_TO_PROG
= ps
/$($(1)).ps
236 python_STEP_TO_PROG
= python
/$($(1)).py
237 r_STEP_TO_PROG
= r
/$($(1)).r
238 racket_STEP_TO_PROG
= racket
/$($(1)).rkt
239 rexx_STEP_TO_PROG
= rexx
/$($(1)).rexxpp
240 rpython_STEP_TO_PROG
= rpython
/$($(1))
241 ruby_STEP_TO_PROG
= ruby
/$($(1)).rb
242 rust_STEP_TO_PROG
= rust
/$($(1))
243 scala_STEP_TO_PROG
= scala
/target
/scala-2.11
/classes
/$($(1)).class
244 scheme_STEP_TO_PROG
= $(scheme_STEP_TO_PROG_
$(scheme_MODE
))
245 skew_STEP_TO_PROG
= skew
/$($(1)).js
246 swift_STEP_TO_PROG
= swift
/$($(1))
247 swift3_STEP_TO_PROG
= swift3
/$($(1))
248 swift4_STEP_TO_PROG
= swift4
/$($(1))
249 tcl_STEP_TO_PROG
= tcl
/$($(1)).tcl
250 ts_STEP_TO_PROG
= ts
/$($(1)).js
251 vala_STEP_TO_PROG
= vala
/$($(1))
252 vb_STEP_TO_PROG
= vb
/$($(1)).exe
253 vhdl_STEP_TO_PROG
= vhdl
/$($(1))
254 vimscript_STEP_TO_PROG
= vimscript
/$($(1)).vim
255 wasm_STEP_TO_PROG
= wasm
/$($(1)).wasm
256 yorick_STEP_TO_PROG
= yorick
/$($(1)).i
260 # General settings and utility functions
263 # Needed some argument munging
266 SPACE
= $(noop
) $(noop
)
267 export FACTOR_ROOTS
:= .
269 opt_DEFERRABLE
= $(if
$(strip $(DEFERRABLE
)),$(if
$(filter t true T True TRUE
1 y yes Yes YES
,$(DEFERRABLE
)),--deferrable
,--no-deferrable
),--no-deferrable
)
270 opt_OPTIONAL
= $(if
$(strip $(OPTIONAL
)),$(if
$(filter t true T True TRUE
1 y yes Yes YES
,$(OPTIONAL
)),--optional
,--no-optional
),--no-optional
)
272 # Return list of test files for a given step. If REGRESS is set then
273 # test files will include step 2 tests through tests for the step
275 STEP_TEST_FILES
= $(strip $(wildcard \
276 $(foreach s
,$(if
$(strip $(REGRESS
)),\
277 $(filter-out $(if
$(filter $(1),$(step5_EXCLUDES
)),step5
,),\
280 $(1)/tests
/$($(s
))$(EXTENSION
) tests
/$($(s
))$(EXTENSION
))))
282 # DOCKERIZE utility functions
283 lc
= $(subst A
,a
,$(subst B
,b
,$(subst C
,c
,$(subst D
,d
,$(subst E
,e
,$(subst F
,f
,$(subst G
,g
,$(subst H
,h
,$(subst I
,i
,$(subst J
,j
,$(subst K
,k
,$(subst L
,l
,$(subst M
,m
,$(subst N
,n
,$(subst O
,o
,$(subst P
,p
,$(subst Q
,q
,$(subst R
,r
,$(subst S
,s
,$(subst T
,t
,$(subst U
,u
,$(subst V
,v
,$(subst W
,w
,$(subst X
,x
,$(subst Y
,y
,$(subst Z
,z
,$1))))))))))))))))))))))))))
284 impl_to_image
= kanaka
/mal-test-
$(call lc
,$(1))
286 actual_impl
= $(if
$(filter mal
,$(1)),$(MAL_IMPL
),$(1))
289 # Returns nothing if DOCKERIZE is not set, otherwise returns the
290 # docker prefix necessary to run make within the docker environment
292 get_build_command
= $(strip $(if
$(strip $(DOCKERIZE
)),\
294 -it
--rm -u
$(shell id
-u
) \
295 -v
$(dir $(abspath
$(lastword
$(MAKEFILE_LIST
)))):/mal \
297 $(if
$(strip $($(1)_MODE
)),-e
$(1)_MODE
=$($(1)_MODE
),) \
298 $(if
$(filter factor
,$(1)),-e FACTOR_ROOTS
=$(FACTOR_ROOTS
),) \
299 $(call impl_to_image
,$(1)) \
300 $(MAKE
) $(if
$(strip $($(1)_MODE
)),$(1)_MODE
=$($(1)_MODE
),) \
302 $(MAKE
) $(if
$(strip $($(1)_MODE
)),$(1)_MODE
=$($(1)_MODE
),)))
304 # Takes impl and step args. Optional env vars and dockerize args
305 # Returns a command prefix (docker command and environment variables)
306 # necessary to launch the given impl and step
307 get_run_prefix
= $(strip $(if
$(strip $(DOCKERIZE
) $(4)),\
308 docker run
-e STEP
=$($2) -e MAL_IMPL
=$(MAL_IMPL
) \
309 -it
--rm -u
$(shell id
-u
) \
310 -v
$(dir $(abspath
$(lastword
$(MAKEFILE_LIST
)))):/mal \
311 -w
/mal
/$(call actual_impl
,$(1)) \
312 $(if
$(strip $($(1)_MODE
)),-e
$(1)_MODE
=$($(1)_MODE
),) \
313 $(if
$(filter factor
,$(1)),-e FACTOR_ROOTS
=$(FACTOR_ROOTS
),) \
314 $(foreach env
,$(3),-e
$(env
)) \
315 $(call impl_to_image
,$(call actual_impl
,$(1))) \
317 env STEP
=$($2) MAL_IMPL
=$(MAL_IMPL
) \
318 $(if
$(strip $($(1)_MODE
)),$(1)_MODE
=$($(1)_MODE
),) \
319 $(if
$(filter factor
,$(1)),FACTOR_ROOTS
=$(FACTOR_ROOTS
),) \
322 # Takes impl and step
323 # Returns the runtest command prefix (with runtest options) for testing the given step
324 get_runtest_cmd
= $(call get_run_prefix
,$(1),$(2),$(if
$(filter cs fsharp tcl vb
,$(1)),RAW
=1,)) \
325 ..
/runtest.py
$(opt_DEFERRABLE
) $(opt_OPTIONAL
) $(call
$(1)_TEST_OPTS
) $(TEST_OPTS
)
327 # Takes impl and step
328 # Returns the runtest command prefix (with runtest options) for testing the given step
329 get_argvtest_cmd
= $(call get_run_prefix
,$(1),$(2)) ..
/run_argv_test.sh
332 STEPS
= $(sort $(filter-out %_EXCLUDES
,$(filter step
%,$(.VARIABLES
))))
333 DO_IMPLS
= $(filter-out $(SKIP_IMPLS
),$(IMPLS
))
334 IMPL_TESTS
= $(foreach impl
,$(DO_IMPLS
),test^
$(impl
))
335 STEP_TESTS
= $(foreach step
,$(STEPS
),test^
$(step
))
336 ALL_TESTS
= $(filter-out $(foreach e
,$(step5_EXCLUDES
),test^
$(e
)^step5
),\
338 $(foreach impl
,$(DO_IMPLS
),\
339 $(foreach step
,$(STEPS
),test^
$(impl
)^
$(step
))))))
341 DOCKER_BUILD
= $(foreach impl
,$(DO_IMPLS
),docker-build^
$(impl
))
343 DOCKER_SHELL
= $(foreach impl
,$(DO_IMPLS
),docker-shell^
$(impl
))
345 IMPL_PERF
= $(foreach impl
,$(filter-out $(perf_EXCLUDES
),$(DO_IMPLS
)),perf^
$(impl
))
347 IMPL_STATS
= $(foreach impl
,$(DO_IMPLS
),stats^
$(impl
))
349 IMPL_REPL
= $(foreach impl
,$(DO_IMPLS
),repl^
$(impl
))
350 ALL_REPL
= $(strip $(sort \
351 $(foreach impl
,$(DO_IMPLS
),\
352 $(foreach step
,$(STEPS
),repl^
$(impl
)^
$(step
)))))
359 # Enable secondary expansion for all rules
362 # Build a program in an implementation directory
363 # Make sure we always try and build first because the dependencies are
364 # encoded in the implementation Makefile not here
365 .PHONY
: $(foreach i
,$(DO_IMPLS
),$(foreach s
,$(STEPS
),$(call
$(i
)_STEP_TO_PROG
,$(s
))))
366 $(foreach i
,$(DO_IMPLS
),$(foreach s
,$(STEPS
),$(call
$(i
)_STEP_TO_PROG
,$(s
)))):
367 $(foreach impl
,$(word 1,$(subst /, ,$(@
))),\
369 $(call get_build_command
,$(impl
)) $(patsubst $(impl
)/%,%,$(@
)), \
370 $(call get_build_command
,$(impl
)) -C
$(impl
) $(subst $(impl
)/,,$(@
))))
372 # Allow IMPL, and IMPL^STEP
373 $(DO_IMPLS
): $$(foreach s
,$$(STEPS
),$$(call
$$(@
)_STEP_TO_PROG
,$$(s
)))
375 $(foreach i
,$(DO_IMPLS
),$(foreach s
,$(STEPS
),$(i
)^
$(s
))): $$(call
$$(word 1,$$(subst ^
, ,$$(@
)))_STEP_TO_PROG
,$$(word 2,$$(subst ^
, ,$$(@
))))
382 $(ALL_TESTS
): $$(call
$$(word 2,$$(subst ^
, ,$$(@
)))_STEP_TO_PROG
,$$(word 3,$$(subst ^
, ,$$(@
))))
383 @
$(foreach impl
,$(word 2,$(subst ^
, ,$(@
))),\
384 $(foreach step
,$(word 3,$(subst ^
, ,$(@
))),\
385 cd
$(if
$(filter mal
,$(impl
)),$(MAL_IMPL
),$(impl
)) && \
386 $(foreach test,$(call STEP_TEST_FILES
,$(impl
),$(step
)),\
387 echo
'----------------------------------------------' && \
388 echo
'Testing $@; step file: $+, test file: $(test)' && \
389 echo
'Running: $(call get_runtest_cmd,$(impl),$(step)) ../$(test) -- ../$(impl)/run' && \
390 $(call get_runtest_cmd
,$(impl
),$(step
)) ..
/$(test) -- ..
/$(impl
)/run
&& \
391 $(if
$(filter tests
/$(argv_STEP
)$(EXTENSION
),$(test)),\
392 echo
'----------------------------------------------' && \
393 echo
'Testing ARGV of $@; step file: $+' && \
394 echo
'Running: $(call get_argvtest_cmd,$(impl),$(step)) ../$(impl)/run ' && \
395 $(call get_argvtest_cmd
,$(impl
),$(step
)) ..
/$(impl
)/run
&& ,\
399 # Allow test, tests, test^STEP, test^IMPL, and test^IMPL^STEP
403 $(IMPL_TESTS
): $$(filter $$@^
%,$$(ALL_TESTS
))
405 $(STEP_TESTS
): $$(foreach step
,$$(subst test^
,,$$@
),$$(filter %^
$$(step
),$$(ALL_TESTS
)))
412 docker-build
: $(DOCKER_BUILD
)
415 @echo
"----------------------------------------------"; \
416 $(foreach impl
,$(word 2,$(subst ^
, ,$(@
))),\
417 echo
"Running: docker build -t $(call impl_to_image,$(impl)) .:"; \
418 cd
$(impl
) && docker build
-t
$(call impl_to_image
,$(impl
)) .
)
425 @echo
"----------------------------------------------"; \
426 $(foreach impl
,$(word 2,$(subst ^
, ,$(@
))),\
427 echo
"Running: $(call get_run_prefix,$(impl),stepA,,dockerize) bash"; \
428 $(call get_run_prefix
,$(impl
),stepA
,,dockerize
) bash
)
432 # Performance test rules
438 @echo
"----------------------------------------------"; \
439 $(foreach impl
,$(word 2,$(subst ^
, ,$(@
))),\
440 cd
$(if
$(filter mal
,$(impl
)),$(MAL_IMPL
),$(impl
)); \
441 echo
"Performance test for $(impl):"; \
442 echo
'Running: $(call get_run_prefix,$(impl),stepA) ../$(impl)/run ../tests/perf1.mal'; \
443 $(call get_run_prefix
,$(impl
),stepA
) ..
/$(impl
)/run ..
/tests
/perf1.mal
; \
444 echo
'Running: $(call get_run_prefix,$(impl),stepA) ../$(impl)/run ../tests/perf2.mal'; \
445 $(call get_run_prefix
,$(impl
),stepA
) ..
/$(impl
)/run ..
/tests
/perf2.mal
; \
446 echo
'Running: $(call get_run_prefix,$(impl),stepA) ../$(impl)/run ../tests/perf3.mal'; \
447 $(call get_run_prefix
,$(impl
),stepA
) ..
/$(impl
)/run ..
/tests
/perf3.mal
)
451 # REPL invocation rules
454 $(ALL_REPL
): $$(call
$$(word 2,$$(subst ^
, ,$$(@
)))_STEP_TO_PROG
,$$(word 3,$$(subst ^
, ,$$(@
))))
455 @
$(foreach impl
,$(word 2,$(subst ^
, ,$(@
))),\
456 $(foreach step
,$(word 3,$(subst ^
, ,$(@
))),\
457 cd
$(if
$(filter mal
,$(impl
)),$(MAL_IMPL
),$(impl
)); \
458 echo
'REPL implementation $(impl), step file: $+'; \
459 echo
'Running: $(call get_run_prefix,$(impl),$(step)) ../$(impl)/run $(RUN_ARGS)'; \
460 $(call get_run_prefix
,$(impl
),$(step
)) ..
/$(impl
)/run
$(RUN_ARGS
);))
462 # Allow repl^IMPL^STEP and repl^IMPL (which starts REPL of stepA)
463 $(IMPL_REPL
): $$@^stepA
469 # For a concise summary:
470 # make stats | egrep -A1 "^Stats for|^all" | egrep -v "^all|^--"
474 @
$(foreach impl
,$(word 2,$(subst ^
, ,$(@
))),\
475 echo
"Stats for $(impl):"; \
476 $(LOCCOUNT
) -x
"Makefile|node_modules" $(impl
))
485 # Recursive rules (call make FOO in each subdirectory)
488 define recur_template
492 @echo
"----------------------------------------------"; \
493 $$(foreach impl
,$$(word 2,$$(subst ^
, ,$$(@
))),\
494 $$(if
$$(DOCKERIZE
), \
495 echo
"Running: $$(call get_build_command,$$(impl)) --no-print-directory $(1)"; \
496 $$(call get_build_command
,$$(impl
)) --no-print-directory
$(1), \
497 echo
"Running: $$(call get_build_command,$$(impl)) --no-print-directory -C $$(impl) $(1)"; \
498 $$(call get_build_command
,$$(impl
)) --no-print-directory
-C
$$(impl
) $(1)))
501 recur_impls_
= $(filter-out $(foreach impl
,$($(1)_EXCLUDES
),$(1)^
$(impl
)),$(foreach impl
,$(IMPLS
),$(1)^
$(impl
)))
504 $(eval
$(call recur_template
,clean,$(call recur_impls_
,clean)))
507 $(eval
$(call recur_template
,dist,$(call recur_impls_
,dist)))