diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 00000000..e8ac4ff2 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,122 @@ +name: CI + +on: [push, pull_request] + +env: + PREVIOUS_CRYSTAL_VERSION: 1.6.0 + CRYSTAL_VERSION: 1.6.2 + PACKAGE_VERSION: 1 + +jobs: + linux-build: + # TODO: set architecture based off matrix value when ARM runner available + name: Build linux binaries + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + architecture: + - x86_64 + - aarch64 + steps: + - + name: Checkout the distribution scripts + uses: actions/checkout@v3 + + - + name: Cache Docker layers + uses: actions/cache@v3 + with: + path: /tmp/.buildx-cache + key: ${{ runner.os }}-buildx-${{ github.sha }} + restore-keys: | + ${{ runner.os }}-buildx- + + - + name: Set up QEMU + uses: docker/setup-qemu-action@v2 + + - + name: Build the linux binaries + run: | + cd linux + make \ + arch=${{ matrix.architecture }} \ + CRYSTAL_VERSION=${{ env.CRYSTAL_VERSION }} \ + PACKAGE_VERSION=${{ env.PACKAGE_VERSION }} \ + PREVIOUS_CRYSTAL_VERSION=${{ env.PREVIOUS_CRYSTAL_VERSION }} + + - + name: Upload the binaries for use in the next step + uses: actions/upload-artifact@v3 + with: + name: linux-${{ env.CRYSTAL_VERSION }}-{{ matrix.architecture }}-${{ env.PACKAGE_VERSION }} + path: linux/build/*.gz + + + docker-build: + name: Build and test the docker images + runs-on: ubuntu-latest + needs: linux-build + strategy: + fail-fast: false + matrix: + architecture: + - x86_64 + - aarch64 + steps: + - + name: Checkout the distribution scripts + uses: actions/checkout@v3 + + - + name: Download the linux binaries + uses: actions/download-artifact@v3 + with: + name: linux-${{ env.CRYSTAL_VERSION }}-{{ matrix.architecture }}-${{ env.PACKAGE_VERSION }} + path: docker/build-context + + - + name: Cache Docker layers + uses: actions/cache@v3 + with: + path: /tmp/.buildx-cache + key: ${{ runner.os }}-buildx-${{ github.sha }} + restore-keys: | + ${{ runner.os }}-buildx- + + - + name: Set up QEMU + uses: docker/setup-qemu-action@v2 + + - + name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + + - + name: Build the docker image + run: | + cd docker + make \ + arch=${{ matrix.architecture }} \ + CRYSTAL_VERSION=${{ env.CRYSTAL_VERSION }} \ + PACKAGE_VERSION=${{ env.PACKAGE_VERSION }} \ + + - + name: Ensure images are well formed + run: | + # NOTE: Hack for GHA + sudo mkdir -p /var/lib/docker/tmp + + cd docker + make test \ + arch=${{ matrix.architecture }} \ + CRYSTAL_VERSION=${{ env.CRYSTAL_VERSION }} \ + PACKAGE_VERSION=${{ env.PACKAGE_VERSION }} + + - + name: Upload the docker images + uses: actions/upload-artifact@v3 + with: + name: docker-crystal-${{ env.CRYSTAL_VERSION }}-${{ env.PACKAGE_VERSION }}-{{ matrix.architecture }} + path: docker/build/*.gz diff --git a/.gitignore b/.gitignore index 23754b45..cb461ec0 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,8 @@ omnibus/bin omnibus/crystal-darwin-* omnibus/shards-darwin-* +build + docs/build/ darwin/build/ diff --git a/darwin/Makefile b/darwin/Makefile index 0729b874..f924b3c8 100644 --- a/darwin/Makefile +++ b/darwin/Makefile @@ -8,7 +8,12 @@ CRYSTAL_SHA1 ?= $(CRYSTAL_VERSION) ## Git tag/branch/sha1 to checkout and build PACKAGE_ITERATION ?= 1 FORCE_GIT_TAGGED ?= 1 ## Require build to be based on git tag/branch -PREVIOUS_CRYSTAL_RELEASE_DARWIN_TARGZ ?= ## url to crystal-{version}-{package}-darwin-x86_64.tar.gz +PREVIOUS_CRYSTAL_VERSION ?= ## Version of the bootstrap compiler +PREVIOUS_PACKAGE_ITERATION ?= 1## Package iteration of the bootstrap compiler + +CRYSTAL_REPOSITORY ?= crystal-lang/crystal + +PREVIOUS_CRYSTAL_RELEASE_DARWIN_TARGZ ?= https://github.com/$(CRYSTAL_REPOSITORY)/releases/download/$(PREVIOUS_CRYSTAL_VERSION)/crystal-$(PREVIOUS_CRYSTAL_VERSION)-$(PREVIOUS_PACKAGE_ITERATION)-darwin-universal.tar.gz## Url to crystal-{version}-{package}-darwin-universal.tar.gz OUTPUT_DIR = build @@ -49,10 +54,11 @@ $(CURDIR)/../omnibus/crystal-darwin-x86_64/embedded/bin/crystal: && rm /tmp/crystal-darwin-x86_64.tar.gz \ && chmod +x $(CURDIR)/../omnibus/crystal-darwin-x86_64/embedded/bin/crystal +# TODO: Shallow clone $(OUTPUT_DIR)/$(DARWIN_NAME) $(OUTPUT_DIR)/$(DARWIN_PKG_NAME): ## Build omnibus crystal project ifeq ($(FORCE_GIT_TAGGED), 0) rm -Rf $(CURDIR)/tmp && mkdir -p $(CURDIR)/tmp && cd $(CURDIR)/tmp \ - && git clone https://github.com/crystal-lang/crystal \ + && git clone https://github.com/$(CRYSTAL_REPOSITORY) \ && cd crystal \ && git checkout $(CRYSTAL_SHA1) \ && git checkout -b $(CRYSTAL_VERSION) diff --git a/docker/Makefile b/docker/Makefile index 152a48d8..e177126c 100644 --- a/docker/Makefile +++ b/docker/Makefile @@ -1,78 +1,127 @@ # Recipies for this Makefile -## Build all docker images -## $ make DOCKER_TAG=nightly CRYSTAL_VERSION=0.xy.z CRYSTAL_DEB=... CRYSTAL_TARGZ=... -## Build ubuntu64 docker images -## $ make ubuntu64 DOCKER_TAG=nightly CRYSTAL_VERSION=0.xy.z CRYSTAL_TARGZ=... -## Build alpine docker images -## $ make alpine DOCKER_TAG=nightly CRYSTAL_VERSION=0.xy.z CRYSTAL_TARGZ=... +## Build all docker images for x86_64 +## $ make arch=x86_64 DOCKER_TAG=nightly CRYSTAL_VERSION=0.xy.z CRYSTAL_TARGZ=... +## Build all docker images for aarch64 +## $ make arch=aarch64 DOCKER_TAG=nightly CRYSTAL_VERSION=0.xy.z CRYSTAL_TARGZ=... +## Build ubuntu docker images for x86_64 +## $ make ubuntu arch=x86_64 DOCKER_TAG=nightly CRYSTAL_VERSION=0.xy.z CRYSTAL_TARGZ=... +## Build alpine docker images for aarch64 +## $ make alpine arch=aarch64 DOCKER_TAG=nightly CRYSTAL_VERSION=0.xy.z CRYSTAL_TARGZ=... + +arch ?= ## Architecture to build for (x86_64, aarch64) +no_cache ?= ## Disable the docker build cache +pull_images ?= ## Always pull docker images to ensure they're up to date CRYSTAL_VERSION ?= ## How the binaries should be branded -CRYSTAL_DEB ?= ## Which crystal.deb file to install in debian based docker images (ubuntu32) -CRYSTAL_TARGZ ?= ## Which crystal.tar.gz file to install in docker images (ubuntu64, alpine) -DOCKER_TAG ?= $(CRYSTAL_VERSION) ## How to tag the docker image (examples: `0.27.2`, `nightly20190307`). `-build` will be appended for build images. -DOCKER_REPOSITORY ?= crystallang/crystal ## Docker hub repository to commit image +PACKAGE_ITERATION ?= 1 +PACKAGE_MAINTAINER = Crystal Team -GC_VERSION = v8.2.0 +DOCKER_TAG ?= $(CRYSTAL_VERSION)## How to tag the docker image (examples: `0.27.2`, `nightly20190307`). `-build` will be appended for build images. +DOCKER_REPOSITORY ?= crystallang/crystal## Docker hub repository to commit image + +GC_VERSION = v8.2.2 + +ifeq ($(arch),x86_64) + DOCKER_BUILD_PLATFORM = linux/amd64 +else ifeq ($(arch),aarch64) + DOCKER_BUILD_PLATFORM = linux/arm64 +else + $(error Expected arch to be one of 'x86_64', or 'aarch64', got: $(arch)) +endif + +BASE_UBUNTU_DOCKER_IMAGE = ubuntu:focal OUTPUT_DIR := build + BUILD_CONTEXT := $(CURDIR)/build-context -BUILD_ARGS_UBUNTU64 := --build-arg crystal_targz=crystal.tar.gz $(BUILD_CONTEXT)/ubuntu64 --build-arg base_docker_image=ubuntu:focal -BUILD_ARGS_ALPINE := --build-arg crystal_targz=crystal.tar.gz $(BUILD_CONTEXT)/alpine --build-arg gc_version=$(GC_VERSION) + +CRYSTAL_TARGZ ?= $(BUILD_CONTEXT)/crystal-$(CRYSTAL_VERSION)-$(PACKAGE_ITERATION)-linux-$(arch).tar.gz## Which crystal.tar.gz file to install in docker images (ubuntu, alpine) + +BUILD_ARGS_COMMON := \ + $(if $(pull_images),--pull) \ + $(if $(no_cache),--no-cache) \ + $(if $(GITHUB_ACTIONS),--cache-from type=gha,mode=max,scope=$(arch) --cache-to type=gha,mode=max,scope=$(arch)) \ + --platform $(DOCKER_BUILD_PLATFORM) \ + --label "crystal_version=$(CRYSTAL_VERSION)" \ + --label "package_iteration=$(PACKAGE_ITERATION)" \ + --label "package_maintainer=$(PACKAGE_MAINTAINER)" \ + --build-arg llvm_version=$(LLVM_VERSION) + +BUILD_ARGS_UBUNTU := $(BUILD_ARGS_COMMON) \ + --build-arg crystal_targz=crystal.tar.gz \ + --build-arg base_docker_image=$(BASE_UBUNTU_DOCKER_IMAGE) \ + $(BUILD_CONTEXT)/ubuntu + +BUILD_ARGS_ALPINE := $(BUILD_ARGS_COMMON) \ + --build-arg crystal_targz=crystal.tar.gz \ + --build-arg gc_version=$(GC_VERSION) \ + $(BUILD_CONTEXT)/alpine + DOCKER_TAG_UBUNTU := $(DOCKER_REPOSITORY):$(DOCKER_TAG) DOCKER_TAG_ALPINE := $(DOCKER_REPOSITORY):$(DOCKER_TAG)-alpine -.PHONY: all64 -all64: ubuntu64 alpine ## Build all x86_64 images +.PHONY: all +all: ubuntu alpine ## Build all images .PHONY: all_ubuntu -all_ubuntu: ubuntu64 ## Build all ubuntu images +all_ubuntu: ubuntu ## Build all ubuntu images -.PHONY: ubuntu64 -ubuntu64: ## Build ubuntu x86_64 images -ubuntu64: $(OUTPUT_DIR)/docker-$(CRYSTAL_VERSION)-ubuntu-x86_64.tar.gz -ubuntu64: $(OUTPUT_DIR)/docker-$(CRYSTAL_VERSION)-ubuntu-x86_64-build.tar.gz +.PHONY: ubuntu +ubuntu: ## Build ubuntu images +ubuntu: $(OUTPUT_DIR)/docker-$(CRYSTAL_VERSION)-ubuntu-$(arch).tar.gz +ubuntu: $(OUTPUT_DIR)/docker-$(CRYSTAL_VERSION)-ubuntu-$(arch)-build.tar.gz .PHONY: alpine alpine: ## Build alpine images -alpine: $(OUTPUT_DIR)/docker-$(CRYSTAL_VERSION)-alpine.tar.gz -alpine: $(OUTPUT_DIR)/docker-$(CRYSTAL_VERSION)-alpine-build.tar.gz +alpine: $(OUTPUT_DIR)/docker-$(CRYSTAL_VERSION)-alpine-$(arch).tar.gz +alpine: $(OUTPUT_DIR)/docker-$(CRYSTAL_VERSION)-alpine-$(arch)-build.tar.gz -$(BUILD_CONTEXT)/ubuntu64: ubuntu.Dockerfile $(BUILD_CONTEXT)/ubuntu64/crystal.tar.gz +$(BUILD_CONTEXT)/ubuntu: ubuntu.Dockerfile $(BUILD_CONTEXT)/ubuntu/crystal.tar.gz cp ubuntu.Dockerfile $@/Dockerfile $(BUILD_CONTEXT)/alpine: alpine.Dockerfile $(BUILD_CONTEXT)/alpine/crystal.tar.gz cp alpine.Dockerfile $@/Dockerfile mkdir $@/files/ -%/crystal.deb: - mkdir -p $(shell dirname $@) - cp $(CRYSTAL_DEB) $@ - %/crystal.tar.gz: mkdir -p $(shell dirname $@) cp $(CRYSTAL_TARGZ) $@ $(OUTPUT_DIR): - mkdir -p $(OUTPUT_DIR) + mkdir -p $(@) + +$(BUILD_CONTEXT): + mkdir -p $(@) + +.PHONY: scripts +scripts: $(BUILD_CONTEXT) + cp -r ../scripts $(BUILD_CONTEXT)/alpine -# Ubuntu x86_64 -$(OUTPUT_DIR)/docker-$(CRYSTAL_VERSION)-ubuntu-x86_64.tar.gz: $(BUILD_CONTEXT)/ubuntu64 $(OUTPUT_DIR) - docker build -t $(DOCKER_TAG_UBUNTU) --target runtime $(BUILD_ARGS_UBUNTU64) - docker save $(DOCKER_TAG_UBUNTU) | gzip > $@ +.PHONY: test +test: test_ubuntu test_alpine -$(OUTPUT_DIR)/docker-$(CRYSTAL_VERSION)-ubuntu-x86_64-build.tar.gz: $(BUILD_CONTEXT)/ubuntu64 $(OUTPUT_DIR) - docker build -t $(DOCKER_TAG_UBUNTU)-build --target build $(BUILD_ARGS_UBUNTU64) - docker save $(DOCKER_TAG_UBUNTU)-build | gzip > $@ +.PHONY: test_ubuntu +test_ubuntu: ubuntu + $(call test_crystal_image, $(DOCKER_TAG_UBUNTU), $(OUTPUT_DIR)/docker-$(CRYSTAL_VERSION)-ubuntu-$(arch).tar.gz) -# Alpine x86_64 -$(OUTPUT_DIR)/docker-$(CRYSTAL_VERSION)-alpine.tar.gz: $(BUILD_CONTEXT)/alpine $(OUTPUT_DIR) - docker build -t $(DOCKER_TAG_ALPINE) --target runtime $(BUILD_ARGS_ALPINE) - docker save $(DOCKER_TAG_ALPINE) | gzip > $@ +.PHONY: test_alpine +test_alpine: alpine + $(call test_crystal_image, $(DOCKER_TAG_ALPINE), $(OUTPUT_DIR)/docker-$(CRYSTAL_VERSION)-alpine-$(arch).tar.gz) -$(OUTPUT_DIR)/docker-$(CRYSTAL_VERSION)-alpine-build.tar.gz: $(BUILD_CONTEXT)/alpine $(OUTPUT_DIR) - docker build -t $(DOCKER_TAG_ALPINE)-build --target build $(BUILD_ARGS_ALPINE) - docker save $(DOCKER_TAG_ALPINE)-build | gzip > $@ +# Ubuntu +$(OUTPUT_DIR)/docker-$(CRYSTAL_VERSION)-ubuntu-$(arch).tar.gz: $(BUILD_CONTEXT)/ubuntu $(OUTPUT_DIR) + docker buildx build --tag $(DOCKER_TAG_UBUNTU) --target runtime -o type=docker,dest=- $(BUILD_ARGS_UBUNTU) | gzip > $@ + +$(OUTPUT_DIR)/docker-$(CRYSTAL_VERSION)-ubuntu-$(arch)-build.tar.gz: $(BUILD_CONTEXT)/ubuntu $(OUTPUT_DIR) + docker buildx build --tag $(DOCKER_TAG_UBUNTU)-build --target build -o type=docker,dest=- $(BUILD_ARGS_UBUNTU) | gzip > $@ + +# Alpine +$(OUTPUT_DIR)/docker-$(CRYSTAL_VERSION)-alpine-$(arch).tar.gz: $(BUILD_CONTEXT)/alpine $(OUTPUT_DIR) scripts + docker buildx build --tag $(DOCKER_TAG_ALPINE) --target runtime -o type=docker,dest=- $(BUILD_ARGS_ALPINE) | gzip > $@ + +$(OUTPUT_DIR)/docker-$(CRYSTAL_VERSION)-alpine-$(arch)-build.tar.gz: $(BUILD_CONTEXT)/alpine $(OUTPUT_DIR) scripts + docker buildx build --tag $(DOCKER_TAG_ALPINE)-build --target build -o type=docker,dest=- $(BUILD_ARGS_ALPINE) | gzip > $@ .PHONY: clean clean: ## Clean up build and output directories @@ -95,3 +144,19 @@ help: ## Show this help @printf '\033[34mrecipes:\033[0m\n' @grep -hE '^##.*$$' $(MAKEFILE_LIST) |\ awk 'BEGIN {FS = "## "}; /^## [a-zA-Z_-]/ {printf " \033[36m%s\033[0m\n", $$2}; /^## / {printf " %s\n", $$2}' + +# Load the docker image and run `crystal` and `shards` +# Arguments: +# $1: The docker image tag to load +# $2: The docker tar ball to load +define test_crystal_image + docker load -i $(2) \ + && \ + docker run --rm \ + $(1) \ + crystal --version \ + && \ + docker run --rm \ + $(1) \ + shards --version +endef diff --git a/docker/README.md b/docker/README.md new file mode 100644 index 00000000..5ddef3d5 --- /dev/null +++ b/docker/README.md @@ -0,0 +1,15 @@ +# Docker builds + +Crystal binaries are [built separately](../linux/README.md), then packaged into Docker images. + +## Dependencies + +- Crystal binaries for `x86_64` and `aarch64` (targz) +- `docker` + +## Environment + +- `CRYSTAL_VERSION`: How the binaries should be branded +- `CRYSTAL_TARGZ`: Which crystal.tar.gz file to install in docker images (ubuntu64, alpine) +- `DOCKER_TAG`: How to tag the docker image (examples: `0.27.2`, `nightly20190307`). `-build` will be appended for build images. +- `DOCKER_REPOSITORY`: Docker hub repository to commit image diff --git a/docker/alpine.Dockerfile b/docker/alpine.Dockerfile index faf8f0d4..ff505b55 100644 --- a/docker/alpine.Dockerfile +++ b/docker/alpine.Dockerfile @@ -12,36 +12,41 @@ RUN \ autoconf automake libtool patch # Build libgc -ARG gc_version +ARG gc_version=8.2.2 -RUN git clone https://github.com/ivmai/bdwgc \ +COPY scripts/shallow-clone.sh /tmp/shallow-clone.sh + +RUN /tmp/shallow-clone.sh ${gc_version} https://github.com/ivmai/bdwgc \ + && rm /tmp/shallow-clone.sh \ && cd bdwgc \ - && git checkout ${gc_version} \ \ && ./autogen.sh \ && ./configure --disable-debug --disable-shared --enable-large-config \ - && make -j$(nproc) CFLAGS=-DNO_GETCONTEXT \ + && make -j$(nproc) CFLAGS="-DNO_GETCONTEXT -pipe -fPIC -O3" \ && make install # Remove build tools from image now that libgc is built RUN apk del -r --purge autoconf automake libtool patch +# Copy platform specific crystal build into container ARG crystal_targz COPY ${crystal_targz} /tmp/crystal.tar.gz RUN \ tar -xz -C /usr --strip-component=1 -f /tmp/crystal.tar.gz \ - --exclude */lib/crystal/lib \ - --exclude */lib/crystal/*.a \ - --exclude */share/crystal/src/llvm/ext/llvm_ext.o && \ + --exclude '*/lib/crystal/lib' \ + --exclude '*/lib/crystal/*.a' \ + --exclude '*/share/crystal/src/llvm/ext/llvm_ext.o' && \ rm /tmp/crystal.tar.gz CMD ["/bin/sh"] FROM runtime as build +ARG llvm_version=13 + RUN \ apk add --update --no-cache --force-overwrite \ - llvm13-dev llvm13-static g++ libffi-dev + llvm${llvm_version}-dev llvm${llvm_version}-static g++ libffi-dev CMD ["/bin/sh"] diff --git a/docker/ubuntu.Dockerfile b/docker/ubuntu.Dockerfile index 74558ff4..065495b3 100644 --- a/docker/ubuntu.Dockerfile +++ b/docker/ubuntu.Dockerfile @@ -11,6 +11,7 @@ RUN \ apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* ARG crystal_targz +# Copy in platform specific crystal build COPY ${crystal_targz} /tmp/crystal.tar.gz RUN \ @@ -21,11 +22,13 @@ CMD ["/bin/sh"] FROM runtime as build +ARG llvm_version=13 + RUN \ apt-get update && \ - apt-get install -y build-essential llvm-10 lld-10 libedit-dev gdb libffi-dev && \ + apt-get install -y build-essential llvm-${llvm_version} lld-${llvm_version} libedit-dev gdb libffi-dev && \ apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* -RUN ln -sf /usr/bin/ld.lld-10 /usr/bin/ld.lld +RUN ln -sf /usr/bin/ld.lld-${llvm_version} /usr/bin/ld.lld CMD ["/bin/sh"] diff --git a/docs/Dockerfile b/docs/Dockerfile index a18f0bb2..187cc53e 100644 --- a/docs/Dockerfile +++ b/docs/Dockerfile @@ -4,10 +4,13 @@ FROM ${crystal_docker_image} RUN crystal --version ARG output_docs_base_name +ARG crystal_repository ARG crystal_sha1 -RUN git clone https://github.com/crystal-lang/crystal \ + +# TODO: Shallow clone +RUN git clone "${crystal_repository}" \ && cd crystal \ - && git checkout ${crystal_sha1} \ + && git checkout "${crystal_sha1}" \ \ && make docs DOCS_OPTIONS='--json-config-url=/api/versions.json --canonical-base-url="https://crystal-lang.org/api/latest/"'\ && git describe --tags --long --always 2>/dev/null > ./docs/revision.txt \ diff --git a/docs/Makefile b/docs/Makefile index 23a5fda2..18df6717 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -9,7 +9,9 @@ AWS_CLI = docker run --rm -e AWS_ACCESS_KEY_ID -e AWS_SECRET_ACCESS_KEY -v $$(pw S3_ENDPOINT = s3://$(AWS_BUCKET)/api AWS_BUCKET = crystal-api -BUILD_ARGS = --build-arg crystal_docker_image=$(CRYSTAL_DOCKER_IMAGE) --build-arg output_docs_base_name=$(OUTPUT_DOCS_BASE_NAME) --build-arg crystal_sha1=$(CRYSTAL_SHA1) +CRYSTAL_REPOSITORY ?= crystal-lang/crystal + +BUILD_ARGS = --build-arg crystal_docker_image=$(CRYSTAL_DOCKER_IMAGE) --build-arg output_docs_base_name=$(OUTPUT_DOCS_BASE_NAME) --build-arg crystal_sha1=$(CRYSTAL_SHA1) --build-arg crystal_repository=https://github.com/$(CRYSTAL_REPOSITORY) .PHONY: all all: $(OUTPUT_DIR)/$(OUTPUT_DOCS_BASE_NAME).tar.gz ## Build docs tarball diff --git a/linux/.dockerignore b/linux/.dockerignore index 2635dcd5..63058ba8 100644 --- a/linux/.dockerignore +++ b/linux/.dockerignore @@ -1,2 +1,4 @@ /** !/files/** +!build/** +!build_context/** diff --git a/linux/.gitignore b/linux/.gitignore index 84c048a7..de840179 100644 --- a/linux/.gitignore +++ b/linux/.gitignore @@ -1 +1,2 @@ /build/ +/build_context/ diff --git a/linux/Dockerfile b/linux/Dockerfile index a20b1fff..dd182bbb 100644 --- a/linux/Dockerfile +++ b/linux/Dockerfile @@ -1,29 +1,37 @@ FROM debian:11 AS debian +ARG llvm_version=13 + RUN apt-get update \ - && apt-get install -y build-essential libevent-dev libpcre3-dev automake libtool pkg-config git curl llvm-13 clang-13 \ + && apt-get install -y build-essential libevent-dev libpcre3-dev automake libtool pkg-config git curl llvm-${llvm_version} clang-13 \ && (pkg-config || true) ARG release -ENV CFLAGS="-fPIC -pipe ${release:+-O2}" ENV CC="clang-13" +ENV CFLAGS="-fPIC -pipe ${release:+-O3}" # Build libgc ARG gc_version -RUN git clone https://github.com/ivmai/bdwgc \ +# Helper script to shallow clone a git repo and checkout a specific tag +ARG scripts_path=build_context/scripts +COPY ${scripts_path}/shallow-clone.sh /tmp/shallow-clone.sh + +RUN /tmp/shallow-clone.sh ${gc_version} https://github.com/ivmai/bdwgc \ && cd bdwgc \ - && git checkout ${gc_version} \ + \ && ./autogen.sh \ && ./configure --disable-debug --disable-shared --enable-large-config \ && make -j$(nproc) FROM alpine:3.16 +ARG llvm_version=13 + # Install dependencies RUN apk add --no-cache \ # Statically-compiled llvm - llvm13-dev llvm13-static \ + llvm${llvm_version}-dev llvm${llvm_version}-static \ # Static stdlib dependencies zlib-static yaml-static libxml2-dev pcre-dev libevent-static \ # Static compiler dependencies @@ -32,17 +40,21 @@ RUN apk add --no-cache \ git gcc g++ make automake libtool autoconf bash coreutils curl ARG release -ENV CFLAGS="-fPIC -pipe ${release:+-O2}" +ENV CFLAGS="-fPIC -pipe ${release:+-O3}" # Build libgc (again, this time for musl) ARG gc_version -RUN git clone https://github.com/ivmai/bdwgc \ + +# Helper script to shallow clone a git repo and checkout a specific tag +ARG scripts_path=build_context/scripts +COPY ${scripts_path}/shallow-clone.sh /tmp/shallow-clone.sh + +RUN /tmp/shallow-clone.sh ${gc_version} https://github.com/ivmai/bdwgc \ && cd bdwgc \ - && git checkout ${gc_version} \ \ && ./autogen.sh \ && ./configure --disable-debug --disable-shared --enable-large-config \ - && make -j$(nproc) CFLAGS=-DNO_GETCONTEXT + && make -j$(nproc) CFLAGS="-DNO_GETCONTEXT ${CFLAGS}" # This overrides default CRYSTAL_LIBRARY_PATH baked into the binary (starting with 1.2.0) # or configured via wrapper script (before 1.2.0) because we want to link against @@ -51,7 +63,8 @@ ENV CRYSTAL_LIBRARY_PATH=/bdwgc/.libs/ RUN llvm-config --version ARG previous_crystal_release -ADD ${previous_crystal_release} /tmp/crystal.tar.gz +COPY ${previous_crystal_release} /tmp/crystal.tar.gz + # TODO: Update path to new install directory /tmp/crystal/bin after migration period ENV PATH=${PATH}:/tmp/crystal/lib/crystal/bin/ RUN mkdir -p /tmp/crystal \ @@ -63,9 +76,9 @@ RUN mkdir -p /tmp/crystal \ ARG crystal_version ARG crystal_sha1 ARG gnu_target -RUN git clone https://github.com/crystal-lang/crystal \ + +RUN /tmp/shallow-clone.sh ${crystal_sha1} https://github.com/crystal-lang/crystal \ && cd crystal \ - && git checkout ${crystal_sha1} \ \ && make crystal stats=true static=true ${release:+release=true} \ CRYSTAL_CONFIG_TARGET=${gnu_target} \ @@ -74,9 +87,8 @@ RUN git clone https://github.com/crystal-lang/crystal \ # Build shards ARG shards_version ARG musl_target -RUN git clone https://github.com/crystal-lang/shards \ +RUN /tmp/shallow-clone.sh ${shards_version} https://github.com/crystal-lang/shards \ && cd shards \ - && git checkout ${shards_version} \ # FIXME: Remove this workaround for https://github.com/crystal-lang/crystal/issues/10861 && touch shard.lock \ && make SHARDS=false CRYSTAL=/crystal/bin/crystal \ diff --git a/linux/Makefile b/linux/Makefile index 287206dd..608c1127 100644 --- a/linux/Makefile +++ b/linux/Makefile @@ -1,103 +1,142 @@ # Recipes for this Makefile -## Build everything -## $ make CRYSTAL_VERSION=0.xx.y PREVIOUS_CRYSTAL_RELEASE_LINUX64_TARGZ=... -## Build just 64bit distribution packages -## $ make package64 CRYSTAL_VERSION=0.xx.y PREVIOUS_CRYSTAL_RELEASE_LINUX64_TARGZ=... +## Build everything for x86_64 +## $ make arch=x86_64 CRYSTAL_VERSION=0.xx.y PREVIOUS_CRYSTAL_VERSION=... +## Build everything for aarch64 +## $ make arch=aarch64 CRYSTAL_VERSION=0.xx.y PREVIOUS_CRYSTAL_VERSION=... ## Build everything for final release -## $ make clean all no_cache=true pull_images=true release=true CRYSTAL_VERSION=0.xx.y PREVIOUS_CRYSTAL_RELEASE_LINUX64_TARGZ=... +## $ make clean all arch= no_cache=true pull_images=true release=true CRYSTAL_VERSION=0.xx.y PREVIOUS_CRYSTAL_VERSION=... +arch ?= ## Architecture to build for (x86_64, aarch64) no_cache ?= ## Disable the docker build cache pull_images ?= ## Always pull docker images to ensure they're up to date release ?= ## Create an optimized build for the final release +bootstrap_aarch64 ?= true## Extract the bootstrap compiler from and aarch64 image until tier-1 aarch64 artefact available CRYSTAL_VERSION ?= ## How the binaries should be branded CRYSTAL_SHA1 ?= $(CRYSTAL_VERSION) ## Git tag/branch/sha1 to checkout and build source PACKAGE_ITERATION ?= 1 -PACKAGE_MAINTAINER = Crystal Team -PREVIOUS_CRYSTAL_VERSION ?= ## Version of the bootstrap compiler -PREVIOUS_CRYSTAL_PACKAGE_ITERATION ?= 1## Package iteration of the bootstrap compiler -PREVIOUS_CRYSTAL_RELEASE_LINUX64_TARGZ ?= https://github.com/crystal-lang/crystal/releases/download/$(PREVIOUS_CRYSTAL_VERSION)/crystal-$(PREVIOUS_CRYSTAL_VERSION)-$(PREVIOUS_CRYSTAL_PACKAGE_ITERATION)-linux-x86_64.tar.gz ## url to crystal-{version}-{package}-linux-x86_64.tar.gz +PREVIOUS_CRYSTAL_VERSION ?= ## Version of the bootstrap compiler +PREVIOUS_PACKAGE_ITERATION ?= 1## Package iteration of the bootstrap compiler SHARDS_VERSION = v0.17.1 +LLVM_VERSION = 13 GC_VERSION = v8.2.2 LIBPCRE_VERSION = 8.45 LIBEVENT_VERSION = release-2.1.12-stable OUTPUT_DIR = build -OUTPUT_BASENAME64 = $(OUTPUT_DIR)/crystal-$(CRYSTAL_VERSION)-$(PACKAGE_ITERATION)-linux-x86_64 +BUILD_CONTEXT = build_context +SCRIPTS_PATH = $(BUILD_CONTEXT)/scripts + +ifeq ($(arch),x86_64) + DOCKER_BUILD_PLATFORM = linux/amd64 +else ifeq ($(arch),aarch64) + DOCKER_BUILD_PLATFORM = linux/arm64 +else + $(error Expected arch to be one of 'x86_64', or 'aarch64', got: $(arch)) +endif + +COMPILER_OUTPUT_BASENAME = crystal-$(CRYSTAL_VERSION)-$(PACKAGE_ITERATION) + +OUTPUT_BASENAME = $(OUTPUT_DIR)/$(COMPILER_OUTPUT_BASENAME)-linux-$(arch) +OUTPUT_BASENAME_BUNDLED = $(OUTPUT_BASENAME)-bundled + +PREVIOUS_CRYSTAL_RELEASE_TARGZ ?= $(BUILD_CONTEXT)/crystal-$(PREVIOUS_CRYSTAL_VERSION)-$(PREVIOUS_PACKAGE_ITERATION)-linux-$(arch).tar.gz## Path to the bootstrap compiler +PREVIOUS_CRYSTAL_RELEASE_TARGZ_URL ?= https://github.com/crystal-lang/crystal/releases/download/$(PREVIOUS_CRYSTAL_VERSION)/crystal-$(PREVIOUS_CRYSTAL_VERSION)-$(PREVIOUS_PACKAGE_ITERATION)-linux-$(arch).tar.gz## URL to crystal-{version}-{package}-linux-$(arch).tar.gz + +BOOTSTRAP_AARCH64_IMAGE=84codes/crystal:$(PREVIOUS_CRYSTAL_VERSION)-alpine + +.SHELLFLAGS=-cx + +BUILD_ARGS_LIB_VERSIONS = \ + --build-arg libpcre_version=$(LIBPCRE_VERSION) \ + --build-arg libevent_version=$(LIBEVENT_VERSION) + +BUILD_ARGS_COMMON = \ + --progress plain \ + $(if $(pull_images),--pull) \ + $(if $(no_cache),--no-cache) \ + $(if $(GITHUB_ACTIONS),--cache-from type=gha,mode=max,scope=$(arch) --cache-to type=gha,mode=max,scope=$(arch)) \ + $(if $(release),--build-arg release=true) \ + --build-arg llvm_version=$(LLVM_VERSION) \ + --build-arg scripts_path=$(SCRIPTS_PATH) \ + --build-arg crystal_version=$(CRYSTAL_VERSION) \ + --build-arg crystal_sha1=$(CRYSTAL_SHA1) \ + --build-arg shards_version=$(SHARDS_VERSION) \ + --build-arg gc_version=$(GC_VERSION) \ + --build-arg package_iteration=$(PACKAGE_ITERATION) + +BUILD_ARGS = \ + $(BUILD_ARGS_COMMON) \ + --build-arg previous_crystal_release=$(PREVIOUS_CRYSTAL_RELEASE_TARGZ) \ + --build-arg musl_target=$(arch)-linux-musl \ + --build-arg gnu_target=$(arch)-unknown-linux-gnu + +BUILD_ARGS_BUNDLED = \ + $(BUILD_ARGS) \ + $(BUILD_ARGS_LIB_VERSIONS) \ + -f bundled.dockerfile -DOCKER_BUILD_ARGS = $(if $(no_cache),--no-cache )$(if $(pull_images),--pull ) +.PHONY: all +all: all_linux ## Build all distribution tarballs [default] -BUILD_ARGS_COMMON = $(DOCKER_BUILD_ARGS) \ - $(if $(release),--build-arg release=true) \ - --build-arg crystal_version=$(CRYSTAL_VERSION) \ - --build-arg crystal_sha1=$(CRYSTAL_SHA1) \ - --build-arg shards_version=$(SHARDS_VERSION) \ - --build-arg gc_version=$(GC_VERSION) \ - --build-arg package_iteration=$(PACKAGE_ITERATION) +.PHONY: all_linux +all_linux: compress_linux clean_tmp ## Build distribution tarballs for linux binaries -BUILD_ARGS64 = $(BUILD_ARGS_COMMON) \ - --build-arg previous_crystal_release=$(PREVIOUS_CRYSTAL_RELEASE_LINUX64_TARGZ) \ - --build-arg musl_target=x86_64-linux-musl \ - --build-arg gnu_target=x86_64-unknown-linux-gnu +.PHONY: build +build: $(OUTPUT_BASENAME).tar ## Build the raw uncompressed tarballs for all distributions -BUILD_ARGS64_BUNDLED = $(BUILD_ARGS64) \ - --build-arg libpcre_version=$(LIBPCRE_VERSION) \ - --build-arg libevent_version=$(LIBEVENT_VERSION) +.PHONY: build_linux +build_linux: $(OUTPUT_BASENAME).tar ## Build the raw uncompressed tarball for linux -.PHONY: all -all: all64 ## Build all distribution tarballs [default] +# Build the compiler -.PHONY: all64 -all64: compress64 clean_tmp ## Build distribution tarballs for 64 bits +$(OUTPUT_BASENAME).tar: Dockerfile $(OUTPUT_DIR) $(PREVIOUS_CRYSTAL_RELEASE_TARGZ) $(SCRIPTS_PATH) + $(call build_in_container,$(DOCKER_BUILD_PLATFORM),$(BUILD_ARGS),/output/$(COMPILER_OUTPUT_BASENAME).tar,$@) -.PHONY: help -help: ## Show this help - @echo - @printf '\033[34mtargets:\033[0m\n' - @grep -hE '^[a-zA-Z0-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) |\ - sort |\ - awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-15s\033[0m %s\n", $$1, $$2}' - @echo - @printf '\033[34moptional variables:\033[0m\n' - @grep -hE '^[a-zA-Z0-9_-]+ \?=.*?## .*$$' $(MAKEFILE_LIST) |\ - sort |\ - awk 'BEGIN {FS = " \\?=.*?## "}; {printf " \033[36m%-15s\033[0m %s\n", $$1, $$2}' - @echo - @printf '\033[34mrecipes:\033[0m\n' - @grep -hE '^##.*$$' $(MAKEFILE_LIST) |\ -awk 'BEGIN {FS = "## "}; /^## [a-zA-Z_-]/ {printf " \033[36m%s\033[0m\n", $$2}; /^## / {printf " %s\n", $$2}' +# Build the bundled libraries -.PHONY: build -build: $(OUTPUT_BASENAME64).tar ## Build the raw uncompressed tarball +$(OUTPUT_BASENAME_BUNDLED)-libs.tar: bundled.dockerfile $(OUTPUT_DIR) $(SCRIPTS_PATH) + $(call build_in_container,$(DOCKER_BUILD_PLATFORM),$(BUILD_ARGS_BUNDLED),/output/bundled-libs.tar,$@) -$(OUTPUT_BASENAME64).tar: Dockerfile - mkdir -p $(OUTPUT_DIR) - docker build $(BUILD_ARGS64) -t crystal-build-temp . - container_id="$$(docker create crystal-build-temp)" \ - && docker cp "$$container_id":/output/crystal-$(CRYSTAL_VERSION)-$(PACKAGE_ITERATION).tar $@ \ - && docker rm -v "$$container_id" +# Create bundled archives -$(OUTPUT_BASENAME64)-bundled.tar: $(OUTPUT_BASENAME64)-bundled - tar -C $(OUTPUT_BASENAME64)-bundled -cf $@ ./ +$(OUTPUT_BASENAME_BUNDLED).tar: $(OUTPUT_BASENAME_BUNDLED) + tar -C $(OUTPUT_BASENAME_BUNDLED) -cf $@ ./ -$(OUTPUT_BASENAME64)-bundled: $(OUTPUT_BASENAME64).tar $(OUTPUT_DIR)/bundled-libs.tar +$(OUTPUT_BASENAME_BUNDLED): $(OUTPUT_BASENAME).tar $(OUTPUT_BASENAME_BUNDLED)-libs.tar rm -rf $@ mkdir -p $@ - tar -C $@ -xf $(OUTPUT_BASENAME64).tar - tar -C $@ -xf $(OUTPUT_DIR)/bundled-libs.tar - -$(OUTPUT_DIR)/bundled-libs.tar: bundled.dockerfile - mkdir -p $(OUTPUT_DIR) - docker build $(BUILD_ARGS64_BUNDLED) -t crystal-build-temp -f bundled.dockerfile . - container_id="$$(docker create crystal-build-temp)" \ - && docker cp "$$container_id":/output/bundled-libs.tar $@ \ - && docker rm -v "$$container_id" + tar -C $@ -xf $(OUTPUT_BASENAME).tar + tar -C $@ -xf $(OUTPUT_BASENAME_BUNDLED)-libs.tar + +.PHONY: compress_linux +compress_linux: $(OUTPUT_BASENAME).tar.gz $(OUTPUT_BASENAME).tar.xz $(OUTPUT_BASENAME_BUNDLED).tar.gz + +$(PREVIOUS_CRYSTAL_RELEASE_TARGZ): $(BUILD_CONTEXT) + if [ "$(arch)" = "aarch64" ] && [ "$(bootstrap_aarch64)" = "true" ]; \ + then \ + container_id=$$(docker create $(DOCKER_PULL) --platform linux/arm64 "$(BOOTSTRAP_AARCH64_IMAGE)"); \ + workdir=$$(mktemp -d); \ + mkdir -p "$$workdir/usr/lib/crystal/bin"; \ + docker cp "$$container_id:/usr/bin/crystal" "$$workdir/usr/lib/crystal/bin" \ + && docker cp "$$container_id:/usr/bin/shards" "$$workdir/usr/lib/crystal/bin" \ + && tar -C "$$workdir" -czf "$@" usr/lib/crystal/bin/crystal usr/lib/crystal/bin/shards \ + && rm -r "$$workdir"; \ + else \ + curl --location --proto '=https' --tlsv1.2 --show-error --silent --fail \ + -o "$(@)" "$(PREVIOUS_CRYSTAL_RELEASE_TARGZ_URL)"; \ + fi + +$(OUTPUT_DIR): + mkdir -p $@ +$(BUILD_CONTEXT): + mkdir -p $@ -.PHONY: compress64 -compress64: $(OUTPUT_BASENAME64).tar.gz $(OUTPUT_BASENAME64).tar.xz $(OUTPUT_BASENAME64)-bundled.tar.gz ## Build compressed tarballs +$(SCRIPTS_PATH): ## Copy helper scripts to build context + cp -r ../scripts $(BUILD_CONTEXT) $(OUTPUT_DIR)/%.gz: $(OUTPUT_DIR)/% gzip -c $< > $@ @@ -107,9 +146,41 @@ $(OUTPUT_DIR)/%.xz: $(OUTPUT_DIR)/% .PHONY: clean clean: ## Clean up build directory - rm -Rf $(OUTPUT_DIR) + rm -Rf $(OUTPUT_DIR) $(BUILD_CONTEXT) .PHONY: clean_tmp clean_tmp: ## Clean up temporary build artifacts - rm -Rf $(OUTPUT_DIR)/bundled-libs.tar - rm -Rf $(OUTPUT_BASENAME64)-bundled + rm -Rf $(OUTPUT_DIR)/*-bundled-libs.tar + rm -Rf $(OUTPUT_DIR)/*-bundled + +.PHONY: help +help: ## Show this help + @echo + @printf '\033[34mtargets:\033[0m\n' + @grep -hE '^[a-zA-Z0-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) |\ + sort |\ + awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-15s\033[0m %s\n", $$1, $$2}' + @echo + @printf '\033[34moptional variables:\033[0m\n' + @grep -hE '^[a-zA-Z0-9_-]+ \?=.*?## .*$$' $(MAKEFILE_LIST) |\ + sort |\ + awk 'BEGIN {FS = " \\?=.*?## "}; {printf " \033[36m%-15s\033[0m %s\n", $$1, $$2}' + @echo + @printf '\033[34mrecipes:\033[0m\n' + @grep -hE '^##.*$$' $(MAKEFILE_LIST) |\ +awk 'BEGIN {FS = "## "}; /^## [a-zA-Z_-]/ {printf " \033[36m%s\033[0m\n", $$2}; /^## / {printf " %s\n", $$2}' + +# Build an image, then copy an artefact to a path on the host +# +# Arguments: +# - $1: Platform (amd64 or aarch64) +# - $2: Build arguments +# - $3: Path of the artefact to copy +# - $4: Path to copy the artefact to +define build_in_container +id=$$(echo '$(1)-$(2)-$(CRYSTAL_SHA1)' | md5sum | cut -c1-5); \ +docker buildx build --load --platform $(1) $(2) --tag "dummy.io/tmp/$$id" . || exit 1 ;\ +container_id=$$(docker create --platform $(1) "dummy.io/tmp/$$id"); \ +docker cp "$$container_id:$(3)" $(4) \ +&& docker rm -v "$$container_id" +endef diff --git a/linux/README.md b/linux/README.md index 75b3d23f..3df3f375 100644 --- a/linux/README.md +++ b/linux/README.md @@ -1,21 +1,33 @@ -# Linux `x86_64` static build +# Linux `x86_64` and `aarch64` static builds -The `x86_64` crystal build is built inside an alpine linux container as a +The `x86_64` and `aarch64` crystal build is built inside an alpine linux container as a statically linked binary using musl libc. `libgc` is built on debian to make it work on glibc. + +`BuildKit` and `qemu` is leveraged to build both target architectures on a single platform. + The whole process is automated using a `Makefile`. +The `arch` argument must be set to either `x86_64` or `aarch64`. -# Dependencies +## Dependencies - `docker` -# Getting started +## Getting started Just run `make help`! -# Build version variables +## Arguments + +* `arch`: Architecture to build for (x86_64, aarch64) +* `no_cache`: Disable the docker build cache +* `pull_images`: Always pull docker images to ensure they're up to date +* `release`: Create an optimized build for the final release + +## Environment * `CRYSTAL_VERSION`: How the binaries should be branded. * `CRYSTAL_SHA1`: Git tag/branch/sha1 to checkout and build source * `PACKAGE_ITERATION`: The package iteration -* `PREVIOUS_CRYSTAL_RELEASE_LINUX64_TARGZ`: Url to crystal-{version}-{package}-linux-x86_64.tar.gz +* `PREVIOUS_CRYSTAL_RELEASE_TARGZ`: Path to crystal-{version}-{package}-linux-{arch}.tar.gz +* `PREVIOUS_CRYSTAL_RELEASE_TARGZ_URL`: Override for the url for crystal-{version}-{package}-linux-{arch}.tar.gz diff --git a/linux/bundled.dockerfile b/linux/bundled.dockerfile index e3bf407a..412414d6 100644 --- a/linux/bundled.dockerfile +++ b/linux/bundled.dockerfile @@ -3,7 +3,7 @@ FROM debian:11 AS debian RUN apt-get update \ && apt-get install -y curl build-essential git automake libtool pkg-config -ENV CFLAGS="-fPIC -pipe ${release:+-O2}" +ENV CFLAGS="-fPIC -pipe ${release:+-O3}" # build libpcre FROM debian AS libpcre @@ -16,10 +16,14 @@ RUN curl https://ftp.exim.org/pub/pcre/pcre-${libpcre_version}.tar.gz | tar -zx # build libevent FROM debian AS libevent + +ARG scripts_path=build-context/scripts +COPY ${scripts_path}/shallow-clone.sh /tmp/shallow-clone.sh + ARG libevent_version -RUN git clone https://github.com/libevent/libevent \ +RUN /tmp/shallow-clone.sh ${libevent_version} https://github.com/libevent/libevent \ && cd libevent \ - && git checkout ${libevent_version} \ + \ && ./autogen.sh \ && ./configure --disable-shared --disable-openssl \ && make -j$(nproc) diff --git a/omnibus/config/software/crystal.rb b/omnibus/config/software/crystal.rb index 192556b1..8c0176cf 100644 --- a/omnibus/config/software/crystal.rb +++ b/omnibus/config/software/crystal.rb @@ -73,6 +73,7 @@ env["CXXFLAGS"] << " -target arm64-apple-darwin" make "deps", env: env + # Compile for aarch64 make "crystal stats=true release=true target=aarch64-apple-darwin FLAGS=\"#{crflags}\" CRYSTAL_CONFIG_TARGET=aarch64-apple-darwin CRYSTAL_CONFIG_LIBRARY_PATH= O=#{output_path}", env: env command "clang #{output_path}/crystal.o -o #{output_bin}_arm64 -target arm64-apple-darwin src/llvm/ext/llvm_ext.o `llvm-config --libs --system-libs --ldflags 2>/dev/null` -lstdc++ -lpcre -lgc -lpthread -levent -liconv -ldl -v", env: env diff --git a/processes/scripts/publish-crystal-packages-on-github.sh b/processes/scripts/publish-crystal-packages-on-github.sh index 06626ff3..4361715a 100755 --- a/processes/scripts/publish-crystal-packages-on-github.sh +++ b/processes/scripts/publish-crystal-packages-on-github.sh @@ -40,6 +40,6 @@ wget --directory-prefix="$artifacts_dir/" \ ls -lh "$artifacts_dir/" -step "Upload artifacts to GitHub release $VERSION" gh release -R crystal-lang/crystal upload $VERSION "$artifacts_dir/*" +step "Upload artifacts to GitHub release $VERSION" gh release -R crystal-lang/crystal upload "$VERSION" "$artifacts_dir/*" rm -rf "$artifacts_dir" diff --git a/scripts/shallow-clone.sh b/scripts/shallow-clone.sh new file mode 100755 index 00000000..e323619c --- /dev/null +++ b/scripts/shallow-clone.sh @@ -0,0 +1,24 @@ +#!/bin/sh + +# Shallow clone a reference +# +# Usage: +# +# scripts/shallow-clone.sh +# +# This helper script clones a reference from a remote URI without history. + +set -eu + +REFERENCE=$1 +URI=$2 + +# Create an empty git dir. +directory=$(basename -s .git "$URI") +git init "$directory" +cd "$directory" + +# Fetch the reference from the remote and check it out. +git remote add origin "$URI" +git fetch --depth 1 origin "$REFERENCE" +git checkout FETCH_HEAD diff --git a/snapcraft/Makefile b/snapcraft/Makefile index 417ae00a..3d42280a 100644 --- a/snapcraft/Makefile +++ b/snapcraft/Makefile @@ -1,9 +1,17 @@ OUTPUT_DIR = build +ifeq ($(arch),x86_64) + SNAP_BUILD_FOR = --build-for amd64 +else ifeq ($(arch),aarch64) + SNAP_BUILD_FOR = --build-for arm64 +else + $(error Expected arch to be one of 'x86_64', or 'aarch64', got: $(arch)) +endif + .PHONY: all all: snap/snapcraft.yaml mkdir -p $(OUTPUT_DIR) - snapcraft + snapcraft $(SNAP_BUILD_FOR) mv *.snap $(OUTPUT_DIR) .PHONY: snap/snapcraft.yaml diff --git a/snapcraft/snap/local/snapcraft.yaml.tpl b/snapcraft/snap/local/snapcraft.yaml.tpl index 7a25e41f..ec62fbba 100644 --- a/snapcraft/snap/local/snapcraft.yaml.tpl +++ b/snapcraft/snap/local/snapcraft.yaml.tpl @@ -21,6 +21,9 @@ apps: shards: command: bin/shards +architectures: + - build-for: [amd64, arm64] + parts: crystal: plugin: dump