diff --git a/Makefile b/Makefile index 0ef56f22..6e1916a5 100644 --- a/Makefile +++ b/Makefile @@ -36,6 +36,8 @@ # See https://www.gnu.org/software/make/manual/html_node/Secondary-Expansion.html .SECONDEXPANSION: +# For details on some of these "prelude" settings, see: +# https://clarkgrubb.com/makefile-style-guide MAKEFLAGS += --warn-undefined-variables --no-builtin-rules SHELL := /usr/bin/env bash .SHELLFLAGS := -uo pipefail -c diff --git a/klone.yaml b/klone.yaml index 49331f3e..2f08509a 100644 --- a/klone.yaml +++ b/klone.yaml @@ -10,55 +10,55 @@ targets: - folder_name: boilerplate repo_url: https://github.com/cert-manager/makefile-modules.git repo_ref: main - repo_hash: 3d9f3fc916817107d8793379fdcc602403360eee + repo_hash: d3fbbe92ebeace2b369fdc51eb785b42fe39d1d9 repo_path: modules/boilerplate - folder_name: cert-manager repo_url: https://github.com/cert-manager/makefile-modules.git repo_ref: main - repo_hash: 3d9f3fc916817107d8793379fdcc602403360eee + repo_hash: d3fbbe92ebeace2b369fdc51eb785b42fe39d1d9 repo_path: modules/cert-manager - folder_name: controller-gen repo_url: https://github.com/cert-manager/makefile-modules.git repo_ref: main - repo_hash: 3d9f3fc916817107d8793379fdcc602403360eee + repo_hash: d3fbbe92ebeace2b369fdc51eb785b42fe39d1d9 repo_path: modules/controller-gen - folder_name: generate-verify repo_url: https://github.com/cert-manager/makefile-modules.git repo_ref: main - repo_hash: 3d9f3fc916817107d8793379fdcc602403360eee + repo_hash: d3fbbe92ebeace2b369fdc51eb785b42fe39d1d9 repo_path: modules/generate-verify - folder_name: helm repo_url: https://github.com/cert-manager/makefile-modules.git repo_ref: main - repo_hash: 3d9f3fc916817107d8793379fdcc602403360eee + repo_hash: d3fbbe92ebeace2b369fdc51eb785b42fe39d1d9 repo_path: modules/helm - folder_name: help repo_url: https://github.com/cert-manager/makefile-modules.git repo_ref: main - repo_hash: 3d9f3fc916817107d8793379fdcc602403360eee + repo_hash: d3fbbe92ebeace2b369fdc51eb785b42fe39d1d9 repo_path: modules/help - folder_name: kind repo_url: https://github.com/cert-manager/makefile-modules.git repo_ref: main - repo_hash: 3d9f3fc916817107d8793379fdcc602403360eee + repo_hash: d3fbbe92ebeace2b369fdc51eb785b42fe39d1d9 repo_path: modules/kind - folder_name: klone repo_url: https://github.com/cert-manager/makefile-modules.git repo_ref: main - repo_hash: 3d9f3fc916817107d8793379fdcc602403360eee + repo_hash: d3fbbe92ebeace2b369fdc51eb785b42fe39d1d9 repo_path: modules/klone - folder_name: oci-image repo_url: https://github.com/cert-manager/makefile-modules.git repo_ref: main - repo_hash: 3d9f3fc916817107d8793379fdcc602403360eee + repo_hash: d3fbbe92ebeace2b369fdc51eb785b42fe39d1d9 repo_path: modules/oci-image - folder_name: repository-base repo_url: https://github.com/cert-manager/makefile-modules.git repo_ref: main - repo_hash: 3d9f3fc916817107d8793379fdcc602403360eee + repo_hash: d3fbbe92ebeace2b369fdc51eb785b42fe39d1d9 repo_path: modules/repository-base - folder_name: tools repo_url: https://github.com/cert-manager/makefile-modules.git repo_ref: main - repo_hash: 3d9f3fc916817107d8793379fdcc602403360eee + repo_hash: d3fbbe92ebeace2b369fdc51eb785b42fe39d1d9 repo_path: modules/tools diff --git a/make/_shared/help/01_mod.mk b/make/_shared/help/01_mod.mk index 143a13ce..1a6a3b48 100644 --- a/make/_shared/help/01_mod.mk +++ b/make/_shared/help/01_mod.mk @@ -17,4 +17,6 @@ help_sh := $(dir $(lastword $(MAKEFILE_LIST)))/help.sh .PHONY: help help: - @MAKEFILE_LIST="$(MAKEFILE_LIST)" $(help_sh) + @MAKEFILE_LIST="$(MAKEFILE_LIST)" \ + MAKE="$(MAKE)" \ + $(help_sh) diff --git a/make/_shared/help/help.sh b/make/_shared/help/help.sh index 391c39f3..d98fc35e 100755 --- a/make/_shared/help/help.sh +++ b/make/_shared/help/help.sh @@ -16,10 +16,7 @@ set -eu -o pipefail -RULE_COLOR="$(tput setaf 6)" -CATEGORY_COLOR="$(tput setaf 3)" -CLEAR_STYLE="$(tput sgr0)" -PURPLE=$(tput setaf 125) +## 1. Build set of extracted line items EMPTYLINE_REGEX="^[[:space:]]*$" DOCBLOCK_REGEX="^##[[:space:]]*(.*)$" @@ -28,7 +25,6 @@ TARGET_REGEX="^(([a-zA-Z0-9\_\/\%\$\(\)]|-)+):.*$" EMPTY_ITEM="" - # shellcheck disable=SC2086 raw_lines=$(cat ${MAKEFILE_LIST} | tr '\t' ' ' | grep -E "($TARGET_REGEX|$DOCBLOCK_REGEX|$EMPTYLINE_REGEX)") extracted_lines="" @@ -56,6 +52,28 @@ while read -r line; do fi done <<< "$raw_lines" +## 2. Build mapping for expanding targets + +ASSIGNMENT_REGEX="^(([a-zA-Z0-9\_\/\%\$\(\)]|-)+)\s*:=\s*(.*)$" + +raw_expansions=$(${MAKE} --dry-run --print-data-base noop | tr '\t' ' ' | grep -E "$ASSIGNMENT_REGEX") +extracted_expansions="" + +while read -r line; do + if [[ $line =~ $ASSIGNMENT_REGEX ]]; then + target=${BASH_REMATCH[1]} + expansion=${BASH_REMATCH[3]// /, } + extracted_expansions="$extracted_expansions\n$target$expansion" + fi +done <<< "$raw_expansions" + +## 3. Sort and print the extracted line items + +RULE_COLOR="$(tput setaf 6)" +CATEGORY_COLOR="$(tput setaf 3)" +CLEAR_STYLE="$(tput sgr0)" +PURPLE=$(tput setaf 125) + extracted_lines=$(echo -e "$extracted_lines" | LC_ALL=C sort -r) current_category="" @@ -67,11 +85,19 @@ IFS=$'\n'; for line in $extracted_lines; do target=$([[ $line =~ \(.*)\ ]] && echo "${BASH_REMATCH[1]}") comment=$([[ $line =~ \(.*)\ ]] && echo -e "${BASH_REMATCH[1]///\\n}") + # Print the category header if it's changed if [[ "$current_category" != "$category" ]]; then current_category=$category echo -e "\n${CATEGORY_COLOR}${current_category}${CLEAR_STYLE}" fi + # replace any $(...) with the actual value + if [[ $target =~ \$\((.*)\) ]]; then + target=$(echo -e "$extracted_expansions" | grep "${BASH_REMATCH[1]}") + target=$([[ $target =~ \(.*)\ ]] && echo -e "${BASH_REMATCH[1]}") + fi + + # Print the target and its multiline comment is_first_line=true while read -r comment_line; do if [[ "$is_first_line" == true ]]; then diff --git a/make/_shared/oci-image/01_mod.mk b/make/_shared/oci-image/01_mod.mk index 3c16929d..fcf5e7ec 100644 --- a/make/_shared/oci-image/01_mod.mk +++ b/make/_shared/oci-image/01_mod.mk @@ -15,13 +15,12 @@ oci_platforms ?= linux/amd64,linux/arm/v7,linux/arm64,linux/ppc64le # Use distroless as minimal base image to package the manager binary -# Refer to https://github.com/GoogleContainerTools/distroless for more details -# To get latest SHA run crane digest gcr.io/distroless/static-debian12:nonroot -base_image_static := gcr.io/distroless/static-debian12@sha256:39ae7f0201fee13b777a3e4a5a9326a8889269172c8b4f4289d9f19c831f45f4 +# To get latest SHA run crane digest quay.io/jetstack/base-static:latest +base_image_static := quay.io/jetstack/base-static@sha256:ba3cff0a4cacc5ae564e04c1f645000e8c9234c0f4b09534be1dee7874a42141 # Use custom apko-built image as minimal base image to package the manager binary # To get latest SHA run crane digest quay.io/jetstack/base-static-csi:latest -base_image_csi-static := quay.io/jetstack/base-static-csi@sha256:f8463a8a6d2265a15a982cf3d6cb08b685ab7220828885fbbb528135baa0a951 +base_image_csi-static := quay.io/jetstack/base-static-csi@sha256:54bacd13cccc385ef66730dbc7eb13bdb6a9ff8853e7f551d025ccb0e8c6bf83 ifndef bin_dir $(error bin_dir is not set) @@ -46,7 +45,7 @@ ifeq ($(oci_$1_base_image_flavor),static) else ifeq ($(oci_$1_base_image_flavor),csi-static) oci_$1_base_image := $(base_image_csi-static) else ifeq ($(oci_$1_base_image_flavor),custom) - $$(call fatal_if_undefined,oci_$1_base_image) + $$(call fatal_if_undefined,oci_$1_base_image) else $$(error oci_$1_base_image_flavor has unknown value "$(oci_$1_base_image_flavor)") endif @@ -85,6 +84,10 @@ oci_build_targets := $(build_names:%=oci-build-%) oci_push_targets := $(build_names:%=oci-push-%) oci_maybe_push_targets := $(build_names:%=oci-maybe-push-%) oci_load_targets := $(build_names:%=oci-load-%) +docker_tarball_targets := $(build_names:%=docker-tarball-%) + +$(foreach build_name,$(build_names),$(eval oci_layout_path_$(build_name) := $(bin_dir)/scratch/image/oci-layout-$(build_name).$(oci_$(build_name)_image_tag))) +$(foreach build_name,$(build_names),$(eval docker_tarball_path_$(build_name) := $(CURDIR)/$(oci_layout_path_$(build_name)).docker.tar)) image_tool_dir := $(dir $(lastword $(MAKEFILE_LIST)))/image_tool/ @@ -92,8 +95,7 @@ image_tool_dir := $(dir $(lastword $(MAKEFILE_LIST)))/image_tool/ ## Build the OCI image. ## @category [shared] Build $(oci_build_targets): oci-build-%: | $(NEEDS_KO) $(NEEDS_GO) $(NEEDS_YQ) $(bin_dir)/scratch/image - $(eval oci_layout_path := $(bin_dir)/scratch/image/oci-layout-$*.$(oci_$*_image_tag)) - rm -rf $(CURDIR)/$(oci_layout_path) + rm -rf $(CURDIR)/$(oci_layout_path_$*) @if [ ! -f "$(go_$*_mod_dir)/go.mod" ]; then \ echo "ERROR: Specified directory "$(go_$*_mod_dir)" does not contain a go.mod file."; \ @@ -115,26 +117,26 @@ $(oci_build_targets): oci-build-%: | $(NEEDS_KO) $(NEEDS_GO) $(NEEDS_YQ) $(bin_d $(YQ) '.builds[0].ldflags[0] = "-s"' | \ $(YQ) '.builds[0].ldflags[1] = "-w"' | \ $(YQ) '.builds[0].ldflags[2] = "{{.Env.LDFLAGS}}"' \ - > $(CURDIR)/$(oci_layout_path).ko_config.yaml + > $(CURDIR)/$(oci_layout_path_$*).ko_config.yaml GOWORK=off \ KO_DOCKER_REPO=$(oci_$*_image_name_development) \ KOCACHE=$(CURDIR)/$(bin_dir)/scratch/image/ko_cache \ - KO_CONFIG_PATH=$(CURDIR)/$(oci_layout_path).ko_config.yaml \ + KO_CONFIG_PATH=$(CURDIR)/$(oci_layout_path_$*).ko_config.yaml \ SOURCE_DATE_EPOCH=$(GITEPOCH) \ KO_GO_PATH=$(GO) \ LDFLAGS="$(go_$*_ldflags)" \ $(KO) build $(go_$*_mod_dir)/$(go_$*_main_dir) \ --platform=$(oci_platforms) \ - --oci-layout-path=$(oci_layout_path) \ - --sbom-dir=$(CURDIR)/$(oci_layout_path).sbom \ + --oci-layout-path=$(oci_layout_path_$*) \ + --sbom-dir=$(CURDIR)/$(oci_layout_path_$*).sbom \ --sbom=spdx \ --push=false \ --bare cd $(image_tool_dir) && GOWORK=off $(GO) run . list-digests \ - $(CURDIR)/$(oci_layout_path) \ - > $(CURDIR)/$(oci_layout_path).digests + $(CURDIR)/$(oci_layout_path_$*) \ + > $(CURDIR)/$(oci_layout_path_$*).digests .PHONY: $(oci_push_targets) ## Build and push OCI image. @@ -145,16 +147,15 @@ $(oci_build_targets): oci-build-%: | $(NEEDS_KO) $(NEEDS_GO) $(NEEDS_YQ) $(bin_d ## - :v1.2.3.sig, :sha256-0000001.sig ## @category [shared] Build $(oci_push_targets): oci-push-%: oci-build-% | $(NEEDS_CRANE) $(NEEDS_COSIGN) $(NEEDS_YQ) $(bin_dir)/scratch/image - $(eval oci_layout_path := $(bin_dir)/scratch/image/oci-layout-$*.$(oci_$*_image_tag)) - $(eval image_ref := $(shell head -1 $(CURDIR)/$(oci_layout_path).digests)) + $(eval image_ref := $(shell head -1 $(CURDIR)/$(oci_layout_path_$*).digests)) ifneq ($(RELEASE_DRYRUN),true) if $(CRANE) image digest $(oci_$*_image_name)@$(image_ref) >/dev/null 2>&1; then \ echo "Digest already exists, will retag without resigning."; \ - $(CRANE) push "$(oci_layout_path)" "$(oci_$*_image_name):$(oci_$*_image_tag)"; \ + $(CRANE) push "$(oci_layout_path_$*)" "$(oci_$*_image_name):$(oci_$*_image_tag)"; \ else \ echo "Digest does not yet exist, pushing image and signing."; \ - $(CRANE) push "$(oci_layout_path)" "$(oci_$*_image_name):$(oci_$*_image_tag)"; \ + $(CRANE) push "$(oci_layout_path_$*)" "$(oci_$*_image_name):$(oci_$*_image_tag)"; \ $(COSIGN) sign --yes=true "$(oci_$*_image_name)@$(image_ref)"; \ fi endif @@ -174,9 +175,12 @@ $(oci_maybe_push_targets): oci-maybe-push-%: | $(NEEDS_CRANE) ## Build OCI image for the local architecture and load ## it into the $(kind_cluster_name) kind cluster. ## @category [shared] Build -$(oci_load_targets): oci_platforms := "" -$(oci_load_targets): oci-load-%: oci-build-% | kind-cluster $(NEEDS_KIND) - $(eval oci_layout_path := $(bin_dir)/scratch/image/oci-layout-$*.$(oci_$*_image_tag)) +$(oci_load_targets): oci-load-%: docker-tarball-% | kind-cluster $(NEEDS_KIND) + $(KIND) load image-archive --name $(kind_cluster_name) $(docker_tarball_path_$*) - cd $(image_tool_dir) && GOWORK=off $(GO) run . convert-to-docker-tar $(CURDIR)/$(oci_layout_path) $(CURDIR)/$(oci_layout_path).docker.tar $(oci_$*_image_name_development):$(oci_$*_image_tag) - $(KIND) load image-archive --name $(kind_cluster_name) $(oci_layout_path).docker.tar +## Build Docker tarball image for the local architecture +## @category [shared] Build +.PHONY: $(docker_tarball_targets) +$(docker_tarball_targets): oci_platforms := "" +$(docker_tarball_targets): docker-tarball-%: oci-build-% + cd $(image_tool_dir) && GOWORK=off $(GO) run . convert-to-docker-tar $(CURDIR)/$(oci_layout_path_$*) $(docker_tarball_path_$*) $(oci_$*_image_name_development):$(oci_$*_image_tag) \ No newline at end of file diff --git a/make/_shared/repository-base/base/Makefile b/make/_shared/repository-base/base/Makefile index 0ef56f22..6e1916a5 100644 --- a/make/_shared/repository-base/base/Makefile +++ b/make/_shared/repository-base/base/Makefile @@ -36,6 +36,8 @@ # See https://www.gnu.org/software/make/manual/html_node/Secondary-Expansion.html .SECONDEXPANSION: +# For details on some of these "prelude" settings, see: +# https://clarkgrubb.com/makefile-style-guide MAKEFLAGS += --warn-undefined-variables --no-builtin-rules SHELL := /usr/bin/env bash .SHELLFLAGS := -uo pipefail -c diff --git a/make/_shared/tools/00_mod.mk b/make/_shared/tools/00_mod.mk index 04a79f99..09c4af76 100644 --- a/make/_shared/tools/00_mod.mk +++ b/make/_shared/tools/00_mod.mk @@ -54,6 +54,12 @@ TOOLS += yq=v4.40.5 TOOLS += ko=0.15.1 # https://github.com/protocolbuffers/protobuf/releases TOOLS += protoc=25.2 +# https://github.com/aquasecurity/trivy/releases +TOOLS += trivy=v0.45.0 +# https://github.com/vmware-tanzu/carvel-ytt/releases +TOOLS += ytt=v0.45.4 +# https://github.com/rclone/rclone/releases +TOOLS += rclone=v1.64.0 ### go packages # https://pkg.go.dev/sigs.k8s.io/controller-tools/cmd/controller-gen?tab=versions @@ -96,9 +102,19 @@ TOOLS += goreleaser=v1.23.0 TOOLS += syft=v0.100.0 # https://github.com/cert-manager/helm-tool TOOLS += helm-tool=v0.4.1 +# https://github.com/cert-manager/cmctl +TOOLS += cmctl=2f75014a7c360c319f8c7c8afe8e9ce33fe26dca +# https://pkg.go.dev/github.com/cert-manager/release/cmd/cmrel?tab=versions +TOOLS += cmrel=fa10147dadc8c36718b7b08aed6d8c6418eb2 +# https://github.com/golangci/golangci-lint/releases +TOOLS += golangci-lint=v1.55.2 # https://pkg.go.dev/k8s.io/code-generator/cmd?tab=versions K8S_CODEGEN_VERSION=v0.29.1 +TOOLS += client-gen=$(K8S_CODEGEN_VERSION) +TOOLS += deepcopy-gen=$(K8S_CODEGEN_VERSION) +TOOLS += informer-gen=$(K8S_CODEGEN_VERSION) +TOOLS += lister-gen=$(K8S_CODEGEN_VERSION) TOOLS += applyconfiguration-gen=$(K8S_CODEGEN_VERSION) TOOLS += openapi-gen=$(K8S_CODEGEN_VERSION) TOOLS += defaulter-gen=$(K8S_CODEGEN_VERSION) @@ -278,11 +294,18 @@ GO_DEPENDENCIES += oras=oras.land/oras/cmd/oras GO_DEPENDENCIES += klone=github.com/cert-manager/klone GO_DEPENDENCIES += goreleaser=github.com/goreleaser/goreleaser GO_DEPENDENCIES += syft=github.com/anchore/syft/cmd/syft +GO_DEPENDENCIES += client-gen=k8s.io/code-generator/cmd/client-gen +GO_DEPENDENCIES += deepcopy-gen=k8s.io/code-generator/cmd/deepcopy-gen +GO_DEPENDENCIES += informer-gen=k8s.io/code-generator/cmd/informer-gen +GO_DEPENDENCIES += lister-gen=k8s.io/code-generator/cmd/lister-gen GO_DEPENDENCIES += applyconfiguration-gen=k8s.io/code-generator/cmd/applyconfiguration-gen GO_DEPENDENCIES += openapi-gen=k8s.io/code-generator/cmd/openapi-gen GO_DEPENDENCIES += defaulter-gen=k8s.io/code-generator/cmd/defaulter-gen GO_DEPENDENCIES += conversion-gen=k8s.io/code-generator/cmd/conversion-gen GO_DEPENDENCIES += helm-tool=github.com/cert-manager/helm-tool +GO_DEPENDENCIES += cmctl=github.com/cert-manager/cmctl/v2 +GO_DEPENDENCIES += cmrel=github.com/cert-manager/release/cmd/cmrel +GO_DEPENDENCIES += golangci-lint=github.com/golangci/golangci-lint/cmd/golangci-lint # Additional Go dependencies can be defined to re-use the tooling in this file ADDITIONAL_GO_DEPENDENCIES ?= @@ -459,6 +482,60 @@ $(bin_dir)/downloaded/tools/protoc@$(PROTOC_VERSION)_%: | $(bin_dir)/downloaded/ chmod +x $@ rm -f $@.zip +######### +# trivy # +######### + +TRIVY_linux_amd64_SHA256SUM=b9785455f711e3116c0a97b01ad6be334895143ed680a405e88a4c4c19830d5d +TRIVY_linux_arm64_SHA256SUM=a192edfcef8766fa7e3e96a6a5faf50cd861371785891857471548e4af7cb60b +TRIVY_darwin_amd64_SHA256SUM=997622dee1d07de0764f903b72d16ec4314daaf202d91c957137b4fd1a2f73c3 +TRIVY_darwin_arm64_SHA256SUM=68aa451f395fa5418f5af59ce4081ef71075c857b95a297dc61da49c6a229a45 + +$(bin_dir)/downloaded/tools/trivy@$(TRIVY_VERSION)_%: | $(bin_dir)/downloaded/tools + $(eval OS_AND_ARCH := $(subst darwin,macOS,$*)) + $(eval OS_AND_ARCH := $(subst linux,Linux,$(OS_AND_ARCH))) + $(eval OS_AND_ARCH := $(subst arm64,ARM64,$(OS_AND_ARCH))) + $(eval OS_AND_ARCH := $(subst amd64,64bit,$(OS_AND_ARCH))) + + $(CURL) https://github.com/aquasecurity/trivy/releases/download/$(TRIVY_VERSION)/trivy_$(patsubst v%,%,$(TRIVY_VERSION))_$(subst _,-,$(OS_AND_ARCH)).tar.gz -o $@.tar.gz + $(checkhash_script) $@.tar.gz $(TRIVY_$*_SHA256SUM) + tar xfO $@.tar.gz trivy > $@ + chmod +x $@ + rm $@.tar.gz + +####### +# ytt # +####### + +YTT_linux_amd64_SHA256SUM=9bf62175c7cc0b54f9731a5b87ee40250f0457b1fce1b0b36019c2f8d96db8f8 +YTT_linux_arm64_SHA256SUM=cbfc85f11ffd8e61d63accf799b8997caaebe46ee046290cc1c4d05ed1ab145b +YTT_darwin_amd64_SHA256SUM=2b6d173dec1b6087e22690386474786fd9a2232c4479d8975cc98ae8160eea76 +YTT_darwin_arm64_SHA256SUM=3e6f092bfe7a121d15126a0de6503797818c6b6745fbc97213f519d35fab08f9 + +$(bin_dir)/downloaded/tools/ytt@$(YTT_VERSION)_%: | $(bin_dir)/downloaded/tools + $(CURL) -sSfL https://github.com/vmware-tanzu/carvel-ytt/releases/download/$(YTT_VERSION)/ytt-$(subst _,-,$*) -o $@ + $(checkhash_script) $@ $(YTT_$*_SHA256SUM) + chmod +x $@ + +########## +# rclone # +########## + +RCLONE_linux_amd64_SHA256SUM=7ebdb680e615f690bd52c661487379f9df8de648ecf38743e49fe12c6ace6dc7 +RCLONE_linux_arm64_SHA256SUM=b5a6cb3aef4fd1a2165fb8c21b1b1705f3cb754a202adc81931b47cd39c64749 +RCLONE_darwin_amd64_SHA256SUM=9ef83833296876f3182b87030b4f2e851b56621bad4ca4d7a14753553bb8b640 +RCLONE_darwin_arm64_SHA256SUM=9183f495b28acb12c872175c6af1f6ba8ca677650cb9d2774caefea273294c8a + +$(bin_dir)/downloaded/tools/rclone@$(RCLONE_VERSION)_%: | $(bin_dir)/downloaded/tools + $(eval OS_AND_ARCH := $(subst darwin,osx,$*)) + $(CURL) https://github.com/rclone/rclone/releases/download/$(RCLONE_VERSION)/rclone-$(RCLONE_VERSION)-$(subst _,-,$(OS_AND_ARCH)).zip -o $@.zip + $(checkhash_script) $@.zip $(RCLONE_$*_SHA256SUM) + @# -p writes to stdout, the second file arg specifies the sole file we + @# want to extract + unzip -p $@.zip rclone-$(RCLONE_VERSION)-$(subst _,-,$(OS_AND_ARCH))/rclone > $@ + chmod +x $@ + rm -f $@.zip + ################# # Other Targets # #################