github.com/bananabytelabs/wazero@v0.0.0-20240105073314-54b22a776da8/Makefile (about) 1 2 gofumpt := mvdan.cc/gofumpt@v0.5.0 3 gosimports := github.com/rinchsan/gosimports/cmd/gosimports@v0.3.8 4 golangci_lint := github.com/golangci/golangci-lint/cmd/golangci-lint@v1.55.2 5 asmfmt := github.com/klauspost/asmfmt/cmd/asmfmt@v1.3.2 6 # sync this with netlify.toml! 7 hugo := github.com/gohugoio/hugo@v0.115.2 8 9 # Make 3.81 doesn't support '**' globbing: Set explicitly instead of recursion. 10 all_sources := $(wildcard *.go */*.go */*/*.go */*/*/*.go */*/*/*.go */*/*/*/*.go) 11 all_testdata := $(wildcard testdata/* */testdata/* */*/testdata/* */*/testdata/*/* */*/*/testdata/*) 12 all_testing := $(wildcard internal/testing/* internal/testing/*/* internal/testing/*/*/*) 13 all_examples := $(wildcard examples/* examples/*/* examples/*/*/* */*/example/* */*/example/*/* */*/example/*/*/*) 14 all_it := $(wildcard internal/integration_test/* internal/integration_test/*/* internal/integration_test/*/*/*) 15 # main_sources exclude any test or example related code 16 main_sources := $(wildcard $(filter-out %_test.go $(all_testdata) $(all_testing) $(all_examples) $(all_it), $(all_sources))) 17 # main_packages collect the unique main source directories (sort will dedupe). 18 # Paths need to all start with ./, so we do that manually vs foreach which strips it. 19 main_packages := $(sort $(foreach f,$(dir $(main_sources)),$(if $(findstring ./,$(f)),./,./$(f)))) 20 21 go_test_options ?= -timeout 300s 22 23 ensureCompilerFastest := -ldflags '-X github.com/bananabytelabs/wazero/internal/integration_test/vs.ensureCompilerFastest=true' 24 .PHONY: bench 25 bench: 26 @go test -run=NONE -benchmem -bench=. ./internal/engine/compiler/... 27 @go build ./internal/integration_test/bench/... 28 @# Don't use -test.benchmem as it isn't accurate when comparing against CGO libs 29 @for d in vs/time vs/wasmedge vs/wasmtime ; do \ 30 cd ./internal/integration_test/$$d ; \ 31 go test -bench=. . -tags='wasmedge' $(ensureCompilerFastest) ; \ 32 cd - ;\ 33 done 34 35 bench_testdata_dir := internal/integration_test/bench/testdata 36 .PHONY: build.bench 37 build.bench: 38 @tinygo build -o $(bench_testdata_dir)/case.wasm -scheduler=none --no-debug -target=wasi $(bench_testdata_dir)/case.go 39 40 .PHONY: test.examples 41 test.examples: 42 @go test $(go_test_options) ./examples/... ./imports/assemblyscript/example/... ./imports/emscripten/... ./experimental/gojs/example/... ./imports/wasi_snapshot_preview1/example/... 43 44 .PHONY: build.examples.as 45 build.examples.as: 46 @cd ./imports/assemblyscript/example/testdata && npm install && npm run build 47 48 %.wasm: %.zig 49 @(cd $(@D); zig build -Doptimize=ReleaseSmall) 50 @mv $(@D)/zig-out/*/$(@F) $(@D) 51 52 .PHONY: build.examples.zig 53 build.examples.zig: examples/allocation/zig/testdata/greet.wasm imports/wasi_snapshot_preview1/example/testdata/zig/cat.wasm imports/wasi_snapshot_preview1/testdata/zig/wasi.wasm 54 @cd internal/testing/dwarftestdata/testdata/zig; zig build; mv zig-out/*/main.wasm ./ # Need DWARF custom sections. 55 56 tinygo_sources := examples/basic/testdata/add.go examples/allocation/tinygo/testdata/greet.go examples/cli/testdata/cli.go imports/wasi_snapshot_preview1/example/testdata/tinygo/cat.go imports/wasi_snapshot_preview1/testdata/tinygo/wasi.go 57 .PHONY: build.examples.tinygo 58 build.examples.tinygo: $(tinygo_sources) 59 @for f in $^; do \ 60 tinygo build -o $$(echo $$f | sed -e 's/\.go/\.wasm/') -scheduler=none --no-debug --target=wasi $$f; \ 61 done 62 63 # We use zig to build C as it is easy to install and embeds a copy of zig-cc. 64 # Note: Don't use "-Oz" as that breaks our wasi sock example. 65 c_sources := imports/wasi_snapshot_preview1/example/testdata/zig-cc/cat.c imports/wasi_snapshot_preview1/testdata/zig-cc/wasi.c internal/testing/dwarftestdata/testdata/zig-cc/main.c 66 .PHONY: build.examples.zig-cc 67 build.examples.zig-cc: $(c_sources) 68 @for f in $^; do \ 69 zig cc --target=wasm32-wasi -o $$(echo $$f | sed -e 's/\.c/\.wasm/') $$f; \ 70 done 71 72 # Here are the emcc args we use: 73 # 74 # * `-Oz` - most optimization for code size. 75 # * `--profiling` - adds the name section. 76 # * `-s STANDALONE_WASM` - ensures wasm is built for a non-js runtime. 77 # * `-s EXPORTED_FUNCTIONS=_malloc,_free` - export allocation functions so that 78 # they can be used externally as "malloc" and "free". 79 # * `-s WARN_ON_UNDEFINED_SYMBOLS=0` - imports not defined in JavaScript error 80 # otherwise. See https://github.com/emscripten-core/emscripten/issues/13641 81 # * `-s TOTAL_STACK=8KB -s TOTAL_MEMORY=64KB` - reduce memory default from 16MB 82 # to one page (64KB). To do this, we have to reduce the stack size. 83 # * `-s ALLOW_MEMORY_GROWTH` - allows "memory.grow" instructions to succeed, but 84 # requires a function import "emscripten_notify_memory_growth". 85 emscripten_sources := $(wildcard imports/emscripten/testdata/*.cc) 86 .PHONY: build.examples.emscripten 87 build.examples.emscripten: $(emscripten_sources) 88 @for f in $^; do \ 89 em++ -Oz --profiling \ 90 -s STANDALONE_WASM \ 91 -s EXPORTED_FUNCTIONS=_malloc,_free \ 92 -s WARN_ON_UNDEFINED_SYMBOLS=0 \ 93 -s TOTAL_STACK=8KB -s TOTAL_MEMORY=64KB \ 94 -s ALLOW_MEMORY_GROWTH \ 95 --std=c++17 -o $$(echo $$f | sed -e 's/\.cc/\.wasm/') $$f; \ 96 done 97 98 %/greet.wasm : cargo_target := wasm32-unknown-unknown 99 %/cat.wasm : cargo_target := wasm32-wasi 100 %/wasi.wasm : cargo_target := wasm32-wasi 101 102 .PHONY: build.examples.rust 103 build.examples.rust: examples/allocation/rust/testdata/greet.wasm imports/wasi_snapshot_preview1/example/testdata/cargo-wasi/cat.wasm imports/wasi_snapshot_preview1/testdata/cargo-wasi/wasi.wasm internal/testing/dwarftestdata/testdata/rust/main.wasm.xz 104 105 # Normally, we build release because it is smaller. Testing dwarf requires the debug build. 106 internal/testing/dwarftestdata/testdata/rust/main.wasm.xz: 107 cd $(@D) && cargo wasi build 108 mv $(@D)/target/wasm32-wasi/debug/main.wasm $(@D) 109 cd $(@D) && xz -k -f ./main.wasm # Rust's DWARF section is huge, so compress it. 110 111 # Builds rust using cargo normally, or cargo-wasi. 112 %.wasm: %.rs 113 @(cd $(@D); cargo $(if $(findstring wasi,$(cargo_target)),wasi build,build --target $(cargo_target)) --release) 114 @mv $(@D)/target/$(cargo_target)/release/$(@F) $(@D) 115 116 spectest_base_dir := internal/integration_test/spectest 117 spectest_v1_dir := $(spectest_base_dir)/v1 118 spectest_v1_testdata_dir := $(spectest_v1_dir)/testdata 119 spec_version_v1 := wg-1.0 120 spectest_v2_dir := $(spectest_base_dir)/v2 121 spectest_v2_testdata_dir := $(spectest_v2_dir)/testdata 122 # Latest draft state as of May 23, 2023. 123 spec_version_v2 := 2e8912e88a3118a46b90e8ccb659e24b4e8f3c23 124 spectest_threads_dir := $(spectest_base_dir)/threads 125 spectest_threads_testdata_dir := $(spectest_threads_dir)/testdata 126 # From https://github.com/WebAssembly/threads/tree/upstream-rebuild which has not been merged to main yet. 127 # It will likely be renamed to main in the future - https://github.com/WebAssembly/threads/issues/216. 128 spec_version_threads := 3635ca51a17e57e106988846c5b0e0cc48ac04fc 129 130 .PHONY: build.spectest 131 build.spectest: 132 @$(MAKE) build.spectest.v1 133 @$(MAKE) build.spectest.v2 134 135 .PHONY: build.spectest.v1 136 build.spectest.v1: # Note: wabt by default uses >1.0 features, so wast2json flags might drift as they include more. See WebAssembly/wabt#1878 137 @rm -rf $(spectest_v1_testdata_dir) 138 @mkdir -p $(spectest_v1_testdata_dir) 139 @cd $(spectest_v1_testdata_dir) \ 140 && curl -sSL 'https://api.github.com/repos/WebAssembly/spec/contents/test/core?ref=$(spec_version_v1)' | jq -r '.[]| .download_url' | grep -E ".wast" | xargs -Iurl curl -sJL url -O 141 @cd $(spectest_v1_testdata_dir) && for f in `find . -name '*.wast'`; do \ 142 perl -pi -e 's/\(assert_return_canonical_nan\s(\(invoke\s"f32.demote_f64"\s\((f[0-9]{2})\.const\s[a-z0-9.+:-]+\)\))\)/\(assert_return $$1 \(f32.const nan:canonical\)\)/g' $$f; \ 143 perl -pi -e 's/\(assert_return_arithmetic_nan\s(\(invoke\s"f32.demote_f64"\s\((f[0-9]{2})\.const\s[a-z0-9.+:-]+\)\))\)/\(assert_return $$1 \(f32.const nan:arithmetic\)\)/g' $$f; \ 144 perl -pi -e 's/\(assert_return_canonical_nan\s(\(invoke\s"f64\.promote_f32"\s\((f[0-9]{2})\.const\s[a-z0-9.+:-]+\)\))\)/\(assert_return $$1 \(f64.const nan:canonical\)\)/g' $$f; \ 145 perl -pi -e 's/\(assert_return_arithmetic_nan\s(\(invoke\s"f64\.promote_f32"\s\((f[0-9]{2})\.const\s[a-z0-9.+:-]+\)\))\)/\(assert_return $$1 \(f64.const nan:arithmetic\)\)/g' $$f; \ 146 perl -pi -e 's/\(assert_return_canonical_nan\s(\(invoke\s"[a-z._0-9]+"\s\((f[0-9]{2})\.const\s[a-z0-9.+:-]+\)\))\)/\(assert_return $$1 \($$2.const nan:canonical\)\)/g' $$f; \ 147 perl -pi -e 's/\(assert_return_arithmetic_nan\s(\(invoke\s"[a-z._0-9]+"\s\((f[0-9]{2})\.const\s[a-z0-9.+:-]+\)\))\)/\(assert_return $$1 \($$2.const nan:arithmetic\)\)/g' $$f; \ 148 perl -pi -e 's/\(assert_return_canonical_nan\s(\(invoke\s"[a-z._0-9]+"\s\((f[0-9]{2})\.const\s[a-z0-9.+:-]+\)\s\([a-z0-9.\s+-:]+\)\))\)/\(assert_return $$1 \($$2.const nan:canonical\)\)/g' $$f; \ 149 perl -pi -e 's/\(assert_return_arithmetic_nan\s(\(invoke\s"[a-z._0-9]+"\s\((f[0-9]{2})\.const\s[a-z0-9.+:-]+\)\s\([a-z0-9.\s+-:]+\)\))\)/\(assert_return $$1 \($$2.const nan:arithmetic\)\)/g' $$f; \ 150 perl -pi -e 's/\(assert_return_canonical_nan\s(\(invoke\s"[a-z._0-9]+"\s\((f[0-9]{2})\.const\s[a-z0-9.+:-]+\)\))\)/\(assert_return $$1 \($$2.const nan:canonical\)\)/g' $$f; \ 151 perl -pi -e 's/\(assert_return_arithmetic_nan\s(\(invoke\s"[a-z._0-9]+"\s\((f[0-9]{2})\.const\s[a-z0-9.+:-]+\)\))\)/\(assert_return $$1 \($$2.const nan:arithmetic\)\)/g' $$f; \ 152 wast2json \ 153 --disable-saturating-float-to-int \ 154 --disable-sign-extension \ 155 --disable-simd \ 156 --disable-multi-value \ 157 --disable-bulk-memory \ 158 --disable-reference-types \ 159 --debug-names $$f; \ 160 done 161 162 .PHONY: build.spectest.v2 163 build.spectest.v2: # Note: SIMD cases are placed in the "simd" subdirectory. 164 @mkdir -p $(spectest_v2_testdata_dir) 165 @cd $(spectest_v2_testdata_dir) \ 166 && curl -sSL 'https://api.github.com/repos/WebAssembly/spec/contents/test/core?ref=$(spec_version_v2)' | jq -r '.[]| .download_url' | grep -E ".wast" | xargs -Iurl curl -sJL url -O 167 @cd $(spectest_v2_testdata_dir) \ 168 && curl -sSL 'https://api.github.com/repos/WebAssembly/spec/contents/test/core/simd?ref=$(spec_version_v2)' | jq -r '.[]| .download_url' | grep -E ".wast" | xargs -Iurl curl -sJL url -O 169 @cd $(spectest_v2_testdata_dir) && for f in `find . -name '*.wast'`; do \ 170 wast2json --debug-names --no-check $$f; \ 171 done 172 173 # Note: We currently cannot build the "threads" subdirectory that spawns threads due to missing support in wast2json. 174 # https://github.com/WebAssembly/wabt/issues/2348#issuecomment-1878003959 175 .PHONY: build.spectest.threads 176 build.spectest.threads: 177 @mkdir -p $(spectest_threads_testdata_dir) 178 @cd $(spectest_threads_testdata_dir) \ 179 && curl -sSL 'https://api.github.com/repos/WebAssembly/threads/contents/test/core?ref=$(spec_version_threads)' | jq -r '.[]| .download_url' | grep -E "atomic.wast" | xargs -Iurl curl -sJL url -O 180 @cd $(spectest_threads_testdata_dir) && for f in `find . -name '*.wast'`; do \ 181 wast2json --enable-threads --debug-names $$f; \ 182 done 183 184 .PHONY: test 185 test: 186 @go test $(go_test_options) $$(go list ./... | grep -vE '$(spectest_v1_dir)|$(spectest_v2_dir)') 187 @cd internal/version/testdata && go test $(go_test_options) ./... 188 189 .PHONY: coverage 190 # replace spaces with commas 191 coverpkg = $(shell echo $(main_packages) | tr ' ' ',') 192 coverage: ## Generate test coverage 193 @go test -coverprofile=coverage.txt -covermode=atomic --coverpkg=$(coverpkg) $(main_packages) 194 @go tool cover -func coverage.txt 195 196 .PHONY: spectest 197 spectest: 198 @$(MAKE) spectest.v1 199 @$(MAKE) spectest.v2 200 201 spectest.v1: 202 @go test $(go_test_options) $$(go list ./... | grep $(spectest_v1_dir)) 203 204 spectest.v2: 205 @go test $(go_test_options) $$(go list ./... | grep $(spectest_v2_dir)) 206 207 golangci_lint_path := $(shell go env GOPATH)/bin/golangci-lint 208 209 $(golangci_lint_path): 210 @go install $(golangci_lint) 211 212 golangci_lint_goarch ?= $(shell go env GOARCH) 213 214 .PHONY: lint 215 lint: $(golangci_lint_path) 216 @GOARCH=$(golangci_lint_goarch) CGO_ENABLED=0 $(golangci_lint_path) run --timeout 5m 217 218 .PHONY: format 219 format: 220 @go run $(gofumpt) -l -w . 221 @go run $(gosimports) -local github.com/tetratelabs/ -w $(shell find . -name '*.go' -type f) 222 @go run $(asmfmt) -w $(shell find . -name '*.s' -type f) 223 224 .PHONY: check # Pre-flight check for pull requests 225 check: 226 # The following checks help ensure our platform-specific code used for system 227 # calls safely falls back on a platform unsupported by the compiler engine. 228 # This makes sure the intepreter can be used. Most often the package that can 229 # drift here is "platform" or "sysfs": 230 # 231 # Ensure we build on plan9. See #1578 232 @GOARCH=amd64 GOOS=plan9 go build ./... 233 # Ensure we build on gojs. See #1526. 234 @GOARCH=wasm GOOS=js go build ./... 235 # Ensure we build on gojs. See #1526. 236 @GOARCH=wasm GOOS=wasip1 go build ./... 237 # Ensure we build on aix. See #1723 238 @GOARCH=ppc64 GOOS=aix go build ./... 239 # Ensure we build on windows: 240 @GOARCH=amd64 GOOS=windows go build ./... 241 # Ensure we build on an arbitrary operating system: 242 @GOARCH=amd64 GOOS=dragonfly go build ./... 243 # Ensure we build on solaris/illumos: 244 @GOARCH=amd64 GOOS=illumos go build ./... 245 @GOARCH=amd64 GOOS=solaris go build ./... 246 # Ensure we build on linux arm for Dapr: 247 # gh release view -R dapr/dapr --json assets --jq 'first(.assets[] | select(.name = "daprd_linux_arm.tar.gz") | {url, downloadCount})' 248 @GOARCH=arm GOOS=linux go build ./... 249 # Ensure we build on linux 386 for Trivy: 250 # gh release view -R aquasecurity/trivy --json assets --jq 'first(.assets[] | select(.name| test("Linux-32bit.*tar.gz")) | {url, downloadCount})' 251 @GOARCH=386 GOOS=linux go build ./... 252 # Ensure we build on FreeBSD amd64 for Trivy: 253 # gh release view -R aquasecurity/trivy --json assets --jq 'first(.assets[] | select(.name| test("FreeBSD-64bit.*tar.gz")) | {url, downloadCount})' 254 @GOARCH=amd64 GOOS=freebsd go build ./... 255 @$(MAKE) lint golangci_lint_goarch=arm64 256 @$(MAKE) lint golangci_lint_goarch=amd64 257 @$(MAKE) format 258 @go mod tidy 259 @if [ ! -z "`git status -s`" ]; then \ 260 echo "The following differences will fail CI until committed:"; \ 261 git diff --exit-code; \ 262 fi 263 264 .PHONY: site 265 site: ## Serve website content 266 @git submodule update --init 267 @cd site && go run $(hugo) server --minify --disableFastRender --baseURL localhost:1313 --cleanDestinationDir -D 268 269 .PHONY: clean 270 clean: ## Ensure a clean build 271 @rm -rf dist build coverage.txt 272 @go clean -testcache 273 274 fuzz_timeout_seconds ?= 10 275 .PHONY: fuzz 276 fuzz: 277 @cd internal/integration_test/fuzz && cargo test 278 @cd internal/integration_test/fuzz && cargo fuzz run no_diff --sanitizer=none -- -rss_limit_mb=8192 -max_total_time=$(fuzz_timeout_seconds) 279 @cd internal/integration_test/fuzz && cargo fuzz run memory_no_diff --sanitizer=none -- -rss_limit_mb=8192 -max_total_time=$(fuzz_timeout_seconds) 280 @cd internal/integration_test/fuzz && cargo fuzz run validation --sanitizer=none -- -rss_limit_mb=8192 -max_total_time=$(fuzz_timeout_seconds) 281 282 #### CLI release related #### 283 284 VERSION ?= dev 285 # Default to a dummy version 0.0.1.1, which is always lower than a real release. 286 # Legal version values should look like 'x.x.x.x' where x is an integer from 0 to 65534. 287 # https://learn.microsoft.com/en-us/windows/win32/msi/productversion?redirectedfrom=MSDN 288 # https://stackoverflow.com/questions/9312221/msi-version-numbers 289 MSI_VERSION ?= 0.0.1.1 290 non_windows_platforms := darwin_amd64 darwin_arm64 linux_amd64 linux_arm64 291 non_windows_archives := $(non_windows_platforms:%=dist/wazero_$(VERSION)_%.tar.gz) 292 windows_platforms := windows_amd64 # TODO: add arm64 windows once we start testing on it. 293 windows_archives := $(windows_platforms:%=dist/wazero_$(VERSION)_%.zip) $(windows_platforms:%=dist/wazero_$(VERSION)_%.msi) 294 checksum_txt := dist/wazero_$(VERSION)_checksums.txt 295 296 # define macros for multi-platform builds. these parse the filename being built 297 go-arch = $(if $(findstring amd64,$1),amd64,arm64) 298 go-os = $(if $(findstring .exe,$1),windows,$(if $(findstring linux,$1),linux,darwin)) 299 # msi-arch is a macro so we can detect it based on the file naming convention 300 msi-arch = $(if $(findstring amd64,$1),x64,arm64) 301 302 build/wazero_%/wazero: 303 $(call go-build,$@,$<) 304 305 build/wazero_%/wazero.exe: 306 $(call go-build,$@,$<) 307 308 dist/wazero_$(VERSION)_%.tar.gz: build/wazero_%/wazero 309 @echo tar.gz "tarring $@" 310 @mkdir -p $(@D) 311 # On Windows, we pass the special flag `--mode='+rx' to ensure that we set the executable flag. 312 # This is only supported by GNU Tar, so we set it conditionally. 313 @tar -C $(<D) -cpzf $@ $(if $(findstring Windows_NT,$(OS)),--mode='+rx',) $(<F) 314 @echo tar.gz "ok" 315 316 define go-build 317 @echo "building $1" 318 @# $(go:go=) removes the trailing 'go', so we can insert cross-build variables 319 @$(go:go=) CGO_ENABLED=0 GOOS=$(call go-os,$1) GOARCH=$(call go-arch,$1) go build \ 320 -ldflags "-s -w -X github.com/bananabytelabs/wazero/internal/version.version=$(VERSION)" \ 321 -o $1 $2 ./cmd/wazero 322 @echo build "ok" 323 endef 324 325 # this makes a marker file ending in .signed to avoid repeatedly calling codesign 326 %.signed: % 327 $(call codesign,$<) 328 @touch $@ 329 330 # This requires osslsigncode package (apt or brew) or latest windows release from mtrojnar/osslsigncode 331 # 332 # Default is self-signed while production should be a Digicert signing key 333 # 334 # Ex. 335 # ```bash 336 # keytool -genkey -alias wazero -storetype PKCS12 -keyalg RSA -keysize 2048 -storepass wazero-bunch \ 337 # -keystore wazero.p12 -dname "O=wazero,CN=wazero.io" -validity 3650 338 # ``` 339 WINDOWS_CODESIGN_P12 ?= packaging/msi/wazero.p12 340 WINDOWS_CODESIGN_PASSWORD ?= wazero-bunch 341 define codesign 342 @printf "$(ansi_format_dark)" codesign "signing $1" 343 @osslsigncode sign -h sha256 -pkcs12 ${WINDOWS_CODESIGN_P12} -pass "${WINDOWS_CODESIGN_PASSWORD}" \ 344 -n "wazero is the zero dependency WebAssembly runtime for Go developers" -i https://wazero.io -t http://timestamp.digicert.com \ 345 $(if $(findstring msi,$(1)),-add-msi-dse) -in $1 -out $1-signed 346 @mv $1-signed $1 347 @printf "$(ansi_format_bright)" codesign "ok" 348 endef 349 350 # This task is only supported on Windows, where we use candle.exe (compile wxs to wixobj) and light.exe (link to msi) 351 dist/wazero_$(VERSION)_%.msi: build/wazero_%/wazero.exe.signed 352 ifeq ($(OS),Windows_NT) 353 @echo msi "building $@" 354 @mkdir -p $(@D) 355 @candle -nologo -arch $(call msi-arch,$@) -dVersion=$(MSI_VERSION) -dBin=$(<:.signed=) -o build/wazero.wixobj packaging/msi/wazero.wxs 356 @light -nologo -o $@ build/wazero.wixobj -spdb 357 $(call codesign,$@) 358 @echo msi "ok" 359 endif 360 361 dist/wazero_$(VERSION)_%.zip: build/wazero_%/wazero.exe.signed 362 @echo zip "zipping $@" 363 @mkdir -p $(@D) 364 @zip -qj $@ $(<:.signed=) 365 @echo zip "ok" 366 367 # Darwin doesn't have sha256sum. See https://github.com/actions/virtual-environments/issues/90 368 sha256sum := $(if $(findstring darwin,$(shell go env GOOS)),shasum -a 256,sha256sum) 369 $(checksum_txt): 370 @cd $(@D); touch $(@F); $(sha256sum) * >> $(@F) 371 372 dist: $(non_windows_archives) $(if $(findstring Windows_NT,$(OS)),$(windows_archives),) $(checksum_txt)