1
1
mirror of https://github.com/kanaka/mal.git synced 2024-11-14 00:09:01 +03:00
mal/impls/swift/Makefile
Joel Martin 8a19f60386 Move implementations into impls/ dir
- Reorder README to have implementation list after "learning tool"
  bullet.

- This also moves tests/ and libs/ into impls. It would be preferrable
  to have these directories at the top level.  However, this causes
  difficulties with the wasm implementations which need pre-open
  directories and have trouble with paths starting with "../../". So
  in lieu of that, symlink those directories to the top-level.

- Move the run_argv_test.sh script into the tests directory for
  general hygiene.
2020-02-10 23:50:16 -06:00

229 lines
7.9 KiB
Makefile

################################################################################
#
# Makefile for the Swift implementation of MAL.
#
# The MAL project consists of building up a dialect/subset of Clojure over a
# series of steps. Each step implements a new feature or concept in an easily
# understandable and approachable manner. Each step can be built on its own and
# tested. Each step is built from a step-specific "step.swift" file and a set
# of files common to all steps.
#
# The general approach in this file is to discover the set of "step" source
# files (step0_repl.swift, etc.), and build corresponding executable files
# (step0_repl, etc) from them and from the set of supporting Swift files.
# Since the set of "step" files is discovered on-the-fly, the rules to make
# those files are also generated on-the-fly using $(eval).
#
# The various "step0_repl.swift", etc., source files are actually generated
# from a file called "templates/step.swift". Since each "step" file
# incrementally builds towards the final, complete "step" file,
# "templates/step.swift" is -- for the most part -- a copy of this final "step"
# file with each line annotated with the step in which that line is introduced.
# Through the use of a simple filter program, the "templates/step.swift" file
# can then be processed to produce each intermediate "step" file. This Makefile
# takes care of performing that processing any time "templates/step.swift"
# changes.
#
# MAKE TARGETS:
#
# all:
# Make all step targets, (re)generating source files if needed.
# alls:
# (Re)generate source files, if needed.
# step0_repl, step1_read_print, etc.:
# Make the corresponding step target.
# s0...sN:
# Shortcuts for the previous targets.
# step0_repl.swift, step1_read_print.swift, etc.:
# (Re)generate source files for the corresponding step target, if
# needed.
# ss0...ssN:
# Shortcuts for the previous targets.
# clean:
# Delete all built executables. Generated source files are *not*
# deleted.
# dump:
# Print some Make variables for debugging.
#
# TODO:
# * Compile each .swift file into an intermediate .o file and link the .o
# files, rather than performing a complete build of all files any time
# any one of them is out-of-date. Here are the commands generated when
# using `swiftc -v`:
#
# /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift \
# -frontend \
# -c \
# -primary-file stepA_mal.swift \
# ./core.swift \
# ./env.swift \
# ./main.swift \
# ./printer.swift \
# ./reader.swift \
# ./readline.swift \
# ./types.swift \
# -target x86_64-apple-darwin14.1.0 \
# -target-cpu core2 \
# -sdk /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk \
# -import-objc-header ./bridging-header.h \
# -color-diagnostics \
# -Onone \
# -ledit \
# -module-name stepA_mal \
# -o /var/folders/dj/p3tx6v852sl88g79qvhhc2ch0000gp/T/stepA_mal-e0a836.o
# ... Similar for each source file...
# /usr/bin/ld \
# /var/folders/dj/p3tx6v852sl88g79qvhhc2ch0000gp/T/stepA_mal-e0a836.o \
# /var/folders/dj/p3tx6v852sl88g79qvhhc2ch0000gp/T/core-28b620.o \
# /var/folders/dj/p3tx6v852sl88g79qvhhc2ch0000gp/T/env-5d8422.o \
# /var/folders/dj/p3tx6v852sl88g79qvhhc2ch0000gp/T/main-e79633.o \
# /var/folders/dj/p3tx6v852sl88g79qvhhc2ch0000gp/T/printer-cdd3e5.o \
# /var/folders/dj/p3tx6v852sl88g79qvhhc2ch0000gp/T/reader-bb188a.o \
# /var/folders/dj/p3tx6v852sl88g79qvhhc2ch0000gp/T/readline-53df55.o \
# /var/folders/dj/p3tx6v852sl88g79qvhhc2ch0000gp/T/types-7cb250.o \
# -L /usr/lib \
# -ledit \
# -syslibroot \
# /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk \
# -lSystem \
# -arch x86_64 \
# -L /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx \
# -rpath /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx \
# -macosx_version_min 10.10.0 \
# -no_objc_category_merging \
# -o stepA_mal
#
# * Consider adding a clean-dist (or similar) that deletes the generated
# "step" source files.
#
################################################################################
#
# Discover the set of "step" source files (those having the form
# "step<#>_foo.swift")
#
SRCS := $(wildcard ./step*.swift)
#
# From the set of "step" source files, generate the set of executable files
# (those having the form "step<#>_foo")
#
EXES := $(patsubst %.swift,%,$(SRCS))
#
# Also generate references to any debug-symbol directories we may make when -g
# is specified.
#
DSYMS := $(patsubst %.swift,%.dSYM,$(SRCS))
#
# Given a name like "./step<#>_foo", return <#>.
#
# (Is there a better way to do this? $(patsubst) seems to be the most
# appropriate built-in command, but it doesn't seem powerful enough.)
#
# (I've included a `sed` version in case relying on bash is contraindicated.)
#
get_step_number = $(shell echo $(1) | sed -e "s/.*step\(.\).*/\1/")
#get_step_number = $(shell [[ $(1) =~ step(.)_.* ]] ; echo $${BASH_REMATCH[1]})
#
# Working from the list of discovered "step<#>_foo.swift" files, generate the
# list of step numbers.
#
get_all_step_numbers = $(foreach SRC,$(SRCS),$(call get_step_number,$(SRC)))
#
# Generate the dependencies for the "all" target. This list has the form
# "s0 s1 ... sN" for all N returned by get_all_step_numbers. That is:
#
# all: s0 s1 ... sN
#
# Also create an "alls" target that just regenerates all the "step" files from
# the corresponding template file.
#
$(eval all: $(patsubst %,s%,$(call get_all_step_numbers)))
$(eval alls: $(patsubst %,ss%,$(call get_all_step_numbers)))
#
# Generate the dependencies for the ".PHONY" target. That is:
#
# .PHONY: all clean dump s0 s1 ... sN
#
$(eval .PHONY: all clean dump $(patsubst %,s%,$(call get_all_step_numbers)))
#
# Define the "EZ" targets, where "s0" builds "step0_repl", "s1" builds
# "step1_read_print", etc. That is:
#
# s0: step0_repl
# s1: step1_read_print
# ...
# sN: stepN_foo
#
# Also create corresponding targets that rebuild the sources files:
#
# ss0: step0_repl.swift
# ss1: step1_read_print.swift
# ...
# ssN: stepN_foo.swift
#
$(foreach EXE,$(EXES),$(eval s$(call get_step_number,$(EXE)): $(EXE)))
$(foreach SRC,$(SRCS),$(eval ss$(call get_step_number,$(SRC)): $(SRC)))
#
# Various helpful variables.
#
DEV_DIR := $(firstword $(wildcard /Applications/Xcode-beta.app /Applications/Xcode.app))
SWIFT := $(shell DEVELOPER_DIR="$(DEV_DIR)" xcrun --find swiftc 2>/dev/null)
SDKROOT := $(shell DEVELOPER_DIR="$(DEV_DIR)" xcrun --show-sdk-path 2>/dev/null)
STEP_TEMPLATE := ./templates/step.swift
FILTER := ./templates/filter_steps.sh
UTIL_SRC := $(filter-out $(STEP_TEMPLATE) $(SRCS),$(wildcard ./*.swift))
ifndef TYPES
TYPES := CLASS
endif
ifeq ($(TYPES), ENUM)
UTIL_SRC := $(filter-out ./types_class.swift,$(UTIL_SRC))
else
UTIL_SRC := $(filter-out ./types_enum.swift,$(UTIL_SRC))
endif
OPT := -Ounchecked -whole-module-optimization
DEBUG := #-g
EXTRA := #-v
COMMON := $(UTIL_SRC) $(OPT) $(DEBUG) $(EXTRA) -import-objc-header ./bridging-header.h -L /usr/lib -ledit -sdk $(SDKROOT)
#
# Build the executable from the input sources consisting of the appropriate
# "step" file and the supporting files in $(UTIL_SRC).
#
$(EXES) : % : %.swift $(UTIL_SRC) ./Makefile
@echo "Making : $@"
@$(SWIFT) $< $(COMMON) -o $@
#
# Build the "step" source file ("step<#>_foo.swift") from the step template
# file that combines all the steps in one file.
#
$(SRCS) : % : $(STEP_TEMPLATE) ./Makefile
@echo "Generating: $@"
@$(FILTER) $(call get_step_number,$@) $< $@
#
# Delete all of the build output (other than generated "step" source files)
#
clean:
@rm -rf $(EXES) $(DSYMS)
#
# Display some variables for debugging.
#
dump:
@echo " SRCS = $(SRCS)"
@echo " EXES = $(EXES)"
@echo " DSYMS = $(DSYMS)"
@echo " UTIL = $(UTIL_SRC)"
@echo " SWIFT = $(SWIFT)"
@echo "SDKROOT = $(SDKROOT)"
@echo " STEPS = $(call get_all_step_numbers)"