diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 05c57113d..5d1472dc1 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -385,6 +385,99 @@ jobs: ${{ github.workspace }}/test + test-windows: + needs: build-version + runs-on: windows-latest + env: + BUILD_TIME: ${{ needs.build-version.outputs.build_time }} + ZIG_DOWNLOAD_BASE_URL: "" + steps: + - name: "Show platform and environment" + shell: pwsh + run: | + systeminfo + Get-ChildItem Env: | Sort-Object Name + - name: "Set BUILD_RELEASE when we are building for a version tag" + if: startsWith(github.ref, 'refs/tags/v') + shell: pwsh + run: | + "BUILD_RELEASE=1" >> $env:GITHUB_ENV + - name: "Check out repository code" + uses: actions/checkout@v6 + - name: "Cache Haskell deps" + uses: actions/cache@v5 + with: + path: | + ~\AppData\Roaming\stack + ~\AppData\Local\Programs\stack + key: stack-windows-x86_64-${{ hashFiles('compiler/stack-windows.yaml', 'compiler/stack-windows.yaml.lock') }} + restore-keys: | + stack-windows-x86_64- + - name: "Install Stack" + shell: pwsh + run: | + choco install haskell-stack -y --no-progress + stack --version + - name: "Install MSYS2 build prerequisites" + uses: msys2/setup-msys2@v2 + with: + update: true + path-type: inherit + install: >- + coreutils + curl + findutils + grep + make + sed + tar + unzip + - name: "Build Acton distribution on Windows" + shell: msys2 {0} + run: | + set -euo pipefail + workspace="$(cygpath -u "${GITHUB_WORKSPACE}")" + make -C "${workspace}" clean + make -C "${workspace}" BUILD_RELEASE="${BUILD_RELEASE:-}" BUILD_TIME="${BUILD_TIME}" + ls -l "${workspace}/dist/bin" + "${workspace}/dist/bin/acton.exe" --help >/dev/null + - name: "Compile helloworld to the default Linux target" + shell: msys2 {0} + run: | + set -euo pipefail + cd "$(cygpath -u "${GITHUB_WORKSPACE}")" + rm -rf tmp-ci-helloworld examples/helloworld + ./dist/bin/acton.exe --tempdir tmp-ci-helloworld examples/helloworld.act + test -s examples/helloworld + ls -l examples/helloworld + - name: "Upload Windows-built Linux ELF" + uses: actions/upload-artifact@v7 + with: + name: windows-built-linux-helloworld + path: ${{ github.workspace }}/examples/helloworld + if-no-files-found: error + + + run-windows-built-linux-elf: + needs: test-windows + runs-on: ubuntu-latest + steps: + - name: "Download Windows-built Linux ELF" + uses: actions/download-artifact@v8 + with: + name: windows-built-linux-helloworld + path: windows-built-linux-helloworld + - name: "Run Windows-built Linux ELF" + run: | + set -euo pipefail + ls -l windows-built-linux-helloworld + file windows-built-linux-helloworld/helloworld + readelf -W -l windows-built-linux-helloworld/helloworld | sed -n '1,40p' + chmod +x windows-built-linux-helloworld/helloworld + windows-built-linux-helloworld/helloworld | tee helloworld.out + grep -Fx "Hello, world!" helloworld.out + + build-debs: needs: build-version strategy: diff --git a/Makefile b/Makefile index 5071e2c0d..a8b479b52 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,25 @@ include version.mk TD := $(CURDIR) +UNAME_S := $(shell uname -s) +UNAME_M := $(shell uname -m) CHANGELOG_VERSION=$(shell grep '^\#\# \[[0-9]' CHANGELOG.md | sed 's/\#\# \[\([^]]\{1,\}\)].*/\1/' | head -n1) GIT_VERSION_TAG=$(shell git tag --points-at HEAD 2>/dev/null | grep "v[0-9]" | sed -e 's/^v//') +ifeq ($(OS),Windows_NT) +OS:=windows +else ifneq ($(findstring MINGW,$(UNAME_S)),) +OS:=windows +else ifneq ($(findstring MSYS_NT,$(UNAME_S)),) +OS:=windows +endif + +EXE_SUFFIX= +ifeq ($(OS),windows) +EXE_SUFFIX=.exe +export GHC_CHARENC=UTF-8 +export LANG=C.UTF-8 +endif + ifdef HOME ZIG_LOCAL_CACHE_DIR ?= $(HOME)/.cache/acton/zig-local-cache ZIG_GLOBAL_CACHE_DIR ?= $(HOME)/.cache/acton/zig-global-cache @@ -14,10 +31,13 @@ endif export ZIG_LOCAL_CACHE_DIR export ZIG_GLOBAL_CACHE_DIR -ACTON=$(TD)/dist/bin/acton -ACTONC=dist/bin/actonc +ACTON_BIN=dist/bin/acton$(EXE_SUFFIX) +ACTONC=dist/bin/actonc$(EXE_SUFFIX) +LSP_SERVER=dist/bin/lsp-server-acton$(EXE_SUFFIX) +ACTONDB=dist/bin/actondb$(EXE_SUFFIX) +ACTON=$(TD)/$(ACTON_BIN) ZIG_VERSION:=0.16.0 -ZIG=$(TD)/dist/zig/zig +ZIG=$(TD)/dist/zig/zig$(EXE_SUFFIX) CURL:=curl --fail --location --retry 5 --retry-delay 2 --retry-max-time 120 --retry-all-errors --retry-connrefused AR=$(ZIG) ar CC=$(ZIG) cc @@ -28,7 +48,15 @@ ACTON_STACK_CC=$(TD)/compiler/tools/zig-cc.sh ACTON_STACK_CXX=$(TD)/compiler/tools/zig-cxx.sh ACTON_STACK_NEEDS_ZIG= ACTON_ZIG_TARGET= +ACTON_STACK_CONFIG=compiler/stack.yaml STACK=unset CC && unset CXX && unset CFLAGS && unset CPPFLAGS && unset LDFLAGS && unset ACTON_REAL_LD && stack +STACK_SETUP=unset CC && unset CXX && unset CFLAGS && unset CPPFLAGS && unset LDFLAGS && unset ACTON_REAL_LD && stack setup + +ifeq ($(OS),windows) +ACTON_STACK_CONFIG=compiler/stack-windows.yaml +STACK=chcp.com 65001 >/dev/null && unset CC && unset CXX && unset CFLAGS && unset CPPFLAGS && unset LDFLAGS && unset ACTON_REAL_LD && stack --stack-yaml stack-windows.yaml +STACK_SETUP=chcp.com 65001 >/dev/null && unset CC && unset CXX && unset CFLAGS && unset CPPFLAGS && unset LDFLAGS && unset ACTON_REAL_LD && stack --stack-yaml stack-windows.yaml setup +endif # Determine which xargs we have. BSD xargs does not have --no-run-if-empty, # rather, it is the default behavior so the argument is superfluous. We check if @@ -66,30 +94,41 @@ ACTC_GHC_OPTS += -fprof-auto -fprof-cafs endif # rewrite arm64 to aarch64 -ifeq ($(shell uname -m),arm64) +ifeq ($(UNAME_M),arm64) ARCH:=aarch64 else -ARCH:=$(shell uname -m) +ARCH:=$(UNAME_M) endif +# -- Windows ------------------------------------------------------------------ +ifeq ($(OS),windows) +ifeq ($(ARCH),x86_64) +ACTON_ZIG_TARGET := x86_64-windows-gnu +else ifeq ($(ARCH),aarch64) +ACTON_ZIG_TARGET := aarch64-windows-gnu +else +$(error "Unsupported architecture for Windows?" $(ARCH)) +endif +endif # -- END: Windows -------------------------------------------------------- + # -- Apple Mac OS X ------------------------------------------------------------ -ifeq ($(shell uname -s),Darwin) +ifeq ($(UNAME_S),Darwin) OS:=macos endif # -- Linux --------------------------------------------------------------------- -ifeq ($(shell uname -s),Linux) +ifeq ($(UNAME_S),Linux) OS:=linux ACTON_ZIG_GLIBC_VERSION ?= 2.31 export ACTON_ZIG_GLIBC_VERSION ACTON_STACK_NEEDS_ZIG=1 STACK=CC="$(ACTON_STACK_CC)" CXX="$(ACTON_STACK_CXX)" CFLAGS= CPPFLAGS= LDFLAGS= ACTON_REAL_LD="$(ACTON_STACK_CC)" stack --with-gcc="$(ACTON_STACK_CC)" -ifeq ($(shell uname -m),x86_64) +ifeq ($(UNAME_M),x86_64) ACTON_ZIG_TARGET := x86_64-linux-gnu.$(ACTON_ZIG_GLIBC_VERSION) -else ifeq ($(shell uname -m),aarch64) +else ifeq ($(UNAME_M),aarch64) ACTON_ZIG_TARGET := aarch64-linux-gnu.$(ACTON_ZIG_GLIBC_VERSION) else -$(error "Unsupported architecture for Linux?" $(shell uname -m)) +$(error "Unsupported architecture for Linux?" $(UNAME_M)) endif ACTONC_TARGET := --target $(ACTON_ZIG_TARGET) endif # -- END: Linux ---------------------------------------------------------- @@ -104,7 +143,7 @@ help: @echo "Available make targets:" @echo " all - build everything" @echo " test - run the test suite" - @echo " make PROFILE=1 dist/bin/acton - build profiled acton binary" + @echo " make PROFILE=1 $(ACTON_BIN) - build profiled acton binary" @echo "" @echo " clean - /normal/ clean repo" @echo " clean-all - thorough cleaning" @@ -124,7 +163,10 @@ endif BUILTIN_HFILES=$(wildcard base/builtin/*.h) -DIST_BINS=$(ACTONC) dist/bin/actondb dist/bin/runacton dist/bin/lsp-server-acton +DIST_BINS=$(ACTONC) dist/bin/runacton $(LSP_SERVER) +ifneq ($(OS),windows) +DIST_BINS += $(ACTONDB) +endif DIST_ZIG=dist/zig ifeq ($(ACTON_STACK_NEEDS_ZIG),1) ACTON_STACK_PREREQS=$(DIST_ZIG) @@ -142,13 +184,13 @@ endif # and needs a fixed location independent of the directory the link runs from. ACTON_BDEPS_DIR := $(TD)/bdeps/out export ACTON_BDEPS_DIR -# libz is the one bdeps lib that GHC actually links into acton on every platform, -# so we build and statically link it everywhere. The ld-wrapper rewrites -lz to -# this archive's full path; dropping any future lib's .a into bdeps/out/lib (e.g. -# liblmdb.a) makes it link statically the same way, with no per-lib wiring. +ifneq ($(OS),windows) +# libz is linked statically into acton on Unix-like platforms. BDEPS += bdeps/out/lib/libz.a -# liblmdb backs the compiler's .tydb interface cache; GHC links it into acton on -# every platform, so -- unlike gmp/tinfo below -- it is an unconditional bdep. +endif +# liblmdb backs the compiler's .tydb interface cache. Cabal also needs the LMDB +# headers and library while configuring the Haskell lmdb package, including on +# Windows where Stack's private MSYS2 installation does not reliably provide it. BDEPS += bdeps/out/lib/liblmdb.a ifeq ($(OS),linux) # gmp and tinfo are only pulled in by GHC on Linux (macOS GHC uses the native @@ -169,34 +211,47 @@ test-backend: $(BACKEND_TESTS) # /compiler ---------------------------------------------- ACTONC_HS=$(wildcard compiler/lib/src/*.hs compiler/lib/src/*/*.hs compiler/acton/*.hs compiler/acton/*/*.hs) ACTONLSP_HS=$(wildcard compiler/lsp-server/*.hs) -dist/bin/acton: compiler/lib/package.yaml.in compiler/acton/package.yaml.in compiler/lsp-server/package.yaml.in compiler/stack.yaml $(ACTONC_HS) $(ACTONLSP_HS) version.mk dist/builder $(ACTON_STACK_PREREQS) $(BDEPS) + +ifeq ($(OS),windows) +ACTONC_LINK_CMD=cp -f dist/bin/acton.exe dist/bin/actonc.exe +else +ACTONC_LINK_CMD=ln -sf acton dist/bin/actonc +endif + +$(ACTON_BIN): compiler/lib/package.yaml.in compiler/acton/package.yaml.in compiler/lsp-server/package.yaml.in $(ACTON_STACK_CONFIG) $(ACTONC_HS) $(ACTONLSP_HS) version.mk dist/builder $(ACTON_STACK_PREREQS) $(BDEPS) mkdir -p dist/bin - rm -f dist/bin/actonc + rm -f $(ACTONC) cd compiler && sed 's,^version: BUILD_VERSION,version: "$(VERSION)",' < lib/package.yaml.in > lib/package.yaml cd compiler && $(STACK) build acton lsp-server-acton $(ACTON_STACK_BUILD_OPTS) --ghc-options='-j4 $(ACTC_GHC_OPTS)' --dry-run 2>&1 | grep "Nothing to build" || \ (sed 's,^version: BUILD_VERSION,version: "$(VERSION_INFO)",' < acton/package.yaml.in > acton/package.yaml \ && sed 's,^version: BUILD_VERSION,version: "$(VERSION_INFO)",' < lsp-server/package.yaml.in > lsp-server/package.yaml \ - && unset CC && unset CXX && unset CFLAGS && unset CPPFLAGS && unset LDFLAGS && unset ACTON_REAL_LD && stack setup \ + && $(STACK_SETUP) \ && $(STACK) build acton lsp-server-acton $(ACTON_STACK_BUILD_OPTS) --ghc-options='-j4 $(ACTC_GHC_OPTS)') cd compiler && $(STACK) --local-bin-path=../dist/bin install acton lsp-server-acton $(ACTON_STACK_BUILD_OPTS) --ghc-options='-j4 $(ACTC_GHC_OPTS)' # Keep actonc as a symlink for compatibility - ln -sf acton dist/bin/actonc + $(ACTONC_LINK_CMD) -dist/bin/actonc: dist/bin/acton +$(ACTONC): $(ACTON_BIN) @mkdir -p $(dir $@) - ln -sf acton $@ + $(ACTONC_LINK_CMD) -dist/bin/lsp-server-acton: dist/bin/acton - @true +$(LSP_SERVER): $(ACTON_BIN) + @if [ ! -f "$@" ]; then \ + echo "$@ missing; rebuilding $(ACTON_BIN)"; \ + $(MAKE) --always-make $(ACTON_BIN); \ + fi + test -f "$@" .PHONY: clean-compiler clean-compiler: cd compiler && stack clean >/dev/null 2>&1 || true - rm -f dist/bin/acton dist/bin/actonc compiler/package.yaml compiler/acton.cabal \ + rm -f dist/bin/acton dist/bin/acton.exe dist/bin/actonc dist/bin/actonc.exe \ + dist/bin/lsp-server-acton dist/bin/lsp-server-acton.exe dist/bin/liblmdb.dll \ + compiler/package.yaml compiler/acton.cabal \ compiler/acton/package.yaml compiler/acton/acton.cabal \ compiler/lib/*.cabal compiler/acton/*.cabal compiler/lsp-server/*.cabal -ACTON_LINKAGE_BINS ?= dist/bin/acton dist/bin/lsp-server-acton dist/bin/actondb +ACTON_LINKAGE_BINS ?= $(ACTON_BIN) $(LSP_SERVER) $(ACTONDB) ACTON_ALLOWED_NEEDED_RE ?= ^(libc\.so\.6|libm\.so\.6|libdl\.so\.2|libpthread\.so\.0|librt\.so\.1|libutil\.so\.1|ld-linux-x86-64\.so\.2|ld-linux-aarch64\.so\.1)$$ .PHONY: ldd ldd: $(ACTON_LINKAGE_BINS) @@ -336,73 +391,83 @@ bdeps/out/lib/liblmdb.a: bdeps/lmdb/build.zig bdeps/lmdb/build.zig.zon $(DIST_ZI # /deps/libargp -------------------------------------------- LIBARGP_REF=137154fb257055beb11f3283021d8eccc3c4f470 LIBARGP_BUILD_ZIG=deps/libargp/build.zig +LIBARGP_BUILD_ZON=deps/libargp/build.zig.zon deps-download/$(LIBARGP_REF).tar.gz: mkdir -p deps-download $(CURL) -o $@ https://github.com/actonlang/argp-standalone/archive/$(LIBARGP_REF).tar.gz -dist/deps/libargp: deps-download/$(LIBARGP_REF).tar.gz $(LIBARGP_BUILD_ZIG) +dist/deps/libargp: deps-download/$(LIBARGP_REF).tar.gz $(LIBARGP_BUILD_ZIG) $(LIBARGP_BUILD_ZON) rm -rf "$@" mkdir -p "$@" cd "$@" && tar zx --strip-components=1 -f "$(TD)/$<" cp "$(TD)/$(LIBARGP_BUILD_ZIG)" "$@/build.zig" + cp "$(TD)/$(LIBARGP_BUILD_ZON)" "$@/build.zig.zon" rm -rf "$@/testsuite" touch "$(TD)/$@" # /deps/libbsdnt -------------------------------------------- LIBBSDNT_REF=cf7db3414867b8b4a5561bc9aa94a8050d0225c4 LIBBSDNT_BUILD_ZIG=deps/libbsdnt/build.zig +LIBBSDNT_BUILD_ZON=deps/libbsdnt/build.zig.zon deps-download/$(LIBBSDNT_REF).tar.gz: mkdir -p deps-download $(CURL) -o $@ https://github.com/actonlang/bsdnt/archive/$(LIBBSDNT_REF).tar.gz -dist/deps/libbsdnt: deps-download/$(LIBBSDNT_REF).tar.gz $(LIBBSDNT_BUILD_ZIG) +dist/deps/libbsdnt: deps-download/$(LIBBSDNT_REF).tar.gz $(LIBBSDNT_BUILD_ZIG) $(LIBBSDNT_BUILD_ZON) rm -rf "$@" mkdir -p "$@" cd "$@" && tar zx --strip-components=1 -f "$(TD)/$<" cp "$(TD)/$(LIBBSDNT_BUILD_ZIG)" "$@/build.zig" + cp "$(TD)/$(LIBBSDNT_BUILD_ZON)" "$@/build.zig.zon" touch "$(TD)/$@" # /deps/libgc -------------------------------------------- LIBGC_REF=0a23b211b558137de7ee654c5527a54113142517 LIBGC_BUILD_ZIG=deps/libgc/build.zig +LIBGC_BUILD_ZON=deps/libgc/build.zig.zon deps-download/$(LIBGC_REF).tar.gz: mkdir -p deps-download $(CURL) -o $@ https://github.com/bdwgc/bdwgc/archive/$(LIBGC_REF).tar.gz -dist/deps/libgc: deps-download/$(LIBGC_REF).tar.gz $(LIBGC_BUILD_ZIG) +dist/deps/libgc: deps-download/$(LIBGC_REF).tar.gz $(LIBGC_BUILD_ZIG) $(LIBGC_BUILD_ZON) rm -rf "$@" mkdir -p "$@" cd "$@" && tar zx --strip-components=1 -f "$(TD)/$<" cp "$(TD)/$(LIBGC_BUILD_ZIG)" "$@/build.zig" + cp "$(TD)/$(LIBGC_BUILD_ZON)" "$@/build.zig.zon" rm -rf "$@/tests" "$@/tools" touch "$(TD)/$@" # /deps/libmbedtls -------------------------------------------- LIBMBEDTLS_REF=c7d83538d3d359b05a9331bb2c9217977b5856ac LIBMBEDTLS_BUILD_ZIG=deps/mbedtls/build.zig +LIBMBEDTLS_BUILD_ZON=deps/mbedtls/build.zig.zon deps-download/$(LIBMBEDTLS_REF).tar.gz: mkdir -p deps-download $(CURL) -o $@ https://github.com/actonlang/mbedtls/archive/$(LIBMBEDTLS_REF).tar.gz -dist/deps/mbedtls: deps-download/$(LIBMBEDTLS_REF).tar.gz $(LIBMBEDTLS_BUILD_ZIG) +dist/deps/mbedtls: deps-download/$(LIBMBEDTLS_REF).tar.gz $(LIBMBEDTLS_BUILD_ZIG) $(LIBMBEDTLS_BUILD_ZON) rm -rf "$@" mkdir -p "$@" cd "$@" && tar zx --strip-components=1 -f "$(TD)/$<" cp "$(TD)/$(LIBMBEDTLS_BUILD_ZIG)" "$@/build.zig" + cp "$(TD)/$(LIBMBEDTLS_BUILD_ZON)" "$@/build.zig.zon" touch "$(TD)/$@" # /deps/libprotobuf_c -------------------------------------------- LIBPROTOBUF_C_REF=abc67a11c6db271bedbb9f58be85d6f4e2ea8389 LIBPROTOBUF_C_BUILD_ZIG=deps/libprotobuf_c/build.zig +LIBPROTOBUF_C_BUILD_ZON=deps/libprotobuf_c/build.zig.zon deps-download/$(LIBPROTOBUF_C_REF).tar.gz: mkdir -p deps-download $(CURL) -o $@ https://github.com/protobuf-c/protobuf-c/archive/$(LIBPROTOBUF_C_REF).tar.gz -dist/deps/libprotobuf_c: deps-download/$(LIBPROTOBUF_C_REF).tar.gz $(LIBPROTOBUF_C_BUILD_ZIG) +dist/deps/libprotobuf_c: deps-download/$(LIBPROTOBUF_C_REF).tar.gz $(LIBPROTOBUF_C_BUILD_ZIG) $(LIBPROTOBUF_C_BUILD_ZON) rm -rf "$@" mkdir -p "$@" cd "$@" && tar zx --strip-components=1 -f "$(TD)/$<" cp "$(TD)/$(LIBPROTOBUF_C_BUILD_ZIG)" "$@/build.zig" + cp "$(TD)/$(LIBPROTOBUF_C_BUILD_ZON)" "$@/build.zig.zon" touch "$(TD)/$@" # /deps/tlsuv --------------------------------------------- @@ -424,15 +489,17 @@ dist/deps/tlsuv: deps-download/$(TLSUV_REF).tar.gz dist/deps/libuv dist/deps/mbe # /deps/libutf8proc -------------------------------------- LIBUTF8PROC_REF=1cb28a66ca79a0845e99433fd1056257456cef8b LIBUTF8PROC_BUILD_ZIG=deps/libutf8proc/build.zig +LIBUTF8PROC_BUILD_ZON=deps/libutf8proc/build.zig.zon deps-download/$(LIBUTF8PROC_REF).tar.gz: mkdir -p deps-download $(CURL) -o $@ https://github.com/JuliaStrings/utf8proc/archive/$(LIBUTF8PROC_REF).tar.gz -dist/deps/libutf8proc: deps-download/$(LIBUTF8PROC_REF).tar.gz $(LIBUTF8PROC_BUILD_ZIG) +dist/deps/libutf8proc: deps-download/$(LIBUTF8PROC_REF).tar.gz $(LIBUTF8PROC_BUILD_ZIG) $(LIBUTF8PROC_BUILD_ZON) rm -rf "$@" mkdir -p "$@" cd "$@" && tar zx --strip-components=1 -f "$(TD)/$<" cp "$(TD)/$(LIBUTF8PROC_BUILD_ZIG)" "$@/build.zig" + cp "$(TD)/$(LIBUTF8PROC_BUILD_ZON)" "$@/build.zig.zon" touch "$(TD)/$@" # /deps/libuuid ------------------------------------------ @@ -443,58 +510,69 @@ dist/deps/libuuid: deps/libuuid # /deps/libuv -------------------------------------------- LIBUV_REF=d760a3f23511ebe7b1935fe1429147d4fca27bb4 LIBUV_BUILD_ZIG=deps/libuv/build.zig +LIBUV_BUILD_ZON=deps/libuv/build.zig.zon deps-download/$(LIBUV_REF).tar.gz: mkdir -p deps-download $(CURL) -o $@ https://github.com/actonlang/libuv/archive/$(LIBUV_REF).tar.gz -dist/deps/libuv: deps-download/$(LIBUV_REF).tar.gz $(LIBUV_BUILD_ZIG) +dist/deps/libuv: deps-download/$(LIBUV_REF).tar.gz $(LIBUV_BUILD_ZIG) $(LIBUV_BUILD_ZON) rm -rf "$@" mkdir -p "$@" cd "$@" && tar zx --strip-components=1 -f "$(TD)/$<" "libuv-$(LIBUV_REF)/include" "libuv-$(LIBUV_REF)/src" cp "$(TD)/$(LIBUV_BUILD_ZIG)" "$@/build.zig" + cp "$(TD)/$(LIBUV_BUILD_ZON)" "$@/build.zig.zon" touch "$(TD)/$@" # /deps/libxml2 ------------------------------------------ LIBXML2_REF=358ca4e6e34dd2b386aab1fdeb74a641c54940a0 LIBXML2_BUILD_ZIG=deps/libxml2/build.zig +LIBXML2_BUILD_ZON=deps/libxml2/build.zig.zon deps-download/$(LIBXML2_REF).tar.gz: mkdir -p deps-download $(CURL) -o $@ https://github.com/actonlang/libxml2/archive/$(LIBXML2_REF).tar.gz -dist/deps/libxml2: deps-download/$(LIBXML2_REF).tar.gz $(LIBXML2_BUILD_ZIG) +dist/deps/libxml2: deps-download/$(LIBXML2_REF).tar.gz $(LIBXML2_BUILD_ZIG) $(LIBXML2_BUILD_ZON) rm -rf "$@" mkdir -p "$@" - cd "$@" && tar zx --strip-components=1 -f "$(TD)/$<" + cd "$@" && tar zx --strip-components=1 \ + --exclude='*/doc' --exclude='*/example' --exclude='*/fuzz' \ + --exclude='*/os400' --exclude='*/python' --exclude='*/test*' \ + -f "$(TD)/$<" cp "$(TD)/$(LIBXML2_BUILD_ZIG)" "$@/build.zig" + cp "$(TD)/$(LIBXML2_BUILD_ZON)" "$@/build.zig.zon" rm -rf "$@/doc" "$@/example" "$@/fuzz" "$@/os400" "$@/python" $@/test* touch "$(TD)/$@" # /deps/pcre2 -------------------------------------------- LIBPCRE2_REF=e4ccef3034c870342f2d37c928e98bc8c69cd340 LIBPCRE2_BUILD_ZIG=deps/pcre2/build.zig +LIBPCRE2_BUILD_ZON=deps/pcre2/build.zig.zon deps-download/$(LIBPCRE2_REF).tar.gz: mkdir -p deps-download $(CURL) -o $@ https://github.com/PCRE2Project/pcre2/archive/$(LIBPCRE2_REF).tar.gz -dist/deps/pcre2: deps-download/$(LIBPCRE2_REF).tar.gz $(LIBPCRE2_BUILD_ZIG) +dist/deps/pcre2: deps-download/$(LIBPCRE2_REF).tar.gz $(LIBPCRE2_BUILD_ZIG) $(LIBPCRE2_BUILD_ZON) rm -rf "$@" mkdir -p "$@" cd "$@" && tar zx --strip-components=1 -f "$(TD)/$<" cp "$(TD)/$(LIBPCRE2_BUILD_ZIG)" "$@/build.zig" + cp "$(TD)/$(LIBPCRE2_BUILD_ZON)" "$@/build.zig.zon" touch "$(TD)/$@" # /deps/libsnappy_c -------------------------------------------- LIBSNAPPY_C_REF=dc05e026488865bc69313a68bcc03ef2e4ea8e83 LIBSNAPPY_C_BUILD_ZIG=deps/libsnappy_c/build.zig +LIBSNAPPY_C_BUILD_ZON=deps/libsnappy_c/build.zig.zon deps-download/$(LIBSNAPPY_C_REF).tar.gz: mkdir -p deps-download $(CURL) -o $@ https://github.com/google/snappy/archive/$(LIBSNAPPY_C_REF).tar.gz -dist/deps/libsnappy_c: deps-download/$(LIBSNAPPY_C_REF).tar.gz $(LIBSNAPPY_C_BUILD_ZIG) +dist/deps/libsnappy_c: deps-download/$(LIBSNAPPY_C_REF).tar.gz $(LIBSNAPPY_C_BUILD_ZIG) $(LIBSNAPPY_C_BUILD_ZON) rm -rf "$@" mkdir -p "$@" cd "$@" && tar zx --strip-components=1 -f "$(TD)/$<" cp "$(TD)/$(LIBSNAPPY_C_BUILD_ZIG)" "$@/build.zig" + cp "$(TD)/$(LIBSNAPPY_C_BUILD_ZON)" "$@/build.zig.zon" touch "$(TD)/$@" dist/deps/libnetstring: deps/libnetstring $(DIST_ZIG) @@ -512,41 +590,41 @@ dist/deps/libyyjson: deps/libyyjson $(DIST_ZIG) # archives must exist first. (test, test-stdlib, test-incremental, online-tests # already pull it in transitively via dist/bin/acton[c].) test-builtins test-compiler test-lib-accept test-acton-goldens-accept test-cross-compile test-syntaxerrors test-syntaxerrors-accept test-typeerrors test-typeerrors-accept test-db test-examples test-lang test-regressions test-rts: $(BDEPS) -test: dist/bin/acton - cd compiler && stack test libacton acton:incremental +test: $(ACTON_BIN) + cd compiler && $(STACK) test libacton acton:incremental # Exclude the cross-compilation group from the default run: it builds for # many targets and bloats ~/.cache/acton. Run it via `make test-cross-compile`. - cd compiler && stack test acton:test_acton --ta '-p "! /cross-compilation/"' + cd compiler && $(STACK) test acton:test_acton --ta '-p "! /cross-compilation/"' $(MAKE) test-stdlib $(MAKE) -C backend test $(MAKE) test-rts-db test-builtins: - cd compiler && stack test acton --ta '-p "Builtins"' + cd compiler && $(STACK) test acton --ta '-p "Builtins"' test-compiler: - cd compiler && stack test libacton - cd compiler && stack test acton --ta '-p "compiler"' + cd compiler && $(STACK) test libacton + cd compiler && $(STACK) test acton --ta '-p "compiler"' test-compiler-accept: test-lib-accept test-acton-goldens-accept test-lib-accept: - cd compiler && stack test libacton:test_lib --test-arguments "--golden-start --golden-reset" + cd compiler && $(STACK) test libacton:test_lib --test-arguments "--golden-start --golden-reset" test-acton-goldens-accept: - cd compiler && stack test acton:test_acton --test-arguments "--accept" + cd compiler && $(STACK) test acton:test_acton --test-arguments "--accept" test-goldens-accept: test-compiler-accept test-incremental-accept test-syntaxerrors-accept test-typeerrors-accept test-cross-compile: - cd compiler && stack test acton --ta '-p "/cross-compilation/"' + cd compiler && $(STACK) test acton --ta '-p "/cross-compilation/"' -test-incremental: dist/bin/actonc - cd compiler && stack test acton:incremental +test-incremental: $(ACTONC) + cd compiler && $(STACK) test acton:incremental .PHONY: test-incremental-accept -test-incremental-accept: dist/bin/actonc - cd compiler && stack test acton:incremental --ta "--accept" +test-incremental-accept: $(ACTONC) + cd compiler && $(STACK) test acton:incremental --ta "--accept" .PHONY: test-rebuild test-rebuild-accept test-rebuild: test-incremental @@ -554,42 +632,42 @@ test-rebuild: test-incremental test-rebuild-accept: test-incremental-accept test-syntaxerrors: - cd compiler && stack test acton --ta '-p "syntax errors"' + cd compiler && $(STACK) test acton --ta '-p "syntax errors"' test-syntaxerrors-accept: cd compiler/acton && stack runghc -- test.hs -p "syntax errors" --accept test-typeerrors: - cd compiler && stack test acton --ta '-p "type errors"' + cd compiler && $(STACK) test acton --ta '-p "type errors"' test-typeerrors-accept: - cd compiler && stack test acton:test_acton --ta '-p "type errors" --accept' + cd compiler && $(STACK) test acton:test_acton --ta '-p "type errors" --accept' test-db: - cd compiler && stack test acton --ta '-p "DB"' + cd compiler && $(STACK) test acton --ta '-p "DB"' test-examples: - cd compiler && stack test acton --ta '-p "Examples"' + cd compiler && $(STACK) test acton --ta '-p "Examples"' test-lang: - cd compiler && stack test acton --ta '-p "Core language"' + cd compiler && $(STACK) test acton --ta '-p "Core language"' test-regressions: - cd compiler && stack test acton --ta '-p "Regression"' + cd compiler && $(STACK) test acton --ta '-p "Regression"' test-rts: - cd compiler && stack test acton --ta '-p "RTS"' + cd compiler && $(STACK) test acton --ta '-p "RTS"' test-rts-db: $(MAKE) -C test -test-stdlib: dist/bin/acton dist/std - cd compiler && stack test acton --ta '-p "stdlib"' +test-stdlib: $(ACTON_BIN) dist/std + cd compiler && $(STACK) test acton --ta '-p "stdlib"' $(MAKE) -C test tls-test-server cd test/stdlib_tests && "$(ACTON)" test -online-tests: dist/bin/actonc - cd compiler && stack test acton:test_acton_online +online-tests: $(ACTONC) + cd compiler && $(STACK) test acton:test_acton_online .PHONY: clean clean-all clean-base clean-std clean-bdeps @@ -611,24 +689,27 @@ clean-bdeps: # BACKEND_FILES = backend/Build.act backend/build.zig backend/build.zig.zon $(wildcard backend/*.c backend/*.h backend/failure_detector/*.c backend/failure_detector/*.h) -DIST_BACKEND_FILES = $(addprefix dist/,$(BACKEND_FILES)) dist/backend/deps dist/bin/actondb +DIST_BACKEND_FILES = $(addprefix dist/,$(BACKEND_FILES)) dist/backend/deps +ifneq ($(OS),windows) +DIST_BACKEND_FILES += $(ACTONDB) +endif dist/backend%: backend/% mkdir -p "$(dir $@)" cp -a "$<" "$@" .PHONY: dist/base -dist/base: base base/.build base/__root.zig base/acton.zig base/build.zig base/build.zig.zon base/acton.zig dist/bin/actonc $(DEPS) dist/backend/Build.act +dist/base: base base/.build base/__root.zig base/acton.zig base/build.zig base/build.zig.zon base/acton.zig $(ACTONC) $(DEPS) dist/backend/Build.act mkdir -p "$@" "$@/.build" "$@/out" rm -rf "$@/src" "$@/out/types/std" cp -a base/__root.zig base/Build.act base/acton.zig base/build.zig base/build.zig.zon base/builtin base/rts base/src dist/base/ - cd dist/base && ../bin/actonc build --skip-build && rm -rf .build + cd dist/base && ../bin/actonc$(EXE_SUFFIX) build --skip-build && rm -rf .build .PHONY: dist/std -dist/std: std std/Build.act std/build.zig std/build.zig.zon dist/base dist/bin/actonc $(DEPS) +dist/std: std std/Build.act std/build.zig std/build.zig.zon dist/base $(ACTONC) $(DEPS) mkdir -p "$@" "$@/.build" "$@/out" rm -rf "$@/src" "$@/out/types" cp -a std/Build.act std/build.zig std/build.zig.zon std/src dist/std/ - cd dist/std && ../bin/actonc build --skip-build && rm -rf .build + cd dist/std && ../bin/actonc$(EXE_SUFFIX) build --skip-build && rm -rf .build # This does a little hack, first copying and then moving the file in place. This # is to avoid an error if the executable is currently running. cp tries to open @@ -640,9 +721,9 @@ ifeq ($(OS),macos) # /dev/null to prevent Zig from trying to use them and instead falling back to # its own implementation. # See https://codeberg.org/ziglang/zig/issues/31658. -dist/bin/actondb: export DEVELOPER_DIR := $(or $(DEVELOPER_DIR),/dev/null) +$(ACTONDB): export DEVELOPER_DIR := $(or $(DEVELOPER_DIR),/dev/null) endif -dist/bin/actondb: $(DIST_ZIG) $(DEPS) +$(ACTONDB): $(DIST_ZIG) $(DEPS) @mkdir -p $(dir $@) cd dist/backend && "$(ZIG)" build -Donly_actondb $(if $(ACTON_ZIG_TARGET),-Dtarget=$(ACTON_ZIG_TARGET)) --prefix "$(TD)/dist" @@ -663,7 +744,11 @@ dist/completion/acton.bash-completion: completion/acton.bash-completion mkdir -p "$(dir $@)" cp "$<" "$@" +ifeq ($(OS),windows) +ZIG_TARBALL=zig-$(ARCH)-windows-$(ZIG_VERSION).zip +else ZIG_TARBALL=zig-$(ARCH)-$(OS)-$(ZIG_VERSION).tar.xz +endif ZIG_DOWNLOAD_BASE_URL ?= ifeq ($(strip $(ZIG_DOWNLOAD_BASE_URL)),) ifeq ($(findstring -dev,$(ZIG_VERSION)),-dev) @@ -677,7 +762,16 @@ endif dist/zig: deps-download/$(ZIG_TARBALL) mkdir -p "$@" +ifeq ($(OS),windows) + rm -rf "$@.tmp" + mkdir -p "$@.tmp" + unzip -q "$(TD)/$<" -d "$@.tmp" + rm -rf "$@" + mv "$@.tmp"/zig-* "$@" + rm -rf "$@.tmp" +else cd "$@" && tar Jx --strip-components=1 -f "../../$^" +endif rm -rf "$@/doc" cp -a deps/zig-extras/* "$@" diff --git a/compiler/acton/Main.hs b/compiler/acton/Main.hs index 83a2afc06..0adc9ede8 100644 --- a/compiler/acton/Main.hs +++ b/compiler/acton/Main.hs @@ -63,7 +63,7 @@ import Data.Word (Word32) import Data.Graph import Data.String.Utils (replace) import Data.Version (showVersion) -import Data.Char (toLower) +import Data.Char (isAlpha, toLower) import qualified Data.List import Data.Either (partitionEithers) import qualified Data.Map as M @@ -83,15 +83,16 @@ import System.Environment (lookupEnv) import System.Exit import System.FileLock import System.FilePath ((), addTrailingPathSeparator) -import System.FilePath.Posix +import System.FilePath.Posix hiding ((), addTrailingPathSeparator) import System.IO hiding (readFile, writeFile) import System.IO.Temp (writeSystemTempFile) import Text.PrettyPrint (renderStyle, style, Style(..), Mode(PageMode)) import Text.Show.Pretty (ppDoc) import System.IO.Unsafe (unsafePerformIO) import System.Info -import System.Posix.Files -import System.Posix.IO (createPipe, setFdOption, closeFd, FdOption(..)) +#if !defined(mingw32_HOST_OS) +import System.Posix.IO (createPipe, fdToHandle, setFdOption, closeFd, FdOption(..)) +#endif import System.Process hiding (createPipe) import qualified System.FSNotify as FS import qualified System.Environment @@ -179,8 +180,14 @@ optimizeModeToZig C.ReleaseSmall = "ReleaseSmall" optimizeModeToZig C.ReleaseFast = "ReleaseFast" zig :: Paths -> FilePath -zig paths = sysPath paths ++ "/zig/zig" +zig paths = sysPath paths ++ "/zig/" ++ zigExeName +zigExeName :: FilePath +#if defined(mingw32_HOST_OS) +zigExeName = "zig.exe" +#else +zigExeName = "zig" +#endif -- Try to acquire a lock, return Nothing if failed, Just (FileLock, FilePath) if succeeded tryLock :: FilePath -> IO (Maybe (FileLock, FilePath)) @@ -828,24 +835,14 @@ dispatchWatchTrigger notify trigger = -- | Classify project FS events into full or incremental rebuild triggers. actWatchTrigger :: FS.Event -> Maybe WatchTrigger actWatchTrigger ev = - case FS.eventIsDirectory ev of - FS.IsDirectory -> - case ev of - FS.Added{} -> Just WatchFull - FS.Removed{} -> Just WatchFull - FS.WatchedDirectoryRemoved{} -> Just WatchFull - FS.Unknown{} -> Just WatchFull - _ -> Nothing - FS.IsFile -> - if takeExtension (FS.eventPath ev) /= ".act" - then Nothing - else case ev of - FS.ModifiedAttributes{} -> Nothing - FS.Added{} -> Just WatchFull - FS.Removed{} -> Just WatchFull - FS.WatchedDirectoryRemoved{} -> Just WatchFull - FS.Unknown{} -> Just WatchFull - _ -> Just (WatchIncremental (FS.eventPath ev)) + let path = FS.eventPath ev + in if takeExtension path /= ".act" + then Nothing + else case ev of + FS.Added{} -> Just WatchFull + FS.Removed{} -> Just WatchFull + FS.Unknown{} -> Just WatchFull + _ -> Just (WatchIncremental path) -- | Classify FS events for a specific file path. fileWatchTrigger :: FilePath -> FS.Event -> Maybe WatchTrigger @@ -854,7 +851,8 @@ fileWatchTrigger target ev = in if evPath /= target then Nothing else case ev of - FS.ModifiedAttributes{} -> Nothing + FS.Removed{} -> Just WatchFull + FS.Unknown{} -> Just WatchFull _ -> Just (WatchIncremental (FS.eventPath ev)) -- | Run the project watch loop and schedule compiles on events. @@ -1952,7 +1950,7 @@ runCliPostCompile cliHooks gopts plan env = do | otherwise = [binTask] preTestBinTasks = map (\t -> BinTask True (modNameToString (name t)) (A.GName (name t) (A.name "test_main")) True) rootTasks selectedTasksByProj = selectedTasksWithProvidersByProj globalTasks neededTasks - depModuleOptsByProj = depModuleOptionsByProj selectedTasksByProj projMap + depModuleOptsByProj = depModuleOptionsByProj sysAbs selectedTasksByProj projMap rootSelectedModuleEntries = selectedCSourceEntriesForProj rootProj (M.findWithDefault [] rootProj selectedTasksByProj) rootBuildLibraries = explicitBuildLibraries rootSelectedModuleEntries rootSpec rootModuleEntries = excludeLibrarySources rootBuildLibraries rootSelectedModuleEntries @@ -2062,15 +2060,18 @@ selectedRootStubEntriesForBins paths bins = | b <- bins ] --- | For each consuming project, map dep name to selected C-source CSV. -depModuleOptionsByProj :: M.Map FilePath [GlobalTask] -> M.Map FilePath ProjCtx -> M.Map FilePath (M.Map String String) -depModuleOptionsByProj tasksByProj projMap = +-- | For each consuming project, map generated Acton dep name to selected C-source CSV. +depModuleOptionsByProj :: FilePath -> M.Map FilePath [GlobalTask] -> M.Map FilePath ProjCtx -> M.Map FilePath (M.Map String String) +depModuleOptionsByProj sysAbs tasksByProj projMap = M.map mkForProj projMap where + sysRoot = addTrailingPathSeparator sysAbs + isSysProj p = p == sysAbs || sysRoot `isPrefixOf` p mkForProj ctx = M.fromList [ (depName, mkCsv depProj) | (depName, depProj) <- projDeps ctx + , not (isSysProj depProj) ] mkCsv depProj = intercalate "," (selectedCSourceEntriesForProj depProj (M.findWithDefault [] depProj tasksByProj)) @@ -2347,32 +2348,38 @@ runZig gopts opts zigExe zigArgs paths wd mProgressUI = do ui <- mProgressUI let tp = puTermProgress ui if termProgressEnabled tp then Just tp else Nothing - (envOverride, onStart, onStop, closeFds) <- case mTermProgress of - Nothing -> return (Nothing, \_ -> return (), return (), True) - Just tp -> do - (readFd, writeFd) <- createPipe - setFdOption writeFd CloseOnExec False - setFdOption readFd CloseOnExec True - doneVar <- newEmptyMVar - pctRef <- newIORef (85 :: Int) - let updatePercent ratio = do - let clamped = max 0 (min 0.999 ratio) - pctRaw = 85 + floor (clamped * 15) - pct <- atomicModifyIORef' pctRef (\prev -> let next = max prev pctRaw in (next, next)) - withLock (termProgressPercent tp pct) - reader = do - readZigProgressStream readFd $ \msg -> - case zigProgressRatio msg of - Nothing -> return () - Just ratio -> updatePercent ratio - _ <- forkIO (reader `finally` putMVar doneVar ()) - let envVal = show (fromIntegral writeFd :: Int) - onStart' _ = closeFd writeFd `catch` ignoreIO - onStop' = do - closeFd writeFd `catch` ignoreIO - closeFd readFd `catch` ignoreIO - takeMVar doneVar - return (Just ("ZIG_PROGRESS", envVal), onStart', onStop', False) + (envOverride, onStart, onStop, closeFds) <- +#if defined(mingw32_HOST_OS) + return (Nothing, \_ -> return (), return (), True) +#else + case mTermProgress of + Nothing -> return (Nothing, \_ -> return (), return (), True) + Just tp -> do + (readFd, writeFd) <- createPipe + setFdOption writeFd CloseOnExec False + setFdOption readFd CloseOnExec True + readHandle <- fdToHandle readFd + doneVar <- newEmptyMVar + pctRef <- newIORef (85 :: Int) + let updatePercent ratio = do + let clamped = max 0 (min 0.999 ratio) + pctRaw = 85 + floor (clamped * 15) + pct <- atomicModifyIORef' pctRef (\prev -> let next = max prev pctRaw in (next, next)) + withLock (termProgressPercent tp pct) + reader = do + readZigProgressStream readHandle $ \msg -> + case zigProgressRatio msg of + Nothing -> return () + Just ratio -> updatePercent ratio + _ <- forkIO (reader `finally` putMVar doneVar ()) + let envVal = show (fromIntegral writeFd :: Int) + onStart' _ = closeFd writeFd `catch` ignoreIO + onStop' = do + closeFd writeFd `catch` ignoreIO + hClose readHandle `catch` ignoreIO + takeMVar doneVar + return (Just ("ZIG_PROGRESS", envVal), onStart', onStop', False) +#endif let env1 = if System.Info.os == "darwin" && not (any ((== "DEVELOPER_DIR") . fst) env0) then ("DEVELOPER_DIR", "/dev/null") : env0 else env0 @@ -2409,7 +2416,7 @@ generateFingerprint name = do genBuildZigFiles :: BuildSpec.BuildSpec -> M.Map String BuildSpec.PkgDep -> [(String, FilePath)] -> Paths -> M.Map String String -> M.Map String FilePath -> IO () genBuildZigFiles spec rootPins depOverrides paths depModuleOpts depPathOverrides = do let proj = projPath paths - projAbs <- canonicalizePath proj + projAbs <- normalizePathSafe proj let sys = sysPath paths buildZigPath = joinPath [proj, "build.zig"] buildZonPath = joinPath [proj, "build.zig.zon"] @@ -2420,8 +2427,8 @@ genBuildZigFiles spec rootPins depOverrides paths depModuleOpts depPathOverrides let zonName = BuildSpec.specName spec fp = BuildSpec.fingerprint spec (transPkgs, transZigs) <- collectDepsRecursive spec proj rootPins depOverrides - absSys <- canonicalizePath sys - let relSys = relativeViaRoot projAbs absSys + absSys <- normalizePathSafe sys + let relSys = zonPath (relativeViaRoot projAbs absSys) homeDir <- getHomeDirectory depsRootAbs <- normalizePathSafe (joinPath [homeDir, ".cache", "acton", "deps"]) normalizedSpec <- normalizeSpecPaths proj spec @@ -2567,16 +2574,25 @@ genBuildZig template spec zigDeps depModuleOpts = in unlines $ header ++ concatMap inject (lines template) where pkgDepDef (name, _) = - let selectedCsv = M.findWithDefault "" name depModuleOpts - in unlines [ " const actdep_" ++ name ++ " = b.dependency(\"" ++ name ++ "\", .{" - , " .target = target," - , " .optimize = optimize," - , " .no_threads = no_threads," - , " .db = db," - , " .acton_modules = " ++ show selectedCsv ++ "," - , " .acton_root_stubs = \"\"," - , " });" - ] + let actonProjectArgs = + case M.lookup name depModuleOpts of + Just selectedCsv -> actonModuleArgs selectedCsv + Nothing + | name == "std" -> [] + | otherwise -> actonModuleArgs "" + in unlines $ + [ " const actdep_" ++ name ++ " = b.dependency(\"" ++ name ++ "\", .{" + , " .target = target," + , " .optimize = optimize," + , " .no_threads = no_threads," + , " .db = db," + ] + ++ actonProjectArgs + ++ [ " });" ] + actonModuleArgs selectedCsv = + [ " .acton_modules = " ++ show selectedCsv ++ "," + , " .acton_root_stubs = \"\"," + ] pkgLibLink (name, _) = " libActonProject.root_module.linkLibrary(actdep_" ++ name ++ ".artifact(\"ActonProject\"));\n" ++ " for (explicit_static_libraries.items) |libActonExplicit| {\n" @@ -2602,6 +2618,15 @@ genBuildZig template spec zigDeps depModuleOpts = zigExeLink resolved = concat [ " executable.root_module.linkLibrary(dep_" ++ zigDepResolvedVarName resolved ++ ".artifact(\"" ++ art ++ "\"));\n" | art <- BuildSpec.artifacts (zigDepResolvedDep resolved) ] +zonPath :: FilePath -> String +zonPath = concatMap escapeChar . map slash + where + slash '\\' = '/' + slash c = c + + escapeChar '"' = "\\\"" + escapeChar c = [c] + genBuildZigZon :: String -> String -> FilePath -> FilePath -> String -> String -> BuildSpec.BuildSpec -> [ZigDepResolved] -> String genBuildZigZon template relSys depsRootAbs projAbs fingerprint zonName spec zigDepsResolved = let @@ -2630,7 +2655,7 @@ genBuildZigZon template relSys depsRootAbs projAbs fingerprint zonName spec zigD if isAbsolutePath rawPath then normalise rawPath else normalise (rebasePath projRoot rawPath) - path = relativeViaRoot projRoot pathAbs + path = zonPath (relativeViaRoot projRoot pathAbs) in unlines [ " ." ++ name ++ " = .{" , " .path = \"" ++ path ++ "\"," , " }," @@ -2642,7 +2667,7 @@ genBuildZigZon template relSys depsRootAbs projAbs fingerprint zonName spec zigD if isAbsolutePath p then normalise p else normalise (rebasePath projAbs p) - relPath = relativeViaRoot projAbs absPath + relPath = zonPath (relativeViaRoot projAbs absPath) in unlines [ " ." ++ zigDepResolvedPkgName resolved ++ " = .{" , " .path = \"" ++ relPath ++ "\"," , " }," @@ -2794,18 +2819,24 @@ relativeViaRoot :: FilePath -> FilePath -> FilePath relativeViaRoot baseAbs targetAbs | not (isAbsolutePath targetAbs) = targetAbs | otherwise = - let (bDriveRaw, bPath) = splitDrive (normalise baseAbs) - (tDriveRaw, tPath) = splitDrive (normalise targetAbs) - bDrive = map toLower bDriveRaw - tDrive = map toLower tDriveRaw - in if bDrive /= tDrive && (not (null bDrive) || not (null tDrive)) - then makeRelativeOrAbsolute baseAbs targetAbs + let bParts = cleanParts (normalise baseAbs) + tParts = cleanParts (normalise targetAbs) + bDrive = pathDrive bParts + tDrive = pathDrive tParts + in if bDrive /= tDrive + then normalise targetAbs else - let ups = replicate (length (cleanParts bPath)) ".." - tParts = cleanParts tPath - in joinPath (ups ++ tParts) + let common = length (takeWhile (uncurry (==)) (zip bParts tParts)) + ups = replicate (length bParts - common) ".." + relParts = ups ++ drop common tParts + in if null relParts then "." else joinPath relParts where cleanParts = filter (\c -> not (null c) && c /= "/") . splitDirectories + pathDrive (p:_) + | isDriveComponent p = Just (map toLower p) + pathDrive _ = Nothing + isDriveComponent [c, ':'] = isAlpha c + isDriveComponent _ = False -- | Walk BuildSpec dependencies to collect transitive packages and zig deps. collectDepsRecursive :: BuildSpec.BuildSpec -> FilePath -> M.Map String BuildSpec.PkgDep -> [(String, FilePath)] -> IO (M.Map String BuildSpec.PkgDep, [ZigDepRef]) diff --git a/compiler/acton/PkgCommands.hs b/compiler/acton/PkgCommands.hs index b44a80d2a..6f358bdb8 100644 --- a/compiler/acton/PkgCommands.hs +++ b/compiler/acton/PkgCommands.hs @@ -1,3 +1,4 @@ +{-# LANGUAGE CPP #-} {-# LANGUAGE OverloadedStrings #-} module PkgCommands ( installCommand @@ -1000,7 +1001,14 @@ getZigExe :: IO FilePath getZigExe = do execDir <- takeDirectory <$> getExecutablePath sysPath <- canonicalizePath (execDir "..") - return (sysPath "zig" "zig") + return (sysPath "zig" zigExeName) + +zigExeName :: FilePath +#if defined(mingw32_HOST_OS) +zigExeName = "zig.exe" +#else +zigExeName = "zig" +#endif validateDepName :: String -> IO () validateDepName name = diff --git a/compiler/acton/TerminalSize.hs b/compiler/acton/TerminalSize.hs index 21b96b240..98fc44afc 100644 --- a/compiler/acton/TerminalSize.hs +++ b/compiler/acton/TerminalSize.hs @@ -1,4 +1,5 @@ {-# LANGUAGE CApiFFI #-} +{-# LANGUAGE CPP #-} module TerminalSize ( TermSize @@ -18,11 +19,13 @@ import Control.Exception (SomeException, try) import Control.Monad (when) import Data.IORef import Data.List (isInfixOf) +#if !defined(mingw32_HOST_OS) import Foreign import Foreign.C.Types -import System.Environment (lookupEnv) import System.Posix.IO (stdOutput) import System.Posix.Signals (Handler(..), installHandler) +#endif +import System.Environment (lookupEnv) data TermSize = TermSize { tsEnabled :: Bool @@ -31,6 +34,7 @@ data TermSize = TermSize , tsDirtyRef :: IORef Bool } +#if !defined(mingw32_HOST_OS) data WinSize = WinSize { wsRows :: CUShort , wsCols :: CUShort @@ -61,6 +65,7 @@ foreign import capi unsafe "signal.h value SIGWINCH" foreign import capi unsafe "sys/ioctl.h ioctl" c_ioctlWinsize :: CInt -> CULong -> Ptr WinSize -> IO CInt +#endif defaultRows :: Int defaultRows = 24 @@ -82,8 +87,10 @@ initTermSize enabled = do , tsDirtyRef = dirtyRef } when enabled $ do +#if !defined(mingw32_HOST_OS) _ <- try (installHandler (fromIntegral c_SIGWINCH) (Catch (writeIORef dirtyRef True)) Nothing) :: IO (Either SomeException Handler) +#endif _ <- termSizeSync ts return () return ts @@ -168,6 +175,9 @@ termRenderedRowsTotal :: Int -> [String] -> Int termRenderedRowsTotal width = sum . map (termRenderedRows width) queryTermSize :: IO (Maybe (Int, Int)) +#if defined(mingw32_HOST_OS) +queryTermSize = return Nothing +#else queryTermSize = alloca $ \ptr -> do rc <- c_ioctlWinsize (fromIntegral stdOutput) c_TIOCGWINSZ ptr @@ -180,6 +190,7 @@ queryTermSize = if rows' > 0 && cols' > 0 then return (Just (rows', cols')) else return Nothing +#endif envOrDefault :: String -> Int -> IO Int envOrDefault name fallback = do diff --git a/compiler/acton/ZigProgress.hs b/compiler/acton/ZigProgress.hs index 903cf04f2..8e3bc478b 100644 --- a/compiler/acton/ZigProgress.hs +++ b/compiler/acton/ZigProgress.hs @@ -13,8 +13,7 @@ import qualified Data.ByteString.Char8 as BSC import Data.List (foldl') import qualified Data.Set as Set import Data.Word (Word8, Word32) -import qualified System.Posix.IO.ByteString as PIOB -import System.Posix.Types (Fd) +import System.IO (Handle) data ZigNode = ZigNode { znCompleted :: Word32 @@ -27,11 +26,11 @@ data ZigProgress = ZigProgress { zpNodes :: [ZigNode] } deriving (Show) -readZigProgressStream :: Fd -> (ZigProgress -> IO ()) -> IO () -readZigProgressStream fd onMsg = go BS.empty +readZigProgressStream :: Handle -> (ZigProgress -> IO ()) -> IO () +readZigProgressStream handle onMsg = go BS.empty where go buf = do - res <- (try (PIOB.fdRead fd 4096) :: IO (Either IOException BS.ByteString)) + res <- (try (BS.hGetSome handle 4096) :: IO (Either IOException BS.ByteString)) case res of Left _ -> return () Right chunk | BS.null chunk -> return () diff --git a/compiler/acton/package.yaml.in b/compiler/acton/package.yaml.in index f6900cd61..d022bf7e0 100644 --- a/compiler/acton/package.yaml.in +++ b/compiler/acton/package.yaml.in @@ -47,18 +47,17 @@ dependencies: - random - split - system-filepath - - sydtest - - tasty - - tasty-expected-failure - - tasty-golden - - tasty-hunit - text - temporary - time - timeit - - unix - unordered-containers - regex-tdfa + +when: + - condition: "!os(windows)" + dependencies: + - unix executables: acton: @@ -86,6 +85,9 @@ executables: # default linker instead of breaking. The script branches internally: GNU ld # -Bstatic toggling on Linux, an -lfoo -> libfoo.a rewrite for ld64 on macOS. when: + - condition: os(windows) + ghc-options: + - -fno-PIC - condition: os(linux) # -no-pie is required on Linux but invalid on macOS (executables are PIE). ghc-options: @@ -100,6 +102,11 @@ tests: test_acton: main: test.hs source-dirs: . + dependencies: + - tasty + - tasty-expected-failure + - tasty-golden + - tasty-hunit ghc-options: - -threaded - -rtsopts @@ -107,6 +114,10 @@ tests: incremental: main: test_incremental.hs source-dirs: . + dependencies: + - tasty + - tasty-golden + - tasty-hunit ghc-options: - -threaded - -rtsopts @@ -114,6 +125,9 @@ tests: test_acton_online: main: test_online.hs source-dirs: . + dependencies: + - tasty + - tasty-hunit ghc-options: - -threaded - -rtsopts diff --git a/compiler/acton/test.hs b/compiler/acton/test.hs index e4ec03ad9..9cc18b9c1 100644 --- a/compiler/acton/test.hs +++ b/compiler/acton/test.hs @@ -1364,12 +1364,12 @@ actonProjTests = rootZon <- readFile (proj "build.zig.zon") depAZon <- readFile (depA "build.zig.zon") expect ".dep_a = .{" rootZon "root build.zig.zon should declare dep_a" - expectAny ["dep_override/deps/dep_a", "dep_override\\deps\\dep_a"] rootZon "root build.zig.zon should use dep_a override path" + expectAny ["deps/dep_a", "deps\\dep_a", "dep_override/deps/dep_a", "dep_override\\deps\\dep_a"] rootZon "root build.zig.zon should use dep_a override path" expect ".dep_b = .{" rootZon "root build.zig.zon should declare dep_b" - expectAny ["dep_override/deps/dep_b", "dep_override\\deps\\dep_b"] rootZon "root build.zig.zon should use dep_b override path transitively" + expectAny ["deps/dep_b", "deps\\dep_b", "dep_override/deps/dep_b", "dep_override\\deps\\dep_b"] rootZon "root build.zig.zon should use dep_b override path transitively" assertBool "root build.zig.zon should not use cached dep_b hash path" (not ("dep_b-" `isInfixOf` rootZon)) expect ".dep_c = .{" rootZon "root build.zig.zon should declare dep_c (non-overridden) transitively" - expectAny ["dep_override/deps/dep_c", "dep_override\\deps\\dep_c"] rootZon "root build.zig.zon should keep dep_c path" + expectAny ["deps/dep_c", "deps\\dep_c", "dep_override/deps/dep_c", "dep_override\\deps\\dep_c"] rootZon "root build.zig.zon should keep dep_c path" assertBool "root build.zig.zon should not include undeclared ghost override" (not ("ghost" `isInfixOf` rootZon)) expect ".dep_b = .{" depAZon "dep_a build.zig.zon should declare dep_b" expectAny ["dep_override/deps/dep_b", "dep_override\\deps\\dep_b", "../dep_b", "..\\dep_b"] depAZon "dep_a build.zig.zon should use dep_b override path" diff --git a/compiler/lib/cbits/wcwidth.c b/compiler/lib/cbits/wcwidth.c new file mode 100644 index 000000000..8b3eec615 --- /dev/null +++ b/compiler/lib/cbits/wcwidth.c @@ -0,0 +1,52 @@ +#if defined(_WIN32) +#include + +static int in_range(unsigned int c, unsigned int lo, unsigned int hi) { + return c >= lo && c <= hi; +} + +int wcwidth(wchar_t wc) { + unsigned int c = (unsigned int)wc; + + if (c == 0) { + return 0; + } + if (c < 32 || in_range(c, 0x7f, 0x9f)) { + return -1; + } + if (in_range(c, 0x0300, 0x036f) || + in_range(c, 0x0483, 0x0489) || + in_range(c, 0x0591, 0x05bd) || + c == 0x05bf || + in_range(c, 0x05c1, 0x05c2) || + in_range(c, 0x05c4, 0x05c5) || + c == 0x05c7 || + in_range(c, 0x0610, 0x061a) || + in_range(c, 0x064b, 0x065f) || + c == 0x0670 || + in_range(c, 0x06d6, 0x06dc) || + in_range(c, 0x06df, 0x06e4) || + in_range(c, 0x06e7, 0x06e8) || + in_range(c, 0x06ea, 0x06ed) || + in_range(c, 0x200b, 0x200f) || + in_range(c, 0x202a, 0x202e) || + in_range(c, 0x2060, 0x206f) || + in_range(c, 0xfe00, 0xfe0f)) { + return 0; + } + if (in_range(c, 0x1100, 0x115f) || + c == 0x2329 || + c == 0x232a || + in_range(c, 0x2e80, 0xa4cf) || + in_range(c, 0xac00, 0xd7a3) || + in_range(c, 0xf900, 0xfaff) || + in_range(c, 0xfe10, 0xfe19) || + in_range(c, 0xfe30, 0xfe6f) || + in_range(c, 0xff00, 0xff60) || + in_range(c, 0xffe0, 0xffe6)) { + return 2; + } + + return 1; +} +#endif diff --git a/compiler/lib/package.yaml.in b/compiler/lib/package.yaml.in index ac9d8844f..0fc8609c4 100644 --- a/compiler/lib/package.yaml.in +++ b/compiler/lib/package.yaml.in @@ -43,24 +43,31 @@ dependencies: - optparse-applicative - parser-combinators - pretty - - pretty-show - prettyprinter - process - random - scientific - stm - - sydtest - - sydtest-discover - temporary - text - time - transformers - - unix - unordered-containers - utf8-string +when: + - condition: "!os(windows)" + dependencies: + - unix + library: source-dirs: src + when: + - condition: os(windows) + c-sources: + - cbits/wcwidth.c + ghc-options: + - -fno-PIC exposed-modules: - Acton.Boxing - Acton.BuildSpec @@ -100,6 +107,8 @@ tests: source-dirs: test dependencies: - libacton + - sydtest + - sydtest-discover ghc-options: - -threaded - -rtsopts @@ -112,6 +121,9 @@ executables: other-modules: [] dependencies: - libacton + when: + - condition: os(windows) + buildable: false ghc-options: - -threaded - -rtsopts @@ -122,6 +134,9 @@ executables: other-modules: [] dependencies: - libacton + when: + - condition: os(windows) + buildable: false ghc-options: - -threaded - -rtsopts @@ -132,6 +147,9 @@ executables: other-modules: [] dependencies: - libacton + when: + - condition: os(windows) + buildable: false ghc-options: - -threaded - -rtsopts diff --git a/compiler/lib/src/Acton/CommandLineParser.hs b/compiler/lib/src/Acton/CommandLineParser.hs index 86b215192..c8451a4f4 100644 --- a/compiler/lib/src/Acton/CommandLineParser.hs +++ b/compiler/lib/src/Acton/CommandLineParser.hs @@ -13,6 +13,10 @@ defTarget = "x86_64-macos-none" defTarget = "aarch64-linux-gnu.2.27" #elif defined(linux_HOST_OS) && defined(x86_64_HOST_ARCH) defTarget = "x86_64-linux-gnu.2.27" +#elif defined(mingw32_HOST_OS) && defined(aarch64_HOST_ARCH) +defTarget = "aarch64-linux-gnu.2.27" +#elif defined(mingw32_HOST_OS) && defined(x86_64_HOST_ARCH) +defTarget = "x86_64-linux-gnu.2.27" #else #error "Unsupported platform" #endif @@ -208,6 +212,13 @@ data ZigPkgRemoveOptions = ZigPkgRemoveOptions -------------------------------------------------------------------- -- Internal stuff +fileCompleter :: String -> Mod ArgumentFields String +#if defined(mingw32_HOST_OS) +fileCompleter _ = mempty +#else +fileCompleter cmd = completer (bashCompleter cmd) +#endif + cmdLineParser :: Parser CmdLineOptions cmdLineParser = hsubparser ( command "new" (info (CmdOpt <$> globalOptions <*> (New <$> newOptions)) (progDesc "Create a new Acton project")) @@ -225,7 +236,7 @@ cmdLineParser = hsubparser <> command "doc" (info (CmdOpt <$> globalOptions <*> (Doc <$> docOptions)) (progDesc "Show type and docstring info")) <> command "version" (info (CmdOpt <$> globalOptions <*> pure Version) (progDesc "Show version")) ) - <|> (CompileOpt <$> (fmap (:[]) $ argument str (metavar "ACTONFILE" <> help "Compile Acton file" <> completer (bashCompleter "file -X '!*.act' -o plusdirs"))) <*> globalOptions <*> compileOptions) + <|> (CompileOpt <$> (fmap (:[]) $ argument str (metavar "ACTONFILE" <> help "Compile Acton file" <> fileCompleter "file -X '!*.act' -o plusdirs")) <*> globalOptions <*> compileOptions) globalOptions :: Parser GlobalOptions globalOptions = GlobalOptions @@ -455,7 +466,7 @@ cloudOptions = CloudOptions <*> switch (long "stop" <> help "Help stop!") docOptions = DocOptions - <$> (argument str (metavar "FILE" <> help "Input file (.act or .tydb) - optional in projects" <> completer (bashCompleter "file -X '!*.act' -X '!*.tydb' -o plusdirs")) <|> pure "") + <$> (argument str (metavar "FILE" <> help "Input file (.act or .tydb) - optional in projects" <> fileCompleter "file -X '!*.act' -X '!*.tydb' -o plusdirs") <|> pure "") <*> formatFlags <*> optional (strOption (long "output" <> short 'o' <> metavar "FILE" <> help "Output file (default: stdout)")) where diff --git a/compiler/lib/src/Acton/Compile.hs b/compiler/lib/src/Acton/Compile.hs index 99b9c5821..d7c379540 100644 --- a/compiler/lib/src/Acton/Compile.hs +++ b/compiler/lib/src/Acton/Compile.hs @@ -243,6 +243,7 @@ import qualified Data.Map as M import Data.Ord (Down(..)) import qualified Data.Set import Data.Time.Clock (UTCTime) +import Data.Time.Clock.POSIX (utcTimeToPOSIXSeconds) import Data.Word (Word8, Word32, Word64) import Error.Diagnose (Diagnostic) import GHC.Conc (getNumCapabilities) @@ -256,16 +257,17 @@ import System.Directory.Recursive (getFilesRecursive) import System.Environment (getExecutablePath, lookupEnv) import System.FileLock (FileLock, SharedExclusive(Exclusive), tryLockFile, unlockFile, withFileLock) import System.FilePath (()) -import System.FilePath.Posix +import System.FilePath.Posix hiding (()) import System.Exit (ExitCode(..)) import System.IO hiding (readFile, writeFile) import System.IO.Temp (createTempDirectory, withSystemTempDirectory) import System.IO.Unsafe (unsafePerformIO) +#if !defined(mingw32_HOST_OS) import System.Posix.Files (FileStatus, deviceID, fileID, fileSize, getFileStatus, modificationTimeHiRes, statusChangeTimeHiRes) +#endif import System.Process (CreateProcess(cwd), readCreateProcessWithExitCode, proc) import System.Random (randomRIO) -import Text.PrettyPrint (renderStyle, style, Style(..), Mode(PageMode)) -import Text.Show.Pretty (ppDoc) +import Text.PrettyPrint (renderStyle, style, Style(..), Mode(PageMode), text) import Text.Printf import qualified Data.ByteString as BS @@ -1066,6 +1068,17 @@ parseActFile opts sp mn actFile mOnProgress = do -- restores falls back to content hashing instead of blindly trusting mtimes. readSourceFileMeta :: FilePath -> IO InterfaceFiles.SourceFileMeta readSourceFileMeta path = do +#if defined(mingw32_HOST_OS) + mtimeNs <- fileModificationTimeNs path + size <- getFileSize path + return InterfaceFiles.SourceFileMeta + { InterfaceFiles.sfmMTimeNs = mtimeNs + , InterfaceFiles.sfmCTimeNs = mtimeNs + , InterfaceFiles.sfmSize = fromIntegral size + , InterfaceFiles.sfmDevice = Nothing + , InterfaceFiles.sfmInode = Nothing + } +#else st <- getFileStatus path let mtimeNs = fileStatusMTimeNs st ctimeNs = fileStatusCTimeNs st @@ -1079,6 +1092,19 @@ readSourceFileMeta path = do where fileStatusMTimeNs st = floor (toRational (modificationTimeHiRes st) * 1000000000) fileStatusCTimeNs st = floor (toRational (statusChangeTimeHiRes st) * 1000000000) +#endif + +fileModificationTimeNs :: FilePath -> IO Integer +#if defined(mingw32_HOST_OS) +fileModificationTimeNs path = + utcTimeToNs <$> getModificationTime path + where + utcTimeToNs = floor . (* (1000000000 :: Rational)) . toRational . utcTimeToPOSIXSeconds +#else +fileModificationTimeNs path = do + st <- getFileStatus path + return (floor (toRational (modificationTimeHiRes st) * 1000000000)) +#endif -- Compilation tasks, chasing imported modules, compilation and building executables ----------------- @@ -1318,7 +1344,7 @@ buildGlobalTasks sp gopts opts projMap mSeeds = do seedKeys <- case mSeeds of Nothing -> return allKeys Just files -> do - absFiles <- mapM canonicalizePath files + absFiles <- mapM normalizePathSafe files let pathIndex = M.fromList [ (actFile, TaskKey (projRoot ctx) mn) | (ctx, mods) <- perProj, (actFile, mn) <- mods ] found = mapMaybe (`M.lookup` pathIndex) absFiles return (if null found then allKeys else found) @@ -1366,7 +1392,7 @@ selectNeededTasks pathsRoot rootProj globalTasks srcFiles = do return [ t | t <- globalTasks, Data.Set.member (gtKey t) neededKeys ] where lookupTaskKey ts f = do - absF <- canonicalizePath f + absF <- normalizePathSafe f let byPath = listToMaybe [ gtKey t | t <- ts , let k = gtKey t @@ -1650,8 +1676,6 @@ readModuleHeader sp gopts opts paths actFile = do snap <- Source.spReadFile sp actFile verifyOrParse mn snap moduleSrcBytesHash modulePubHash moduleImplHash cachedSourceMeta (Just currentSourceMeta) imps nameHashes roots tests mdoc where - fileStatusMTimeNs st = floor (toRational (modificationTimeHiRes st) * 1000000000) - mkTyHead mn moduleSrcBytesHash modulePubHash moduleImplHash imps nameHashes roots tests mdoc = TyHead { mhName = mn @@ -1697,10 +1721,10 @@ readModuleHeader sp gopts opts paths actFile = do case exePathE of Left _ -> return False Right exePath -> do - exeStatusE <- (try (getFileStatus exePath) :: IO (Either SomeException FileStatus)) + exeStatusE <- (try (fileModificationTimeNs exePath) :: IO (Either SomeException Integer)) case exeStatusE of Left _ -> return False - Right exeStatus -> return (fileStatusMTimeNs exeStatus > tyMTimeNs) + Right exeMTimeNs -> return (exeMTimeNs > tyMTimeNs) refreshCachedSourceMeta currentSourceMeta = do let tyFilePath = tyDbPath paths (modName paths) @@ -2069,7 +2093,7 @@ runFrontPasses gopts opts dbpBlocked paths env0 parsed srcContent srcBytes sourc when (C.parse opts && isRoot) $ dump mn "parse" (Pretty.print parsed) when (C.parse_ast opts && isRoot) $ - dump mn "parse-ast" (renderStyle prettyAstStyle (ppDoc parsed)) + dump mn "parse-ast" (renderStyle prettyAstStyle (text (show parsed))) typeStmtTimingsRef <- newIORef ([] :: [TypeStmtTiming]) inferredSigsRef <- newIORef ([] :: [InferredSignature]) @@ -3693,6 +3717,13 @@ systemTypePaths :: FilePath -> FilePath -> [FilePath] systemTypePaths sys types = [joinPath [sys, "std", "out", "types"], types] +zigExeName :: FilePath +#if defined(mingw32_HOST_OS) +zigExeName = "zig.exe" +#else +zigExeName = "zig" +#endif + type FingerprintMap = M.Map String FilePath scratchBuildSpec :: FilePath -> BuildSpec.BuildSpec @@ -3918,9 +3949,10 @@ withProjectLock projDir action = -- Resolves the project root (or temp root), output dirs, and search path, -- creating required directories along the way. findPaths :: FilePath -> C.CompileOptions -> IO Paths -findPaths actFile opts = do execDir <- takeDirectory <$> getExecutablePath - sysPath <- canonicalizePath (if null $ C.syspath opts then execDir ++ "/.." else C.syspath opts) - absSrcFile <- canonicalizePath actFile +findPaths actFile opts = do execPath <- normalisePathSyntax <$> getExecutablePath + let execDir = takeDirectory execPath + sysPath <- canonicalizePathPosix (if null $ C.syspath opts then execDir ++ "/.." else C.syspath opts) + absSrcFile <- canonicalizePathPosix actFile (isTmp, projPath, dirInSrc) <- analyze (takeDirectory absSrcFile) [] let sysTypes = joinPath [sysPath, "base", "out", "types"] srcDir = if isTmp then takeDirectory absSrcFile else joinPath [projPath, "src"] @@ -3939,16 +3971,19 @@ findPaths actFile opts = do execDir <- takeDirectory <$> getExecutablePath return $ Paths sPaths sysPath sysTypes projPath projOut projTypes binDir srcDir isTmp fileExt modName where (fileBody,fileExt) = splitExtension $ takeFileName actFile - analyze "/" ds = do tmp <- canonicalizePath (C.tempdir opts) - return (True, tmp, []) - analyze pre ds = do isProjectRoot <- isActonProjectRoot pre - if isProjectRoot - then case ds of - [] -> return $ (False, pre, []) - "src":dirs -> return $ (False, pre, dirs) - "out":"types":dirs -> return $ (False, pre, dirs) - _ -> throwProjectError ("Source file is not in a valid project directory: " ++ joinPath ds) - else analyze (takeDirectory pre) (takeFileName pre : ds) + analyze pre ds + | pre == takeDirectory pre = do + tmp <- canonicalizePathPosix (C.tempdir opts) + return (True, tmp, []) + | otherwise = do + isProjectRoot <- isActonProjectRoot pre + if isProjectRoot + then case ds of + [] -> return $ (False, pre, []) + "src":dirs -> return $ (False, pre, dirs) + "out":"types":dirs -> return $ (False, pre, dirs) + _ -> throwProjectError ("Source file is not in a valid project directory: " ++ joinPath ds) + else analyze (takeDirectory pre) (takeFileName pre : ds) -- Module helpers for multi-project builds --------------------------------------------------------- @@ -4185,12 +4220,24 @@ isAbsolutePath p = (c:':':_) -> isAlpha c _ -> False +-- This module intentionally uses POSIX FilePath operations for Acton module +-- paths. Canonical paths from Windows use backslashes, so normalize them at the +-- boundary before takeDirectory, makeRelative, splitDirectories, etc. see them. +normalisePathSyntax :: FilePath -> FilePath +normalisePathSyntax = normalise . map slash + where + slash '\\' = '/' + slash c = c + +canonicalizePathPosix :: FilePath -> IO FilePath +canonicalizePathPosix p = normalisePathSyntax <$> canonicalizePath p + -- | Normalize a path without failing if it does not exist. -- Falls back to normalise for non-existent paths (useful for temporary builds). normalizePathSafe :: FilePath -> IO FilePath normalizePathSafe p = do res <- try (canonicalizePath p) :: IO (Either IOException FilePath) - return $ either (const (normalise p)) id res + return $ normalisePathSyntax (either (const p) id res) -- | Trim leading and trailing whitespace from a string. -- Used when parsing or normalizing BuildSpec inputs. @@ -4278,7 +4325,7 @@ fetchDependencies gopts paths depOverrides = do unless (C.quiet gopts) $ putStrLn "Resolving dependencies (fetching if missing)..." home <- getHomeDirectory - let zigExe = joinPath [sysPath paths, "zig", "zig"] + let zigExe = joinPath [sysPath paths, "zig", zigExeName] globalCache = joinPath [home, ".cache", "acton", "zig-global-cache"] depsCache = joinPath [home, ".cache", "acton", "deps"] cacheDir h = joinPath [globalCache, "p", h] diff --git a/compiler/lib/src/InterfaceFiles.hs b/compiler/lib/src/InterfaceFiles.hs index 0670354b5..0be20e8c8 100644 --- a/compiler/lib/src/InterfaceFiles.hs +++ b/compiler/lib/src/InterfaceFiles.hs @@ -11,7 +11,7 @@ -- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -- -{-# LANGUAGE DeriveGeneric, ScopedTypeVariables #-} +{-# LANGUAGE CPP, DeriveGeneric, ScopedTypeVariables #-} -- Acton Interface (.tydb) Files -- -- Purpose @@ -109,17 +109,20 @@ import qualified Data.ByteString.Lazy as BL import qualified Data.Text as T import qualified Data.Text.Encoding as TE import Data.Time.Clock (UTCTime) +import Data.Time.Clock.POSIX (utcTimeToPOSIXSeconds) import qualified Database.LMDB.Raw as LMDB import qualified Acton.Syntax as A import qualified Acton.NameInfo as I import Foreign.Ptr (castPtr) import Foreign.Storable (peek) import GHC.Generics (Generic) -import System.Directory (canonicalizePath, createDirectoryIfMissing, doesDirectoryExist, doesFileExist, getFileSize, getModificationTime, listDirectory, removeFile, removePathForcibly) -import System.FilePath ((), takeExtension) -import System.IO.Error (isDoesNotExistError) +import System.Directory (canonicalizePath, createDirectoryIfMissing, doesDirectoryExist, doesFileExist, getFileSize, getModificationTime, getPermissions, listDirectory, removeFile, removePathForcibly, writable) +import System.FilePath ((), normalise, takeExtension) +import System.IO.Error (ioeGetErrorString, isDoesNotExistError) import System.IO.Unsafe (unsafePerformIO) +#if !defined(mingw32_HOST_OS) import System.Posix.Files (fileAccess, getFileStatus, modificationTimeHiRes, setFileMode) +#endif data NameHashInfo = NameHashInfo { nhName :: A.Name @@ -218,8 +221,13 @@ interfaceModifiedTime path = getModificationTime (dataFilePath path) interfaceModifiedTimeNs :: FilePath -> IO Integer interfaceModifiedTimeNs path = do +#if defined(mingw32_HOST_OS) + time <- getModificationTime (dataFilePath path) + return (utcTimeToNs time) +#else st <- getFileStatus (dataFilePath path) return (floor (toRational (modificationTimeHiRes st) * 1000000000)) +#endif copyInterface :: FilePath -> FilePath -> IO () copyInterface src dst = do @@ -342,9 +350,10 @@ copyVal (LMDB.MDB_val len ptr) = withEnv :: FilePath -> Bool -> Int -> (LMDB.MDB_env -> IO a) -> IO a withEnv path readOnly mapSize action = - withInterfaceLock path $ + withInterfaceLock lmdbPath $ E.bracket open LMDB.mdb_env_close action where + lmdbPath = normalise path open = withMVar lmdbOpenLock $ \_ -> openWithRetry envOpenMaxAttempts -- Concurrent opens of the same env race on lock.mdb setup, which surfaces as -- a transient OS-level mdb_env_open failure (e.g. ENOENT) that resolves on @@ -363,9 +372,17 @@ withEnv path readOnly mapSize action = | otherwise -> E.throwIO err openEnv env | readOnly = do - flags <- readOnlyOpenFlags path - LMDB.mdb_env_open env path flags - | otherwise = LMDB.mdb_env_open env path [] + exists <- doesDirectoryExist lmdbPath + unless exists $ + ioError (userError ("Missing .tydb directory: " ++ lmdbPath)) + flags <- readOnlyOpenFlags lmdbPath + openWithContext env "read" flags + | otherwise = do + createDirectoryIfMissing True lmdbPath + openWithContext env "write" [] + openWithContext env mode flags = + LMDB.mdb_env_open env lmdbPath flags `E.catch` \(err :: LMDB.LMDB_Error) -> + ioError (userError ("mdb_env_open " ++ mode ++ " " ++ lmdbPath ++ ": " ++ show err)) -- A transient env-open failure is an OS-level error (Either Left, a raw errno) -- from a concurrent lock.mdb setup race -- retrying succeeds once the winning @@ -396,8 +413,8 @@ canUseLockFile path = do let lockPath = lockFilePath path exists <- doesFileExist lockPath if exists - then fileAccess lockPath False True False - else fileAccess path False True True + then canWritePath lockPath False + else canWritePath path True canReadWithoutLock :: FilePath -> IO Bool canReadWithoutLock path = do @@ -406,10 +423,18 @@ canReadWithoutLock path = do if not exists then return False else do - dataWritable <- fileAccess dataPath False True False - dirWritable <- fileAccess path False True True + dataWritable <- canWritePath dataPath False + dirWritable <- canWritePath path True return (not dataWritable && not dirWritable) +canWritePath :: FilePath -> Bool -> IO Bool +#if defined(mingw32_HOST_OS) +canWritePath path _ = + (writable <$> getPermissions path) `E.catch` \(_ :: E.IOException) -> return False +#else +canWritePath path searchable = fileAccess path False True searchable +#endif + envOpenMaxAttempts :: Int envOpenMaxAttempts = 5 @@ -522,13 +547,28 @@ isCorruptEnv :: E.SomeException -> Bool isCorruptEnv err = case E.fromException err of Just LMDB.LMDB_Error{ LMDB.e_code = Right code } -> - code `elem` [ LMDB.MDB_PAGE_NOTFOUND - , LMDB.MDB_CORRUPTED - , LMDB.MDB_PANIC - , LMDB.MDB_VERSION_MISMATCH - , LMDB.MDB_INVALID - ] - _ -> False + code `elem` corruptEnvCodes + _ | Just ioErr <- E.fromException err -> + hasCorruptEnvMarker (ioeGetErrorString ioErr) || hasCorruptEnvMarker (show err) + | otherwise -> hasCorruptEnvMarker (show err) + where + hasCorruptEnvMarker s = + any (`Data.List.isInfixOf` s) corruptEnvMarkers + corruptEnvCodes = + [ LMDB.MDB_PAGE_NOTFOUND + , LMDB.MDB_CORRUPTED + , LMDB.MDB_PANIC + , LMDB.MDB_VERSION_MISMATCH + , LMDB.MDB_INVALID + ] + corruptEnvMarkers = + map show corruptEnvCodes ++ + [ "MDB_PAGE_NOTFOUND" + , "MDB_CORRUPTED" + , "MDB_PANIC" + , "MDB_VERSION_MISMATCH" + , "MDB_INVALID" + ] writeEntries :: FilePath -> [(BS.ByteString, BS.ByteString)] -> IO () writeEntries path entries = do @@ -553,6 +593,9 @@ writeEntries path entries = do Left (err :: E.SomeException) -> E.throwIO err setReadableInterfacePermissions :: FilePath -> IO () +#if defined(mingw32_HOST_OS) +setReadableInterfacePermissions _ = return () +#else setReadableInterfacePermissions path = do setFileMode path 0o755 setFileMode (dataFilePath path) 0o644 @@ -564,6 +607,10 @@ setReadableInterfacePermissions path = do if isDoesNotExistError err then return () else E.throwIO (err :: E.IOException) +#endif + +utcTimeToNs :: UTCTime -> Integer +utcTimeToNs = floor . (* (1000000000 :: Rational)) . toRational . utcTimeToPOSIXSeconds validateVersion :: LMDB.MDB_txn -> LMDB.MDB_dbi -> IO () validateVersion txn dbi = do @@ -757,6 +804,7 @@ tyCacheMiss err isTyCacheMiss :: E.SomeException -> Bool isTyCacheMiss err | Just (_ :: TyCacheInvalid) <- E.fromException err = True - | Just (ioe :: E.IOException) <- E.fromException err = isDoesNotExistError ioe + | Just (ioe :: E.IOException) <- E.fromException err = + isDoesNotExistError ioe || isCorruptEnv err | isCorruptEnv err = True | otherwise = False diff --git a/compiler/lib/src/Utils.hs b/compiler/lib/src/Utils.hs index e4962a564..a30103831 100644 --- a/compiler/lib/src/Utils.hs +++ b/compiler/lib/src/Utils.hs @@ -25,8 +25,8 @@ import SrcLocation import Pretty import Control.DeepSeq import Prelude hiding((<>)) -import System.Directory (renameFile, removeFile) -import System.FilePath (takeDirectory, takeFileName) +import System.Directory (createDirectoryIfMissing, renameFile, removeFile) +import System.FilePath (normalise, takeDirectory, takeFileName) import System.IO (openTempFile, hSetEncoding, utf8, hPutStr, hClose) import System.IO.Error (catchIOError) @@ -173,7 +173,8 @@ iff False _ = return () -- | Write a UTF-8 text file atomically (temp file + rename). -- Keeps readers from observing partial writes of generated artifacts. writeFileUtf8Atomic :: FilePath -> String -> IO () -writeFileUtf8Atomic path contents = +writeFileUtf8Atomic path contents = do + createDirectoryIfMissing True dir Control.Exception.bracketOnError (openTempFile dir template) (\(tmp, h) -> do @@ -183,7 +184,8 @@ writeFileUtf8Atomic path contents = hSetEncoding h utf8 hPutStr h contents hClose h - renameFile tmp path) + renameFile tmp path') where - dir = takeDirectory path - template = takeFileName path ++ ".tmp" + path' = normalise path + dir = takeDirectory path' + template = takeFileName path' ++ ".tmp" diff --git a/compiler/stack-windows.yaml b/compiler/stack-windows.yaml new file mode 100644 index 000000000..99731f175 --- /dev/null +++ b/compiler/stack-windows.yaml @@ -0,0 +1,34 @@ +# Windows builds use the same package plan as stack.yaml, but omit the broad +# -fPIC workaround that Unix builds need for static linking. +snapshot: lts-23.28 + +packages: +- diagnose +- lib +- acton +- lsp-server + +extra-deps: + - Cabal-3.10.3.0 + - Cabal-syntax-3.10.3.0 + - dir-traverse-0.2.3.0 + - directory-1.3.8.5 + - filepath-1.4.300.1 + - fsnotify-0.3.0.1@sha256:58bb530d7acf93eb4ed69473e32a1485581815f04f69dfc8a278523781ba49dd,2988 + - haskeline-0.8.4.1@sha256:349296dd2e58dc9d2daabaa3fcacc2de9af5828ce8491c07f3f392ae65a98f7a,6178 + - lsp-2.7.0.0 + - lsp-types-2.3.0.0 + - parsec-3.1.17.0@sha256:8407cbd428d7f640a0fff8891bd2f7aca13cebe70a5e654856f8abec9a648b56 + - process-1.6.19.0 + - tasty-1.5.3 + - time-1.12.2 + - unix-2.8.2.1 + - Win32-2.14.2.2 + +extra-include-dirs: + - ../bdeps/out/include +extra-lib-dirs: + - ../bdeps/out/lib + +ghc-options: + lsp-types: -O0 -fexternal-interpreter diff --git a/compiler/stack-windows.yaml.lock b/compiler/stack-windows.yaml.lock new file mode 100644 index 000000000..b81ba6bc7 --- /dev/null +++ b/compiler/stack-windows.yaml.lock @@ -0,0 +1,117 @@ +# This file was autogenerated by Stack. +# You should not edit this file by hand. +# For more information, please see the documentation at: +# https://docs.haskellstack.org/en/stable/lock_files + +packages: +- completed: + hackage: Cabal-3.10.3.0@sha256:4a36954a66769eef90353daa0dbb07d43e49c228281383c7e4134445d495f714,12313 + pantry-tree: + sha256: 1d8835f47d5a86a326a4997ce77f7bfd78d732a483264deaf0c280e8d2b764b7 + size: 9222 + original: + hackage: Cabal-3.10.3.0 +- completed: + hackage: Cabal-syntax-3.10.3.0@sha256:5904508da905b34d995a704a86970de489cc4495dd981b1cfe5fb5baa2bde71b,7672 + pantry-tree: + sha256: 9fc66c9d0e6d487de26a25453a9b87631871e77e0250456a28b2bc87aff4c569 + size: 11052 + original: + hackage: Cabal-syntax-3.10.3.0 +- completed: + hackage: dir-traverse-0.2.3.0@sha256:adcc128f201ff95131b15ffe41365dc99c50dc3fa3a910f021521dc734013bfa,2137 + pantry-tree: + sha256: b19f0562746dfd0f8f21eccab6584592f55fb781ca3e043da9132cc23d8a5b99 + size: 389 + original: + hackage: dir-traverse-0.2.3.0 +- completed: + hackage: directory-1.3.8.5@sha256:350b29864672fa542e4cb44cc95c3044ecd402120cec95688c67f3cc7e4d1e13,3306 + pantry-tree: + sha256: 43417bdb1ef5a12cc3543349707ac9f4c35a94eda692344781bcbf02eaeb5610 + size: 3519 + original: + hackage: directory-1.3.8.5 +- completed: + hackage: filepath-1.4.300.1@sha256:d9e181e1acae0ac505d8b217dec3805c68554878f1e32b3d8351b9ce17061623,5900 + pantry-tree: + sha256: c84b787da2ee47ab8e50cfe37c6419ff9bb97ae69d92991178a7dc052c452b58 + size: 3998 + original: + hackage: filepath-1.4.300.1 +- completed: + hackage: fsnotify-0.3.0.1@sha256:58bb530d7acf93eb4ed69473e32a1485581815f04f69dfc8a278523781ba49dd,2988 + pantry-tree: + sha256: 8d1a410d34fd77e9b6603c9d1a940d7de63a85c852dbde467c0ef38c82ef6ea0 + size: 1130 + original: + hackage: fsnotify-0.3.0.1@sha256:58bb530d7acf93eb4ed69473e32a1485581815f04f69dfc8a278523781ba49dd,2988 +- completed: + hackage: haskeline-0.8.4.1@sha256:349296dd2e58dc9d2daabaa3fcacc2de9af5828ce8491c07f3f392ae65a98f7a,6178 + pantry-tree: + sha256: 43b5325128eea82943bc0f9dbaf4f19c9e6af26dcce571938459313c7fc7e6b1 + size: 2968 + original: + hackage: haskeline-0.8.4.1@sha256:349296dd2e58dc9d2daabaa3fcacc2de9af5828ce8491c07f3f392ae65a98f7a,6178 +- completed: + hackage: lsp-2.7.0.0@sha256:cec57fe8924368ab3f431726b0ca0c9d76fad025161fc3d2fde71ed814d0bf7e,3998 + pantry-tree: + sha256: 93f62225c8d50459fb05346630aaf3934d7a4000dcfe5109e7ff45d94d8a283f + size: 1120 + original: + hackage: lsp-2.7.0.0 +- completed: + hackage: lsp-types-2.3.0.0@sha256:ca17a686bda5dc7ff04105ca7081dce5a90bcd050c8800a13efd68b7f0901f1c,34215 + pantry-tree: + sha256: 0bf22e394dc804c8cee74d19a7f38021cfd48a15082b39a14753c037f2a64288 + size: 51996 + original: + hackage: lsp-types-2.3.0.0 +- completed: + hackage: parsec-3.1.17.0@sha256:8407cbd428d7f640a0fff8891bd2f7aca13cebe70a5e654856f8abec9a648b56,5149 + pantry-tree: + sha256: 0922d72bd7115bbb590757bd92a827021dfe745ed6c0cd22856f767bee83d91f + size: 2810 + original: + hackage: parsec-3.1.17.0@sha256:8407cbd428d7f640a0fff8891bd2f7aca13cebe70a5e654856f8abec9a648b56 +- completed: + hackage: process-1.6.19.0@sha256:807bfa9b4038b59ae0c362bd94a783f898fbe0b42dbe1f2ede3c392bf2b8727d,3148 + pantry-tree: + sha256: bf6056cc0e82ed9d85ab01ab57aea03c2202677a2c3015b686eb20993407816b + size: 1675 + original: + hackage: process-1.6.19.0 +- completed: + hackage: tasty-1.5.3@sha256:6b5dda3f16db1274a0b3e6c4073ac57172a1e96b1dca05666c5cbd1183639412,2923 + pantry-tree: + sha256: 55cabcd98ff0f5c671a93fb138b8b8cb1cf223497b0fbf9207e6c519fd54a9e9 + size: 1944 + original: + hackage: tasty-1.5.3 +- completed: + hackage: time-1.12.2@sha256:88e8493d9130038d3b9968a2530a0900141cd3d938483c83dde56e12b875ebc8,6510 + pantry-tree: + sha256: de0ab314661da3788b5dad20254e44929b1659b00d32b5a0cd54922a05e006e8 + size: 7264 + original: + hackage: time-1.12.2 +- completed: + hackage: unix-2.8.2.1@sha256:433396e6087bbe6433ea4a743600bddd29d0e6cd701ea688d6d637ebae7b7bac,9318 + pantry-tree: + sha256: 1be1c56da093b0db76374ed0692109a8ebb7a0e5a44b660d186ac759e2b5bd94 + size: 5752 + original: + hackage: unix-2.8.2.1 +- completed: + hackage: Win32-2.14.2.2@sha256:534f6273a3a61162747111bb5cbdda7f04081971083c69ed4562eb34c744d845,5877 + pantry-tree: + sha256: 726de3917a588afc73c0af619b5280594fa22409fc871e20ad7b2b16e0402e9c + size: 8301 + original: + hackage: Win32-2.14.2.2 +snapshots: +- completed: + sha256: 7e724f347d5969cb5e8dde9f9aae30996e3231c29d1dafd45f21f1700d4c4fcb + size: 684460 + url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/23/28.yaml + original: lts-23.28 diff --git a/deps/libargp/build.zig.zon b/deps/libargp/build.zig.zon new file mode 100644 index 000000000..8f7872ce2 --- /dev/null +++ b/deps/libargp/build.zig.zon @@ -0,0 +1,8 @@ +.{ + .name = .libargp, + .version = "0.0.0", + .fingerprint = 0xb32523545ff94c96, + .minimum_zig_version = "0.16.0", + .dependencies = .{}, + .paths = .{""}, +} diff --git a/deps/libbsdnt/build.zig.zon b/deps/libbsdnt/build.zig.zon new file mode 100644 index 000000000..ad82e3ae0 --- /dev/null +++ b/deps/libbsdnt/build.zig.zon @@ -0,0 +1,8 @@ +.{ + .name = .libbsdnt, + .version = "0.0.0", + .fingerprint = 0xc0c476554a015af3, + .minimum_zig_version = "0.16.0", + .dependencies = .{}, + .paths = .{""}, +} diff --git a/deps/libgc/build.zig.zon b/deps/libgc/build.zig.zon new file mode 100644 index 000000000..0e2025981 --- /dev/null +++ b/deps/libgc/build.zig.zon @@ -0,0 +1,8 @@ +.{ + .name = .libgc, + .version = "0.0.0", + .fingerprint = 0x699a07146c24bd98, + .minimum_zig_version = "0.16.0", + .dependencies = .{}, + .paths = .{""}, +} diff --git a/deps/libnetstring/build.zig.zon b/deps/libnetstring/build.zig.zon new file mode 100644 index 000000000..66fb922ff --- /dev/null +++ b/deps/libnetstring/build.zig.zon @@ -0,0 +1,8 @@ +.{ + .name = .libnetstring, + .version = "0.0.0", + .fingerprint = 0x93f788cd241fc695, + .minimum_zig_version = "0.16.0", + .dependencies = .{}, + .paths = .{""}, +} diff --git a/deps/libprotobuf_c/build.zig.zon b/deps/libprotobuf_c/build.zig.zon new file mode 100644 index 000000000..7b1405cce --- /dev/null +++ b/deps/libprotobuf_c/build.zig.zon @@ -0,0 +1,8 @@ +.{ + .name = .libprotobuf_c, + .version = "0.0.0", + .fingerprint = 0xfcfd7b442ded66a4, + .minimum_zig_version = "0.16.0", + .dependencies = .{}, + .paths = .{""}, +} diff --git a/deps/libsnappy_c/build.zig.zon b/deps/libsnappy_c/build.zig.zon new file mode 100644 index 000000000..34f155188 --- /dev/null +++ b/deps/libsnappy_c/build.zig.zon @@ -0,0 +1,8 @@ +.{ + .name = .libsnappy, + .version = "0.0.0", + .fingerprint = 0xf5ea7e597512b0cd, + .minimum_zig_version = "0.16.0", + .dependencies = .{}, + .paths = .{""}, +} diff --git a/deps/libutf8proc/build.zig.zon b/deps/libutf8proc/build.zig.zon new file mode 100644 index 000000000..dc617fee9 --- /dev/null +++ b/deps/libutf8proc/build.zig.zon @@ -0,0 +1,8 @@ +.{ + .name = .libutf8proc, + .version = "0.0.0", + .fingerprint = 0xd7d11c6f6da16d6b, + .minimum_zig_version = "0.16.0", + .dependencies = .{}, + .paths = .{""}, +} diff --git a/deps/libuuid/build.zig.zon b/deps/libuuid/build.zig.zon new file mode 100644 index 000000000..018aea66b --- /dev/null +++ b/deps/libuuid/build.zig.zon @@ -0,0 +1,8 @@ +.{ + .name = .libuuid, + .version = "0.0.0", + .fingerprint = 0xed480ceafcee79e1, + .minimum_zig_version = "0.16.0", + .dependencies = .{}, + .paths = .{""}, +} diff --git a/deps/libuv/build.zig.zon b/deps/libuv/build.zig.zon new file mode 100644 index 000000000..a42920e07 --- /dev/null +++ b/deps/libuv/build.zig.zon @@ -0,0 +1,8 @@ +.{ + .name = .libuv, + .version = "0.0.0", + .fingerprint = 0x7cb3932c5d4cacd6, + .minimum_zig_version = "0.16.0", + .dependencies = .{}, + .paths = .{""}, +} diff --git a/deps/libxml2/build.zig.zon b/deps/libxml2/build.zig.zon new file mode 100644 index 000000000..938c60c00 --- /dev/null +++ b/deps/libxml2/build.zig.zon @@ -0,0 +1,8 @@ +.{ + .name = .libxml2, + .version = "0.0.0", + .fingerprint = 0xf268267bf50b038e, + .minimum_zig_version = "0.16.0", + .dependencies = .{}, + .paths = .{""}, +} diff --git a/deps/libyyjson/build.zig.zon b/deps/libyyjson/build.zig.zon new file mode 100644 index 000000000..4710d4a81 --- /dev/null +++ b/deps/libyyjson/build.zig.zon @@ -0,0 +1,8 @@ +.{ + .name = .libyyjson, + .version = "0.0.0", + .fingerprint = 0x1d7fa4acd6e9645e, + .minimum_zig_version = "0.16.0", + .dependencies = .{}, + .paths = .{""}, +} diff --git a/deps/mbedtls/build.zig.zon b/deps/mbedtls/build.zig.zon new file mode 100644 index 000000000..372994cde --- /dev/null +++ b/deps/mbedtls/build.zig.zon @@ -0,0 +1,8 @@ +.{ + .name = .libmbedtls, + .version = "0.0.0", + .fingerprint = 0x5328c30da4ecbb1f, + .minimum_zig_version = "0.16.0", + .dependencies = .{}, + .paths = .{""}, +} diff --git a/deps/pcre2/build.zig.zon b/deps/pcre2/build.zig.zon new file mode 100644 index 000000000..5a713fa2b --- /dev/null +++ b/deps/pcre2/build.zig.zon @@ -0,0 +1,8 @@ +.{ + .name = .libpcre2, + .version = "0.0.0", + .fingerprint = 0xee1d0784457618a7, + .minimum_zig_version = "0.16.0", + .dependencies = .{}, + .paths = .{""}, +}