MIN_MAKE_VERSION = 3.82 ifneq ($(MIN_MAKE_VERSION), $(firstword $(sort $(MAKE_VERSION) $(MIN_MAKE_VERSION)))) $(error this project requires make version $(MIN_MAKE_VERSION) or higher) endif SHELL:=/bin/bash # Set the command for running `docker` # -- allows user to override for things like sudo usage or container images DOCKER := docker # Set the first containerd.sock that successfully stats -- fallback to the docker4mac default CONTAINERD_SOCK := $(shell \ $(DOCKER) run -i --rm \ -v /run:/run:ro \ -v /var/run:/var/run:ro \ busybox:latest \ ls 2>/dev/null \ /run/containerd/containerd.sock \ /run/docker/containerd/containerd.sock \ /var/run/containerd/containerd.sock \ /var/run/docker/containerd/containerd.sock \ | head -n1 \ || echo \ /var/run/docker/containerd/containerd.sock \ ) # Set the command for running `ctr` # Use root inside a container with the host containerd socket # This is a form of privilege escalation that avoids interactive sudo during make CTR := $(DOCKER) run -i --rm \ -v $(CONTAINERD_SOCK):/run/containerd/containerd.sock \ linuxkit/containerd:751de142273e1b5d2d247d2832d654ab92e907bc \ ctr UID_GID?=$(shell id -u):$(shell id -g) FIRECRACKER_VERSION:=$(shell cat hack/FIRECRACKER_VERSION) GO_VERSION=1.14.2 DOCKER_USER?=weaveworks IMAGE=$(DOCKER_USER)/ignite GIT_VERSION:=$(shell DOCKER_USER=$(DOCKER_USER) hack/ldflags.sh --version-only) IMAGE_DEV_TAG=dev IMAGE_TAG:=$(shell IGNITE_GIT_VERSION=$(GIT_VERSION) DOCKER_USER=$(DOCKER_USER) hack/ldflags.sh --image-tag-only) # IS_DIRTY is 1 if the tree state is dirty, otherwise 0 IS_DIRTY:=$(shell echo ${GIT_VERSION} | grep -c dirty) PROJECT = github.com/weaveworks/ignite APIS_DIR = ${PROJECT}/pkg/apis API_DIRS = ${APIS_DIR}/ignite,${APIS_DIR}/ignite/v1alpha2,${APIS_DIR}/ignite/v1alpha3,${APIS_DIR}/meta/v1alpha1 CACHE_DIR = $(shell pwd)/bin/cache # Specifies if this is a CI build or not; if it is, it will save the docker image created to bin/$(GOARCH)/image.tar IS_CI_BUILD ?= 0 # Unset any GOFLAGS that would interfere with the build undefine GOFLAGS ## Multi-platform-related stuff # Ignore GOARCH from the environment for the query, otherwise it results in the environment's GOARCH GOHOSTARCH := $(shell GOARCH= go env GOARCH 2>/dev/null || echo "amd64") GOARCH ?= amd64 GOARCH_LIST = amd64 arm64 QEMUVERSION=v4.2.0-6 ifeq ($(GOARCH),amd64) QEMUARCH=amd64 BASEIMAGE=alpine:3.11 FIRECRACKER_ARCH_SUFFIX=-x86_64 endif ifeq ($(GOARCH),arm64) QEMUARCH=aarch64 BASEIMAGE=arm64v8/alpine:3.11 FIRECRACKER_ARCH_SUFFIX=-aarch64 endif E2E_REGEX := Test E2E_COUNT := 1 TEST_COUNT := 1 # Project packages. TEST_REQUIRES_ROOT_PACKAGES="$(PROJECT)/pkg/runtime/containerd" TEST_E2E_PACKAGES="$(PROJECT)/e2e" # Default is to build all the binaries for this architecture all: build-all-$(GOARCH) install: ignite sudo cp bin/$(GOARCH)/ignite /usr/local/bin install-all: install ignited sudo cp bin/$(GOARCH)/ignited /usr/local/bin BINARIES = ignite ignited ignite-spawn $(BINARIES): $(MAKE) go-make TARGETS="bin/$(GOARCH)/$@" # Always update the image when ignite-spawn is updated [[ $@ == "ignite-spawn" ]] && $(MAKE) image || exit 0 GO_MAKE_TARGET := go-in-docker # user can override to "local" go-make: # MAKEFLAGS must be set manually in case the sub-make is in a container: $(MAKE) $(GO_MAKE_TARGET) COMMAND="$(MAKE) \"MAKEFLAGS=$(MAKEFLAGS)\" $(TARGETS)" local: # Do not use directly -- use $(GO_MAKE_TARGET) $(COMMAND) go-in-docker: # Do not use directly -- use $(GO_MAKE_TARGET) mkdir -p $(CACHE_DIR)/go $(CACHE_DIR)/cache $(DOCKER) run -it --rm \ -v $(CACHE_DIR)/go:/go \ -v $(CACHE_DIR)/cache:/.cache/go-build \ -v $(shell pwd):/go/src/${PROJECT} \ -w /go/src/${PROJECT} \ -u $(shell id -u):$(shell id -g) \ -e GOARCH=$(GOARCH) \ golang:$(GO_VERSION) \ $(COMMAND) # Make make execute this target although the file already exists. .PHONY: bin/$(GOARCH)/ignite bin/$(GOARCH)/ignite-spawn bin/$(GOARCH)/ignited bin/$(GOARCH)/ignite bin/$(GOARCH)/ignited bin/$(GOARCH)/ignite-spawn: bin/$(GOARCH)/%: CGO_ENABLED=0 GOARCH=$(GOARCH) go build -mod=vendor -ldflags "$(shell IGNITE_GIT_VERSION=$(GIT_VERSION) DOCKER_USER=$(DOCKER_USER) ./hack/ldflags.sh)" -o bin/$(GOARCH)/$* ./cmd/$* ifeq ($(GOARCH),$(GOHOSTARCH)) ln -sf ./$(GOARCH)/$* bin/$* endif .PHONY: bin/$(GOARCH)/Dockerfile image: bin/$(GOARCH)/Dockerfile bin/$(GOARCH)/Dockerfile: qemu sed -e "s|QEMUARCH|$(QEMUARCH)|g;s|BASEIMAGE|$(BASEIMAGE)|g;" Dockerfile > bin/$(GOARCH)/Dockerfile ifeq ($(GOARCH),amd64) # When building for amd64, remove the qemu stuff, it has no part in the amd64 image sed -i "/qemu/d" bin/$(GOARCH)/Dockerfile else # Register /usr/bin/qemu-ARCH-static as the handler for non-x86 binaries in the kernel $(DOCKER) run --rm --privileged multiarch/qemu-user-static:register --reset endif $(DOCKER) build -t $(IMAGE):${IMAGE_DEV_TAG}-$(GOARCH) \ --build-arg FIRECRACKER_VERSION=${FIRECRACKER_VERSION} \ --build-arg FIRECRACKER_ARCH_SUFFIX=${FIRECRACKER_ARCH_SUFFIX} bin/$(GOARCH) $(DOCKER) image save $(IMAGE):${IMAGE_DEV_TAG}-$(GOARCH) \ | $(CTR) -n firecracker image import - ifeq ($(GOARCH),$(GOHOSTARCH)) # Only tag the development image if its architecture matches the host $(DOCKER) tag $(IMAGE):${IMAGE_DEV_TAG}-$(GOARCH) $(IMAGE):${IMAGE_DEV_TAG} $(DOCKER) image save $(IMAGE):${IMAGE_DEV_TAG} \ | $(CTR) -n firecracker image import - endif ifneq (${IMAGE_TAG},) ifeq ($(IS_DIRTY),0) $(DOCKER) tag $(IMAGE):${IMAGE_DEV_TAG}-$(GOARCH) $(IMAGE):${IMAGE_TAG}-$(GOARCH) $(DOCKER) image save $(IMAGE):${IMAGE_TAG}-$(GOARCH) \ | $(CTR) -n firecracker image import - ifeq ($(GOARCH),$(GOHOSTARCH)) # For dev builds for a clean (non-dirty) environment; "simulate" that # a manifest list has been built by tagging the docker image $(DOCKER) tag $(IMAGE):${IMAGE_TAG}-$(GOARCH) $(IMAGE):${IMAGE_TAG} $(DOCKER) image save $(IMAGE):${IMAGE_TAG} \ | $(CTR) -n firecracker image import - endif endif ifeq ($(IS_CI_BUILD),1) $(DOCKER) save $(IMAGE):${IMAGE_TAG}-$(GOARCH) -o bin/$(GOARCH)/image.tar endif endif build-all: $(addprefix build-all-,$(GOARCH_LIST)) build-all-%: $(MAKE) GOARCH=$* $(BINARIES) release: build-all ifneq ($(IS_DIRTY),0) $(error "cannot release dirty tree") endif mkdir -p bin/releases/${GIT_VERSION} cp -r bin/{amd64,arm64} bin/releases/${GIT_VERSION} DOCKER=$(DOCKER) hack/push-manifest-list.sh $(IMAGE):$(IMAGE_TAG) $(GOARCH_LIST) tidy: /go/bin/goimports go mod tidy go mod vendor hack/generate-client.sh gofmt -s -w pkg cmd goimports -w pkg cmd go run hack/cobra.go tidy-in-docker: $(MAKE) go-make TARGETS="tidy" # Exclude e2e tests, incomplete package pkg/dm and packages that require root. test: go test -mod=vendor -v $(shell go list ./... | grep -v /e2e | grep -v /pkg/dm | grep -v $(TEST_REQUIRES_ROOT_PACKAGES)) -count=$(TEST_COUNT) test-in-docker: $(MAKE) go-make TARGETS="test" # Run tests that require root. root-test: sudo $(shell which go) test -mod=vendor -v $(TEST_REQUIRES_ROOT_PACKAGES) -count=$(TEST_COUNT) graph: hack/graph.sh api-docs: godoc2md cd pkg/apis/ && for gv in */v1*; do \ GROUPVERSION=$$gv GROUP_VERSION=$$(echo $$gv | sed 's|/|_|g') \ $(MAKE) -C ../../ api-doc; done api-doc: mkdir -p docs/api bin/tmp/${GROUPVERSION} mv $(shell pwd)/pkg/apis/${GROUPVERSION}/zz_generated* bin/tmp/${GROUPVERSION} $(MAKE) $(GO_MAKE_TARGET) COMMAND="godoc2md /go/src/${PROJECT}/pkg/apis/${GROUPVERSION} > bin/tmp/${GROUP_VERSION}.md" sed -e "s|src/target|pkg/apis/${GROUPVERSION}|g;s|/go/src/||g" -i bin/tmp/${GROUP_VERSION}.md sed -e "s|(/pkg/apis|(https://github.com/weaveworks/ignite/tree/master/pkg/apis|g" -i bin/tmp/${GROUP_VERSION}.md mv bin/tmp/${GROUPVERSION}/*.go $(shell pwd)/pkg/apis/${GROUPVERSION}/ rm -r bin/tmp/${GROUPVERSION} # Format the docs with pandoc $(DOCKER) run -it --rm \ -v $(shell pwd):/data \ -u $(shell id -u):$(shell id -g) \ pandoc/core \ --from markdown \ --to gfm \ bin/tmp/${GROUP_VERSION}.md > docs/api/${GROUP_VERSION}.md autogen: $(MAKE) go-make TARGETS="go-autogen" go-autogen: /go/bin/deepcopy-gen /go/bin/defaulter-gen /go/bin/conversion-gen /go/bin/openapi-gen # Let the boilerplate be empty touch /tmp/boilerplate # Need to do this, otherwise go mod thinks the state is dirty (for some reason) go mod vendor /go/bin/deepcopy-gen \ --input-dirs ${API_DIRS} \ --bounding-dirs ${APIS_DIR} \ -O zz_generated.deepcopy \ -h /tmp/boilerplate /go/bin/defaulter-gen \ --input-dirs ${API_DIRS} \ -O zz_generated.defaults \ -h /tmp/boilerplate /go/bin/conversion-gen \ --input-dirs ${API_DIRS} \ -O zz_generated.conversion \ -h /tmp/boilerplate /go/bin/openapi-gen \ --input-dirs ${API_DIRS} \ --output-package ${PROJECT}/pkg/openapi \ --report-filename pkg/openapi/violations.txt \ -h /tmp/boilerplate # These commands modify the env a bit, clean up after us too $(MAKE) tidy /go/bin/deepcopy-gen /go/bin/defaulter-gen /go/bin/conversion-gen: /go/bin/%: vendor go get k8s.io/code-generator/cmd/$* /go/bin/openapi-gen: go get k8s.io/kube-openapi/cmd/openapi-gen godoc2md: bin/cache/go/bin/godoc2md bin/cache/go/bin/godoc2md: mkdir -p $$(dirname $@) curl -sSL https://github.com/luxas/godoc2md/releases/download/v0.1.0/godoc2md > $@ chmod +x $@ /go/bin/goimports: go get golang.org/x/tools/cmd/goimports # QEMU stuff qemu: bin/$(GOARCH)/qemu-$(QEMUARCH)-static bin/$(GOARCH)/qemu-$(QEMUARCH)-static: mkdir -p bin/$(GOARCH) ifneq ($(GOARCH),amd64) curl -sSL https://github.com/multiarch/qemu-user-static/releases/download/$(QEMUVERSION)/x86_64_qemu-$(QEMUARCH)-static.tar.gz | tar -xz -C bin/$(GOARCH) chmod 0755 $@ endif # Read the docs stuff bin/docs/builder-image.tar: mkdir -p bin/docs $(DOCKER) build -t ignite-docs-builder -f docs/Dockerfile.build docs $(DOCKER) save ignite-docs-builder -o $@ e2e: build-all e2e-nobuild e2e-nobuild: sudo IGNITE_E2E_HOME=$(shell pwd) \ $(shell which go) test \ $(TEST_E2E_PACKAGES) -v -mod=vendor \ -count $(E2E_COUNT) \ -run $(E2E_REGEX) docs-deps: pip3 install -r docs/requirements.txt serve-docs: docs-deps mkdocs serve