diff --git a/.yetus/blanks-tabs.txt b/.yetus/blanks-tabs.txt index 865c555b37..b67192f687 100644 --- a/.yetus/blanks-tabs.txt +++ b/.yetus/blanks-tabs.txt @@ -1,4 +1,5 @@ .*Makefile.* +.*\.mk .*\.go .*\.dts .*\.md diff --git a/Makefile b/Makefile index 89912b4230..d0357cbd3b 100644 --- a/Makefile +++ b/Makefile @@ -18,9 +18,6 @@ uniq = $(if $1,$(firstword $1) $(call uniq,$(filter-out $(firstword $1),$1))) # you are not supposed to tweak these variables -- they are effectively R/O HV_DEFAULT=kvm -# linuxkit version. This **must** be a published semver version so it can be downloaded already compiled from -# the release page at https://github.com/linuxkit/linuxkit/releases -LINUXKIT_VERSION=v1.8.1 GOVER ?= 1.24.1 PKGBASE=github.com/lf-edge/eve GOMODULE=$(PKGBASE)/pkg/pillar @@ -381,11 +378,10 @@ LINUXKIT_PKG_TARGET=build # buildkitd.toml configuration file can control a configuration of the buildkit daemon # it is used for example to setup a Docker registry mirror for CI to speedup the builds -# this option can be overridden by setting BUILDKIT_CONFIG_FILE variable on make command line -BUILDKIT_CONFIG_FILE ?= /etc/buildkit/buildkitd.toml -BUILDKIT_CONFIG_OPTS := $(if $(filter manifest,$(LINUXKIT_PKG_TARGET)),,$(if $(wildcard $(BUILDKIT_CONFIG_FILE)),--builder-config $(BUILDKIT_CONFIG_FILE),)) - -LINUXKIT_OPTS=$(if $(strip $(EVE_HASH)),--hash) $(EVE_HASH) $(if $(strip $(EVE_REL)),--release) $(EVE_REL) $(BUILDKIT_CONFIG_OPTS) +# defaults to /etc/buildkit/buildkitd.toml if it exists; override via LINUXKIT_BUILDER_CONFIG +LINUXKIT_BUILDER_CONFIG ?= $(wildcard /etc/buildkit/buildkitd.toml) +export LINUXKIT_BUILDER_CONFIG +LINUXKIT_OPTS=$(if $(strip $(EVE_HASH)),--hash) $(EVE_HASH) $(if $(strip $(EVE_REL)),--release) $(EVE_REL) ifdef LIVE_FAST # Check the makerootfs.sh and the linuxkit tool invocation, the --input-tar @@ -465,14 +461,6 @@ ifeq ($(LINUXKIT_PKG_TARGET),push) EVE_REL:=$(EVE_REL)$(if $(TAGPLAT),-$(TAGPLAT),) endif -# Check for a custom registry (used for development purposes) -ifdef REGISTRY -LINUXKIT_ORG_TARGET=--org $(REGISTRY)/lfedge -export LINUXKIT_ORG_TARGET -else -LINUXKIT_ORG_TARGET= -endif - # The rootfs partition size is set to 512MB after 10.2.0 release (see commit 719b4d516) # Before 10.2.0 it was 300MB. We must maintain compatibility with older versions so rootfs size cannot exceed 300MB. # 'k' and nvidia are not affected by this limitation because there no installation of kubevirt/k3s prior to 10.2.0 @@ -637,8 +625,8 @@ $(UBOOT_IMG): PKG=u-boot $(BSP_IMX_PART): PKG=bsp-imx $(EFI_PART) $(BOOT_PART) $(INITRD_IMG) $(IPXE_IMG) $(BIOS_IMG) $(UBOOT_IMG) $(BSP_IMX_PART): $(LINUXKIT) | $(INSTALLER) mkdir -p $(dir $@) - $(LINUXKIT) pkg build --pull $(LINUXKIT_ORG_TARGET) $(LINUXKIT_OPTS) --platforms linux/$(ZARCH) pkg/$(PKG) # running linuxkit pkg build _without_ force ensures that we either pull it down or build it. - cd $(dir $@) && $(LINUXKIT) cache export --platform linux/$(DOCKER_ARCH_TAG) --format filesystem --outfile - $(shell $(LINUXKIT) pkg $(LINUXKIT_ORG_TARGET) show-tag pkg/$(PKG)) | tar xvf - $(notdir $@) + $(LINUXKIT) pkg build --pull $(LINUXKIT_OPTS) --platforms linux/$(ZARCH) pkg/$(PKG) # running linuxkit pkg build _without_ force ensures that we either pull it down or build it. + cd $(dir $@) && $(LINUXKIT) cache export --platform linux/$(DOCKER_ARCH_TAG) --format filesystem --outfile - $(shell $(LINUXKIT) pkg show-tag pkg/$(PKG)) | tar xvf - $(notdir $@) $(QUIET): $@: Succeeded # run swtpm if TPM flag defined @@ -899,9 +887,9 @@ compare_sbom_collected_sources: $(SBOM) $(COLLECTED_SOURCES) $(COMPARESOURCES) publish_sources: $(COLLECTED_SOURCES) $(QUIET): $@: Begin cp pkg/sources/* $(SOURCES_DIR) - $(LINUXKIT) $(DASH_V) pkg $(LINUXKIT_PKG_TARGET) $(LINUXKIT_ORG_TARGET) $(LINUXKIT_OPTS) --platforms linux/$(ZARCH) --hash-path $(CURDIR) --hash $(ROOTFS_VERSION)-$(HV) --docker $(if $(strip $(EVE_REL)),--release) $(EVE_REL)$(if $(strip $(EVE_REL)),-$(HV)) $(SOURCES_DIR) $| + $(LINUXKIT) $(DASH_V) pkg $(LINUXKIT_PKG_TARGET) $(LINUXKIT_OPTS) --platforms linux/$(ZARCH) --hash-path $(CURDIR) --hash $(ROOTFS_VERSION)-$(HV) --docker $(if $(strip $(EVE_REL)),--release) $(EVE_REL)$(if $(strip $(EVE_REL)),-$(HV)) $(SOURCES_DIR) $| $(QUIET)if [ -n "$(EVE_REL)" ] && [ $(HV) = $(HV_DEFAULT) ]; then \ - $(LINUXKIT) $(DASH_V) pkg $(LINUXKIT_PKG_TARGET) $(LINUXKIT_ORG_TARGET) $(LINUXKIT_OPTS) --platforms linux/$(ZARCH) --hash-path $(CURDIR) --hash $(EVE_REL)-$(HV) --docker --release $(EVE_REL) $(SOURCES_DIR) $| ;\ + $(LINUXKIT) $(DASH_V) pkg $(LINUXKIT_PKG_TARGET) $(LINUXKIT_OPTS) --platforms linux/$(ZARCH) --hash-path $(CURDIR) --hash $(EVE_REL)-$(HV) --docker --release $(EVE_REL) $(SOURCES_DIR) $| ;\ fi $(QUIET): $@: Succeeded @@ -953,7 +941,7 @@ pkg/kernel: $(QUIET): $@: No-op pkg/kernel pkg/kube/external-boot-image.tar: pkg/external-boot-image - $(eval BOOT_IMAGE_TAG := $(shell $(LINUXKIT) pkg $(LINUXKIT_ORG_TARGET) show-tag --canonical pkg/external-boot-image)) + $(eval BOOT_IMAGE_TAG := $(shell $(LINUXKIT) pkg show-tag --canonical pkg/external-boot-image)) $(eval CACHE_CONTENT := $(shell $(LINUXKIT) cache ls 2>&1)) $(if $(filter $(BOOT_IMAGE_TAG),$(CACHE_CONTENT)),,$(LINUXKIT) cache pull $(BOOT_IMAGE_TAG)) $(MAKE) cache-export IMAGE=$(BOOT_IMAGE_TAG) OUTFILE=pkg/kube/external-boot-image.tar @@ -971,9 +959,9 @@ eve: $(INSTALLER) $(EVE_ARTIFACTS) current $(RUNME) $(BUILD_YML) | $(BUILD_DIR) $(QUIET): "$@: Begin: EVE_REL=$(EVE_REL), HV=$(HV), LINUXKIT_PKG_TARGET=$(LINUXKIT_PKG_TARGET)" cp images/out/*.yml $| $(PARSE_PKGS) pkg/eve/Dockerfile.in > $|/Dockerfile - $(LINUXKIT) $(DASH_V) pkg $(LINUXKIT_PKG_TARGET) $(LINUXKIT_ORG_TARGET) $(LINUXKIT_OPTS) --platforms linux/$(ZARCH) --hash-path $(CURDIR) --hash $(ROOTFS_VERSION)-$(HV) --docker $(if $(strip $(EVE_REL)),--release) $(EVE_REL)$(if $(strip $(EVE_REL)),-$(HV)) $(FORCE_BUILD) $| + $(LINUXKIT) $(DASH_V) pkg $(LINUXKIT_PKG_TARGET) $(LINUXKIT_OPTS) --platforms linux/$(ZARCH) --hash-path $(CURDIR) --hash $(ROOTFS_VERSION)-$(HV) --docker $(if $(strip $(EVE_REL)),--release) $(EVE_REL)$(if $(strip $(EVE_REL)),-$(HV)) $(FORCE_BUILD) $| $(QUIET)if [ -n "$(EVE_REL)" ] && [ $(HV) = $(HV_DEFAULT) ]; then \ - $(LINUXKIT) $(DASH_V) pkg $(LINUXKIT_PKG_TARGET) $(LINUXKIT_ORG_TARGET) $(LINUXKIT_OPTS) --platforms linux/$(ZARCH) --hash-path $(CURDIR) --hash $(EVE_REL)-$(if $(TAGPLAT),$(TAGPLAT)-)$(HV) --docker --release $(EVE_REL) $(FORCE_BUILD) $| ;\ + $(LINUXKIT) $(DASH_V) pkg $(LINUXKIT_PKG_TARGET) $(LINUXKIT_OPTS) --platforms linux/$(ZARCH) --hash-path $(CURDIR) --hash $(EVE_REL)-$(if $(TAGPLAT),$(TAGPLAT)-)$(HV) --docker --release $(EVE_REL) $(FORCE_BUILD) $| ;\ fi $(QUIET): $@: Succeeded @@ -1004,7 +992,7 @@ cache-export-docker-load: $(LINUXKIT) rm -rf ${TARFILE} %-cache-export-docker-load: $(LINUXKIT) pkg/% - $(eval IMAGE_TAG := $(shell $(LINUXKIT) pkg $(LINUXKIT_ORG_TARGET) show-tag --canonical pkg/$*)) + $(eval IMAGE_TAG := $(shell $(LINUXKIT) pkg show-tag --canonical pkg/$*)) $(eval CACHE_CONTENT := $(shell $(LINUXKIT) cache ls 2>&1)) $(if $(filter $(IMAGE_TAG),$(CACHE_CONTENT)),$(MAKE) cache-export-docker-load IMAGE=$(IMAGE_TAG),@echo "Missing image $(IMAGE_TAG) in cache") @@ -1056,32 +1044,21 @@ shell: $(GOBUILDER) $(QUIET)DOCKER_GO_ARGS=-t ; $(DOCKER_GO) bash $(GOTREE) $(GOMODULE) # -# Linuxkit +# Parallel build lock — a unique per-build sentinel file used to serialize +# operations that must not run concurrently (e.g. docker image prune). # -.PHONY: linuxkit -linuxkit: $(LINUXKIT) - -LINUXKIT_SOURCE=https://github.com/linuxkit/linuxkit -PARALLEL_BUILD_LOCK_FNAME:=$(shell mktemp -u eve-parallel-build-XXXXXX) -PARALLEL_BUILD_LOCK:=$(BUILD_DIR)/$(PARALLEL_BUILD_LOCK_FNAME) +PARALLEL_BUILD_LOCK_FNAME := $(shell mktemp -u eve-parallel-build-XXXXXX) +PARALLEL_BUILD_LOCK := $(BUILD_DIR)/$(PARALLEL_BUILD_LOCK_FNAME) $(PARALLEL_BUILD_LOCK): $(BUILD_DIR) $(QUIET): "$@: Begin: PARALLEL_BUILD_LOCK=$(PARALLEL_BUILD_LOCK)" @touch $@ $(QUIET): $@: Succeeded -# $(PARALLEL_BUILD_LOCK) is unique for each build, so we can use is a flag -# to cleanup possibly old linuxkit-builder containers because this -# target is executed only once per build for both secuential and parallel builds -$(LINUXKIT): $(BUILDTOOLS_BIN)/linuxkit-$(LINUXKIT_VERSION) $(PARALLEL_BUILD_LOCK) - $(QUIET)docker stop linuxkit-builder >/dev/null 2>&1 || true - $(QUIET)docker rm linuxkit-builder >/dev/null 2>&1 || true - $(QUIET)ln -sf $(notdir $<) $@ - $(QUIET): $@: Succeeded - -$(BUILDTOOLS_BIN)/linuxkit-$(LINUXKIT_VERSION): - $(QUIET) curl -L -o $@ $(LINUXKIT_SOURCE)/releases/download/$(LINUXKIT_VERSION)/linuxkit-$(LOCAL_GOOS)-$(HOSTARCH) && chmod +x $@ - $(QUIET): $@: Succeeded +# +# Linuxkit +# +include $(CURDIR)/mk/linuxkit.mk $(GOBUILDER): $(QUIET): "$@: Begin: GOBUILDER=$(GOBUILDER)" @@ -1169,7 +1146,7 @@ eve-%: pkg/%/Dockerfile $(LINUXKIT) $(RESCAN_DEPS) $(eval LINUXKIT_BUILD_PLATFORMS_LIST := $(call uniq,linux/$(ZARCH) $(if $(filter $(PKGS_HOSTARCH),$*),linux/$(HOSTARCH),))) $(eval LINUXKIT_BUILD_PLATFORMS := --platforms $(subst $(space),$(comma),$(strip $(LINUXKIT_BUILD_PLATFORMS_LIST)))) $(eval LINUXKIT_FLAGS := $(if $(filter manifest,$(LINUXKIT_PKG_TARGET)),,$(FORCE_BUILD) $(LINUXKIT_DOCKER_LOAD) $(LINUXKIT_BUILD_PLATFORMS))) - $(QUIET)$(LINUXKIT) $(DASH_V) pkg $(LINUXKIT_PKG_TARGET) $(LINUXKIT_ORG_TARGET) $(LINUXKIT_OPTS) $(LINUXKIT_EXTRA_BUILD_ARGS) $(LINUXKIT_FLAGS) --build-yml $(call get_pkg_build_yml,$*) pkg/$* + $(QUIET)$(LINUXKIT) $(DASH_V) pkg $(LINUXKIT_PKG_TARGET) $(LINUXKIT_OPTS) $(LINUXKIT_EXTRA_BUILD_ARGS) $(LINUXKIT_FLAGS) --build-yml $(call get_pkg_build_yml,$*) pkg/$* $(QUIET)if [ -n "$(PRUNE)" ]; then \ flock $(PARALLEL_BUILD_LOCK) docker image prune -f; \ fi @@ -1265,7 +1242,7 @@ $(ROOTFS_FULL_NAME)-%-$(ZARCH).$(ROOTFS_FORMAT): $(ROOTFS_IMG_BASE).img $(QUIET): $@: Succeeded %-show-tag: - @$(LINUXKIT) pkg $(LINUXKIT_ORG_TARGET) show-tag --canonical pkg/$* + @$(LINUXKIT) pkg show-tag --canonical pkg/$* %Gopkg.lock: %Gopkg.toml | $(GOBUILDER) @$(DOCKER_GO) "dep ensure -update $(GODEP_NAME)" $(dir $@) diff --git a/docs/BUILD.md b/docs/BUILD.md index dd05937e5d..28ac3deaf9 100644 --- a/docs/BUILD.md +++ b/docs/BUILD.md @@ -1008,7 +1008,14 @@ The whole flow looks like this: All containers built by the EVE project are available in the official [LF-Edge's Docker HUB](https://hub.docker.com/u/lfedge). However, developers might want to pull and/or push all containers to a local container registry for debugging and development purposes. -EVE's build system allows to override the default docker registry through the `REGISTRY` variable. For example: +EVE's build system provides two environment variables for this: + +* `LINUXKIT_PKG_ORG` — overrides the registry organization used for pushing and pulling package images. +* `LINUXKIT_MIRROR` — configures a pull-through proxy (registry mirror) to cache upstream images locally and speed up builds. + +### Pushing to a custom registry + +Use `LINUXKIT_PKG_ORG` to redirect package pushes to a local registry. For example: 1. Start docker registry at local port 5001 (to not clash with a running docker registry) @@ -1019,13 +1026,13 @@ EVE's build system allows to override the default docker registry through the `R 1. Build EVE with the local registry URL ```sh - make REGISTRY="localhost:5001" pkgs eve + make LINUXKIT_PKG_ORG="localhost:5001/lfedge" pkgs eve ``` 1. Push packages to the local registry ```sh - make REGISTRY="localhost:5001" LINUXKIT_PKG_TARGET=push pkgs eve + make LINUXKIT_PKG_ORG="localhost:5001/lfedge" LINUXKIT_PKG_TARGET=push pkgs eve ``` 1. A list of packages pushed to the local registry can be retrieved with the following command: @@ -1065,3 +1072,13 @@ EVE's build system allows to override the default docker registry through the `R ] } ``` + +### Using a pull-through proxy + +To speed up builds by caching upstream images locally, use `LINUXKIT_MIRROR` to point at a pull-through registry mirror: + +```sh +make LINUXKIT_MIRROR="http://localhost:5001" pkgs eve +``` + +This tells linuxkit to pull base images through the mirror instead of hitting Docker Hub directly, which is useful in CI environments or when working with rate-limited registries. diff --git a/mk/linuxkit.mk b/mk/linuxkit.mk new file mode 100644 index 0000000000..a8fcccebc7 --- /dev/null +++ b/mk/linuxkit.mk @@ -0,0 +1,78 @@ +# Copyright (c) 2026 Zededa, Inc. +# SPDX-License-Identifier: Apache-2.0 +# +# mk/linuxkit.mk — linuxkit binary acquisition +# +# Priority (first match wins): +# 1. LINUXKIT_SRC=/path build from local source tree, no network +# 2. LINUXKIT_GIT_URL set clone at LINUXKIT_GIT_REF (commit hash) and build +# 3. (neither) download official release binary +# +# Set LINUXKIT_GIT_URL="" to use the release binary (case 3). +# LINUXKIT_VERSION must remain a published semver tag — it is used only for +# the release-download URL in case 3. + +# linuxkit version. This **must** be a published semver version so it can be +# downloaded already compiled from the release page at +# https://github.com/linuxkit/linuxkit/releases +LINUXKIT_VERSION ?= v1.8.1 +LINUXKIT_SOURCE ?= https://github.com/linuxkit/linuxkit + +# LINUXKIT_GIT_REF must be a commit hash (reproducible, no ls-remote needed). +# Update by running: git ls-remote https://github.com/linuxkit/linuxkit master +LINUXKIT_GIT_URL ?= https://github.com/linuxkit/linuxkit +LINUXKIT_GIT_REF ?= 4cfb70d3cc9256024bb0d4de760c631df0ad06f6 +# Optional local source tree — takes priority over LINUXKIT_GIT_URL. +# make LINUXKIT_SRC=/path/to/linuxkit +LINUXKIT_SRC ?= + +.PHONY: linuxkit +linuxkit: $(LINUXKIT) + +ifneq ($(LINUXKIT_SRC),) +# ── Case 1: local source tree ──────────────────────────────────────────────── +# Rebuild whenever Go sources change; no network access needed. +$(LINUXKIT): $(PARALLEL_BUILD_LOCK) | $(BUILDTOOLS_BIN) + @echo "Building linuxkit from local source: $(LINUXKIT_SRC)" + $(QUIET)$(MAKE) -C $(LINUXKIT_SRC) local-build LOCAL_TARGET=$(abspath $@) + $(QUIET)docker stop linuxkit-builder >/dev/null 2>&1 || true + $(QUIET)docker rm linuxkit-builder >/dev/null 2>&1 || true + $(QUIET): $@: Succeeded + +else ifneq ($(LINUXKIT_GIT_URL),) +# ── Case 2: commit hash from a git repo ────────────────────────────────────── +# The hash is used directly as the versioned binary name — no network call at +# parse time. Make skips the recipe if the binary already exists (cached). +_LK_VERSION := $(shell printf '%s' '$(LINUXKIT_GIT_REF)' | cut -c1-12) + +$(LINUXKIT): $(BUILDTOOLS_BIN)/linuxkit-$(_LK_VERSION) $(PARALLEL_BUILD_LOCK) + $(QUIET)docker stop linuxkit-builder >/dev/null 2>&1 || true + $(QUIET)docker rm linuxkit-builder >/dev/null 2>&1 || true + $(QUIET)ln -sf $(notdir $<) $@ + $(QUIET): $@: Succeeded + +$(BUILDTOOLS_BIN)/linuxkit-$(_LK_VERSION): | $(BUILDTOOLS_BIN) + @echo "Building linuxkit from $(LINUXKIT_GIT_URL) at $(LINUXKIT_GIT_REF)" + $(QUIET)tmp=$$(mktemp -d) && \ + git clone --filter=blob:none $(LINUXKIT_GIT_URL) $$tmp && \ + git -C $$tmp checkout $(LINUXKIT_GIT_REF) && \ + $(MAKE) -C $$tmp local-build LOCAL_TARGET=$(abspath $@) && \ + rm -rf $$tmp + $(QUIET): $@: Succeeded + +else +# ── Case 3: download upstream release binary ────────────────────────────────── +$(LINUXKIT): $(BUILDTOOLS_BIN)/linuxkit-$(LINUXKIT_VERSION) $(PARALLEL_BUILD_LOCK) + $(QUIET)docker stop linuxkit-builder >/dev/null 2>&1 || true + $(QUIET)docker rm linuxkit-builder >/dev/null 2>&1 || true + $(QUIET)ln -sf $(notdir $<) $@ + $(QUIET): $@: Succeeded + +$(BUILDTOOLS_BIN)/linuxkit-$(LINUXKIT_VERSION): | $(BUILDTOOLS_BIN) + @echo "Downloading linuxkit release $(LINUXKIT_VERSION)" + $(QUIET)curl -fsSL -o $@ \ + $(LINUXKIT_SOURCE)/releases/download/$(LINUXKIT_VERSION)/linuxkit-$(LOCAL_GOOS)-$(HOSTARCH) \ + && chmod +x $@ + $(QUIET): $@: Succeeded + +endif diff --git a/tools/collect-sources.sh b/tools/collect-sources.sh index 560a7bcadc..5b8ea2a90b 100755 --- a/tools/collect-sources.sh +++ b/tools/collect-sources.sh @@ -37,4 +37,5 @@ echo "${outfile}" "${eve}/build-tools/bin/go-sources-and-licenses" sources -b "${tmproot}" --find --out "${tmpout}" --prefix golang --template 'golang,{{.Module}}@{{.Version}},{{.Version}},{{.Path}}' } > "${manifest}" tar "${tar_opts}" -zcf "${outfile}" -C "${tmpout}" . +chmod -R u+w "${tmproot}" rm -rf "${tmproot}" "${tmpout}"