-
Notifications
You must be signed in to change notification settings - Fork 160
/
Makefile
143 lines (126 loc) · 4.62 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
# See https://tech.davis-hansson.com/p/make
SHELL := bash
.ONESHELL:
.SHELLFLAGS := -eu -o pipefail -c
.DELETE_ON_ERROR:
.DEFAULT_GOAL := all
MAKEFLAGS += --warn-undefined-variables
MAKEFLAGS += --no-builtin-rules
ifndef VERBOSE
MAKEFLAGS += --silent
endif
ifeq ($(origin .RECIPEPREFIX), undefined)
$(error This Make does not support .RECIPEPREFIX. Please use GNU Make 4.0 or later)
endif
.RECIPEPREFIX = >
GIT := git
BUNX := bunx
CAST := cast
FORGE := forge
TESTS_DIR := tests
CONTRACTS_DIR := contracts
ARTIFACTS_DIR := artifacts
INTERFACES_FILE := $(TESTS_DIR)/interfaces/interfaces.txt
INTERFACES_DIR := $(TESTS_DIR)/interfaces/internal
INTERFACES_PRAGMA := >=0.6.0 <0.9.0
.PHONY: help
help: ## Describe useful make targets
> grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "%-30s %s\n", $$1, $$2}'
.PHONY: all
all: install build ## Run install & build (default)
.PHONY: install
install: ## Install all dependencies
> $(GIT) submodule update --init --recursive
.PHONY: build
build: artifacts interfaces ## Build all contract artifacts & interfaces
.PHONY: artifacts
artifacts: $(ARTIFACTS_DIR)/.sentinel ## Build all contract artifacts
.PHONY: interfaces
interfaces: $(INTERFACES_DIR)/.sentinel ## Generate interfaces for all contracts listed in interfaces.txt
.PHONY: test
test: ## Run the entire test suite
> $(FORGE) test
.PHONY: lint
lint: ## Check linting on all contract source files
> $(BUNX) solhint $(CONTRACTS_DIR)/**/*.sol $(TESTS_DIR)/**/*.sol
> $(FORGE) fmt --check $(CONTRACTS_DIR) $(TESTS_DIR)
.PHONY: format
format: ## Apply formatting to all contract source files
> $(FORGE) fmt $(CONTRACTS_DIR) $(TESTS_DIR)
.PHONY: clean
clean: ## Remove all untracked files and directories and bust any caches
> $(GIT) clean -dfX --exclude !**/.env* --exclude !**/deployments --exclude !**/cache
> $(FORGE) clean
$(ARTIFACTS_DIR)/.sentinel: $(shell find $(CONTRACTS_DIR) -type f -name "*.sol")
> mkdir -p $(@D)
> # Remove this once the `forge build` command supports a more capable version of the `--skip` option.
> export FOUNDRY_TEST=this-directory-does-not-exist
> $(FORGE) build --sizes --extra-output-files abi
> touch $@
$(INTERFACES_DIR)/.sentinel: $(INTERFACES_FILE) $(ARTIFACTS_DIR)/.sentinel
> mkdir -p $(@D)
>
> # Remove all existing interfaces and abis (from the immediate directory only).
> find $(INTERFACES_DIR) -maxdepth 1 -type f -name "*.sol" -delete
> find $(INTERFACES_DIR) -maxdepth 1 -type f -name "*.abi.json" -delete
>
> echo "Generating interfaces ..."
>
> # Read interfaces.txt line by line and use `cast interface` to generate the interfaces.
> while read -r line; do
> # Skip empty lines and lines starting with `#`.
> if [[ -z "$$line" || "$$line" == \#* ]]; then
> continue
> fi
>
> # The line format is `output: input`.
> output="$$(echo $$line | cut -d ':' -f1 | xargs)"
> input="$$(echo $$line | cut -d ':' -f2 | xargs)"
> if [[ -z "$$output" || -z "$$input" ]]; then
> echo "Invalid line format in $(INTERFACES_FILE) ($$line)"
> exit 1;
> fi
>
> # Extract the output name of the interface from the output path.
> name="$$(basename $$output | cut -d '.' -f1)"
> if [[ -z "$$name" ]]; then
> echo "Invalid output $$output in $(INTERFACES_FILE)"
> exit 1
> fi
>
> # Prepend the interfaces directory to the output path and check the file extension.
> output="$(INTERFACES_DIR)/$$output"
> if [[ ! "$$input" == *.abi.json ]]; then
> echo "Invalid extension for interface source $$input"
> exit 1
> fi
>
> # If the input is a path, use it directly. Otherwise, try to find the file in the artifacts directory.
> if echo "$$input" | grep -q "/"; then
> path="$$input"
> else
> path="$$(find $(ARTIFACTS_DIR) -type f -name $$input | head -n 1)"
> fi
>
> # Check if the source file was found. If not, try alternative files based on a pattern (e.g. `Dispatcher.*.abi.json` instead of `Dispatcher.abi.json`).
> if [[ -z "$$path" || ! -f "$$path" ]]; then
> alternative="$$(find $(ARTIFACTS_DIR) -type f -name "$$(basename $$input .abi.json).*.abi.json" | sort -Vr | head -n 1)"
> if [[ -z "$$alternative" || ! -f "$$alternative" ]]; then
> echo "Failed to locate source file for $$input"
> exit 1
> else
> path="$$alternative"
> fi
> fi
>
> # Create the parent directory.
> mkdir -p "$$(dirname $$output)"
>
> # Generate the interface using `cast interface`.
> $(CAST) interface "$$path" -o "$$output" -n "$$name" --pragma "$(INTERFACES_PRAGMA)" > /dev/null
>
> # Copy the abi file to the interfaces directory.
> cp "$$path" "$$(dirname $$output)/$$name.abi.json"
> done < "$(INTERFACES_FILE)"
>
> touch $@