1、Makefile简介
Makefile 是一种用于自动化构建软件项目的文件。它通常用于管理和执行编译、链接、测试等一系列任务,以提高开发效率。
1.1 目标与依赖
1.1.1目标(Targets)
- 代表一个任务或一个文件的生成结果。例如,编译生成的可执行文件、库文件等都可以是目标。
- 常见的目标有 “all”(表示构建整个项目)、“clean”(用于清理生成的文件)等。
1.1.2 依赖(Dependencies)
- 目标所依赖的其他文件或目标。只有当依赖发生变化时,才会重新执行生成目标的命令。
- 例如,一个可执行文件可能依赖于多个源文件和库文件。
1.2 规则与命令
1.2.1 规则(Rules)
- 描述了如何从依赖生成目标。通常由目标、依赖和命令三部分组成。
- 格式一般为:target: dependencies,接着是命令部分,每行命令前面必须以制表符(Tab)开头。
1.2.2 命令(Commands)
- 用于执行生成目标的具体操作。可以是编译器命令、链接器命令、文件复制命令等。
- 例如,编译 C 语言源文件的命令可能是gcc -o target source.c。
1.3 变量与函数
1.3.1 变量(Variables)
- 可以定义和使用变量来存储常用的值,如编译器名称、编译选项、源文件列表等。
- 变量定义方式为VARIABLE = value,使用时用$(VARIABLE)。
1.3.2 函数(Functions)
- Makefile 提供了一些内置函数,可以进行字符串处理、文件操作等。
- 例如,$(wildcard *.c)可以获取当前目录下所有的 C 语言源文件。
1.4 优势
1.4.1 自动化构建
- 可以自动执行一系列构建步骤,减少手动操作和错误。
- 当源文件发生变化时,只重新构建受影响的部分,提高构建效率。
1.4.2 可重复性
确保在不同的环境中都能以相同的方式构建项目。
1.4.3 易于维护
项目的构建过程集中在一个文件中,便于修改和管理。
2、kubebuilder makefile
2.1 kubebuilder 项目makefile
一个kubebuilder创建的operator项目的makefile文件内容:
# Image URL to use all building/pushing image targets
IMG ?= controller:latest
# ENVTEST_K8S_VERSION refers to the version of kubebuilder assets to be downloaded by envtest binary.
ENVTEST_K8S_VERSION = 1.31.0
# Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set)
ifeq (,$(shell go env GOBIN))
GOBIN=$(shell go env GOPATH)/bin
else
GOBIN=$(shell go env GOBIN)
endif
# CONTAINER_TOOL defines the container tool to be used for building images.
# Be aware that the target commands are only tested with Docker which is
# scaffolded by default. However, you might want to replace it to use other
# tools. (i.e. podman)
CONTAINER_TOOL ?= docker
# Setting SHELL to bash allows bash commands to be executed by recipes.
# Options are set to exit when a recipe line exits non-zero or a piped command fails.
SHELL = /usr/bin/env bash -o pipefail
.SHELLFLAGS = -ec
.PHONY: all
all: build
##@ General
# The help target prints out all targets with their descriptions organized
# beneath their categories. The categories are represented by '##@' and the
# target descriptions by '##'. The awk command is responsible for reading the
# entire set of makefiles included in this invocation, looking for lines of the
# file as xyz: ## something, and then pretty-format the target and help. Then,
# if there's a line with ##@ something, that gets pretty-printed as a category.
# More info on the usage of ANSI control characters for terminal formatting:
# https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters
# More info on the awk command:
# http://linuxcommand.org/lc3_adv_awk.php
.PHONY: help
help: ## Display this help.
@awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m<target>\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST)
##@ Development
.PHONY: manifests
manifests: controller-gen ## Generate WebhookConfiguration, ClusterRole and CustomResourceDefinition objects.
$(CONTROLLER_GEN) rbac:roleName=manager-role crd webhook paths="./..." output:crd:artifacts:config=config/crd/bases
.PHONY: generate
generate: controller-gen ## Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations.
$(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./..."
.PHONY: fmt
fmt: ## Run go fmt against code.
go fmt ./...
.PHONY: vet
vet: ## Run go vet against code.
go vet ./...
.PHONY: test
test: manifests generate fmt vet envtest ## Run tests.
KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path)" go test $$(go list ./... | grep -v /e2e) -coverprofile cover.out
# Utilize Kind or modify the e2e tests to load the image locally, enabling compatibility with other vendors.
.PHONY: test-e2e # Run the e2e tests against a Kind k8s instance that is spun up.
test-e2e:
go test ./test/e2e/ -v -ginkgo.v
.PHONY: lint
lint: golangci-lint ## Run golangci-lint linter
$(GOLANGCI_LINT) run
.PHONY: lint-fix
lint-fix: golangci-lint ## Run golangci-lint linter and perform fixes
$(GOLANGCI_LINT) run --fix
##@ Build
.PHONY: build
build: manifests generate fmt vet ## Build manager binary.
go build -o bin/manager cmd/main.go
.PHONY: run
run: manifests generate fmt vet ## Run a controller from your host.
go run ./cmd/main.go
# If you wish to build the manager image targeting other platforms you can use the --platform flag.
# (i.e. docker build --platform linux/arm64). However, you must enable docker buildKit for it.
# More info: https://docs.docker.com/develop/develop-images/build_enhancements/
.PHONY: docker-build
docker-build: ## Build docker image with the manager.
$(CONTAINER_TOOL) build -t ${IMG} .
.PHONY: docker-push
docker-push: ## Push docker image with the manager.
$(CONTAINER_TOOL) push ${IMG}
# PLATFORMS defines the target platforms for the manager image be built to provide support to multiple
# architectures. (i.e. make docker-buildx IMG=myregistry/mypoperator:0.0.1). To use this option you need to:
# - be able to use docker buildx. More info: https://docs.docker.com/build/buildx/
# - have enabled BuildKit. More info: https://docs.docker.com/develop/develop-images/build_enhancements/
# - be able to push the image to your registry (i.e. if you do not set a valid value via IMG=<myregistry/image:<tag>> then the export will fail)
# To adequately provide solutions that are compatible with multiple platforms, you should consider using this option.
PLATFORMS ?= linux/arm64,linux/amd64,linux/s390x,linux/ppc64le
.PHONY: docker-buildx
docker-buildx: ## Build and push docker image for the manager for cross-platform support
# copy existing Dockerfile and insert --platform=${BUILDPLATFORM} into Dockerfile.cross, and preserve the original Dockerfile
sed -e '1 s/\(^FROM\)/FROM --platform=\$$\{BUILDPLATFORM\}/; t' -e ' 1,// s//FROM --platform=\$$\{BUILDPLATFORM\}/' Dockerfile > Dockerfile.cross
- $(CONTAINER_TOOL) buildx create --name myapp-operator-builder
$(CONTAINER_TOOL) buildx use myapp-operator-builder
- $(CONTAINER_TOOL) buildx build --push --platform=$(PLATFORMS) --tag ${IMG} -f Dockerfile.cross .
- $(CONTAINER_TOOL) buildx rm myapp-operator-builder
rm Dockerfile.cross
.PHONY: build-installer
build-installer: manifests generate kustomize ## Generate a consolidated YAML with CRDs and deployment.
mkdir -p dist
cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG}
$(KUSTOMIZE) build config/default > dist/install.yaml
##@ Deployment
ifndef ignore-not-found
ignore-not-found = false
endif
.PHONY: install
install: manifests kustomize ## Install CRDs into the K8s cluster specified in ~/.kube/config.
$(KUSTOMIZE) build config/crd | $(KUBECTL) apply -f -
.PHONY: uninstall
uninstall: manifests kustomize ## Uninstall CRDs from the K8s cluster specified in ~/.kube/config. Call with ignore-not-found=true to ignore resource not found errors during deletion.
$(KUSTOMIZE) build config/crd | $(KUBECTL) delete --ignore-not-found=$(ignore-not-found) -f -
.PHONY: deploy
deploy: manifests kustomize ## Deploy controller to the K8s cluster specified in ~/.kube/config.
cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG}
$(KUSTOMIZE) build config/default | $(KUBECTL) apply -f -
.PHONY: undeploy
undeploy: kustomize ## Undeploy controller from the K8s cluster specified in ~/.kube/config. Call with ignore-not-found=true to ignore resource not found errors during deletion.
$(KUSTOMIZE) build config/default | $(KUBECTL) delete --ignore-not-found=$(ignore-not-found) -f -
##@ Dependencies
## Location to install dependencies to
LOCALBIN ?= $(shell pwd)/bin
$(LOCALBIN):
mkdir -p $(LOCALBIN)
## Tool Binaries
KUBECTL ?= kubectl
KUSTOMIZE ?= $(LOCALBIN)/kustomize
CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen
ENVTEST ?= $(LOCALBIN)/setup-envtest
GOLANGCI_LINT = $(LOCALBIN)/golangci-lint
## Tool Versions
KUSTOMIZE_VERSION ?= v5.4.3
CONTROLLER_TOOLS_VERSION ?= v0.16.1
ENVTEST_VERSION ?= release-0.19
GOLANGCI_LINT_VERSION ?= v1.59.1
.PHONY: kustomize
kustomize: $(KUSTOMIZE) ## Download kustomize locally if necessary.
$(KUSTOMIZE): $(LOCALBIN)
$(call go-install-tool,$(KUSTOMIZE),sigs.k8s.io/kustomize/kustomize/v5,$(KUSTOMIZE_VERSION))
.PHONY: controller-gen
controller-gen: $(CONTROLLER_GEN) ## Download controller-gen locally if necessary.
$(CONTROLLER_GEN): $(LOCALBIN)
$(call go-install-tool,$(CONTROLLER_GEN),sigs.k8s.io/controller-tools/cmd/controller-gen,$(CONTROLLER_TOOLS_VERSION))
.PHONY: envtest
envtest: $(ENVTEST) ## Download setup-envtest locally if necessary.
$(ENVTEST): $(LOCALBIN)
$(call go-install-tool,$(ENVTEST),sigs.k8s.io/controller-runtime/tools/setup-envtest,$(ENVTEST_VERSION))
.PHONY: golangci-lint
golangci-lint: $(GOLANGCI_LINT) ## Download golangci-lint locally if necessary.
$(GOLANGCI_LINT): $(LOCALBIN)
$(call go-install-tool,$(GOLANGCI_LINT),github.com/golangci/golangci-lint/cmd/golangci-lint,$(GOLANGCI_LINT_VERSION))
# go-install-tool will 'go install' any package with custom target and name of binary, if it doesn't exist
# $1 - target path with name of binary
# $2 - package url which can be installed
# $3 - specific version of package
define go-install-tool
@[ -f "$(1)-$(3)" ] || { \
set -e; \
package=$(2)@$(3) ;\
echo "Downloading $${package}" ;\
rm -f $(1) || true ;\
GOBIN=$(LOCALBIN) go install $${package} ;\
mv $(1) $(1)-$(3) ;\
} ;\
ln -sf $(1)-$(3) $(1)
endef
2.2 变量定义部分
2.2.1 IMG(定义构建和推送Docker镜像的目标镜像URL)
# Image URL to use all building/pushing image targets
IMG ?= controller:latest
作用:定义构建和推送Docker镜像的目标镜像URL
解释:如果没有在命令中指定IMG,则默认值为controller:latest
2.2.2 ENVTEST_K8S_VERSION(定义envtest工具下载的Kubernetes资产版本)
# ENVTEST_K8S_VERSION refers to the version of kubebuilder assets to be downloaded by envtest binary.
ENVTEST_K8S_VERSION = 1.31.0
作用:定义envtest工具下载的Kubernetes资产版本
解释:envtest是一个用于测试的工具,这个变量制定了要下载的Kubernetes版本。
2.2.3 GOBIN(当前使用的Go的安装路径)
# Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set)
ifeq (,$(shell go env GOBIN))
GOBIN=$(shell go env GOPATH)/bin
else
GOBIN=$(shell go env GOBIN)
endif
作用:获取当前使用的Go的安装路径
解释:如果GONBIN环境变量未设置,则使用GOPATCH/bin作为默认路径;否则使用GOBIN的值。
2.2.4 CONTAINER_TOOL(用于构建镜像的容器工具)
# CONTAINER_TOOL defines the container tool to be used for building images.
# Be aware that the target commands are only tested with Docker which is
# scaffolded by default. However, you might want to replace it to use other
# tools. (i.e. podman)
CONTAINER_TOOL ?= docker
作用:定义用于构建镜像的容器工具
解释:默认值为docker,但是可以替换为其他工具,例如podman
2.2.5 SHELL 和 .SHELLFLAGS(设置Makefile使用的shell和shell选项)
# Setting SHELL to bash allows bash commands to be executed by recipes.
# Options are set to exit when a recipe line exits non-zero or a piped command fails.
SHELL = /usr/bin/env bash -o pipefail
.SHELLFLAGS = -ec
作用:设置Makefile使用的shell和shell选项
解释:
- SHELL设置为/usr/bin/env bash -o pipefail
- .SHELLFLAGS 设置为-ec,表示shell应该立即退出并在任何命令失败时报告错误
2.3 目标定义部分
2.3.1 通用目标
2.3.1.1 all(定义默认目标,调用build目标)
.PHONY: all
all: build
作用:定义默认目标,调用build目标
解释:当运行make时,如果没有指定目标。默认会执行build目标。
2.3.1.2 help(显示帮助信息)
.PHONY: help
help: ## Display this help.
@awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m<target>\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST)
作用:显示帮助信息
解释:使用awk命令解析Makefile,提取每个目标的描述,并按类别组织显示。##@
表示类别,##
表示目标描述
2.3.2 开发目标
2.3.2.1 manifests(生成WebhookConfiguration、ClusterRole和CustomResourceDefinition 对象)
.PHONY: manifests
manifests: controller-gen ## Generate WebhookConfiguration, ClusterRole and CustomResourceDefinition objects.
$(CONTROLLER_GEN) rbac:roleName=manager-role crd webhook paths="./..." output:crd:artifacts:config=config/crd/bases
作用:生成WebhookConfiguration、ClusterRole和CustomResourceDefinition 对象
解释:使用controller-gen工具生成必要的Kubernetes资源文件,并保存到config/crd/bases目录
2.3.2.2 generate(生成包含DeepCopy、DeepCopyInto, 和DeepCopyObject方法实现的代码。)
.PHONY: generate
generate: controller-gen ## Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations.
$(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./..."
作用:生成包含DeepCopy、DeepCopyInto, 和DeepCopyObject方法实现的代码。
解释:使用controller-gen工具生成GO代码,这些代码自动生成对象的深拷贝方法。
2.3.2.3 fmt(格式化代码)
.PHONY: fmt
fmt: ## Run go fmt against code.
go fmt ./...
作用:格式化代码
解释:使用go fmt命令格式化项目中的所有Go代码
2.3.2.4 vet(检查代码中的潜在问题)
.PHONY: vet
vet: ## Run go vet against code.
go vet ./...
作用:检查代码中的潜在问题
解释:使用go vet命令检查项目中的所有Go代码,查找可能的问题。
2.3.2.5 test(运行测试)
.PHONY: test
test: manifests generate fmt vet envtest ## Run tests.
KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path)" go test $$(go list ./... | grep -v /e2e) -coverprofile cover.out
作用:运行测试
解释:
- 先运行manifests、generate、fmt和vet目标
- 使用envtest工具设置环境变量KUBEBUILDER_ASSETS,然后运行项目中的所有测试(排除e2e测试)
2.3.2.6 test-e2e(运行端到端测试)
# Utilize Kind or modify the e2e tests to load the image locally, enabling compatibility with other vendors.
.PHONY: test-e2e # Run the e2e tests against a Kind k8s instance that is spun up.
test-e2e:
go test ./test/e2e/ -v -ginkgo.v
作用:运行端到端测试
解释:使用go test命令运行test/e2e目录中的端到端测试,并启动详细输出。
2.3.2.7 lint(运行代码风格检查)
.PHONY: lint
lint: golangci-lint ## Run golangci-lint linter
$(GOLANGCI_LINT) run
作用:运行代码风格检查
解释:使用golangci-lint工具运行代码风格检查
2.3.2.8 lint-fix (运行代码风格检查并自动修复问题)
.PHONY: lint-fix
lint-fix: golangci-lint ## Run golangci-lint linter and perform fixes
$(GOLANGCI_LINT) run --fix
作用:运行代码风格检查并自动修复问题
解释:使用golangci-lint工具运行代码风格检查,并使用–fix选项自动修复发现的问题。
2.3.3 构建目标
2.3.3.1 build(构建controller的二进制文件)
.PHONY: build
build: manifests generate fmt vet ## Build manager binary.
go build -o bin/manager cmd/main.go
作用:构建controller的二进制文件
解释:
- 先运行manifests、generate、fmt和vet目标
- 使用go build命令编译cmd/main.go文件,并将生成的二进制文件保存到bin/manager。
2.3.3.2 run(在主机上运行controller)
.PHONY: run
run: manifests generate fmt vet ## Run a controller from your host.
go run ./cmd/main.go
作用:在主机上运行controller
解释:
- 先运行manifests、generate、fmt和vet目标
- 使用go run命令运行cmd/main.go文件
2.3.3.3 docker-build(构建Docker镜像)
# If you wish to build the manager image targeting other platforms you can use the --platform flag.
# (i.e. docker build --platform linux/arm64). However, you must enable docker buildKit for it.
# More info: https://docs.docker.com/develop/develop-images/build_enhancements/
.PHONY: docker-build
docker-build: ## Build docker image with the manager.
$(CONTAINER_TOOL) build -t ${IMG} .
作用:构建Docker镜像
解释:使用CONTAINER_TOOL(默认为docker)构建docker镜像,并使用IMG变量指定镜像名称和标签
2.3.3.4 docker-push(推送Docker镜像)
.PHONY: docker-push
docker-push: ## Push docker image with the manager.
$(CONTAINER_TOOL) push ${IMG}
作用:推送Docker镜像
解释:使用CONTAINER_TOOL(默认为docker)推送构建好的Docker镜像到指定的仓库
2.3.3.5 docker-buildx(构建并推送多平台支持的Docker镜像)
# PLATFORMS defines the target platforms for the manager image be built to provide support to multiple
# architectures. (i.e. make docker-buildx IMG=myregistry/mypoperator:0.0.1). To use this option you need to:
# - be able to use docker buildx. More info: https://docs.docker.com/build/buildx/
# - have enabled BuildKit. More info: https://docs.docker.com/develop/develop-images/build_enhancements/
# - be able to push the image to your registry (i.e. if you do not set a valid value via IMG=<myregistry/image:<tag>> then the export will fail)
# To adequately provide solutions that are compatible with multiple platforms, you should consider using this option.
PLATFORMS ?= linux/arm64,linux/amd64,linux/s390x,linux/ppc64le
.PHONY: docker-buildx
docker-buildx: ## Build and push docker image for the manager for cross-platform support
# copy existing Dockerfile and insert --platform=${BUILDPLATFORM} into Dockerfile.cross, and preserve the original Dockerfile
sed -e '1 s/\(^FROM\)/FROM --platform=\$$\{BUILDPLATFORM\}/; t' -e ' 1,// s//FROM --platform=\$$\{BUILDPLATFORM\}/' Dockerfile > Dockerfile.cross
- $(CONTAINER_TOOL) buildx create --name myapp-operator-builder
$(CONTAINER_TOOL) buildx use myapp-operator-builder
- $(CONTAINER_TOOL) buildx build --push --platform=$(PLATFORMS) --tag ${IMG} -f Dockerfile.cross .
- $(CONTAINER_TOOL) buildx rm myapp-operator-builder
rm Dockerfile.cross
作用:构建并推送多平台支持的Docker镜像
解释:
- 使用sed命令复制现有的Dockerfile并插入
--platform=${BUILDPLATFORM}
选项,生成Dockerfile.cross - 创建一个名为myapp-builder的构建器
- 使用buildx构建并推送多平台镜像
- 删除构建器和临时生成的Dockerfile.cross
2.3.3.6 docker-installer(生成包含CRDs和部署的合并YAML文件)
.PHONY: build-installer
build-installer: manifests generate kustomize ## Generate a consolidated YAML with CRDs and deployment.
mkdir -p dist
cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG}
$(KUSTOMIZE) build config/default > dist/install.yaml
作用:生成包含CRDs和部署的合并YAML文件
解释:
- 创建dist目录
- 使用kustomize工具设置controller镜像为IMG
- 使用kustomize构建config/default目录中的资源,并保存到dist/install.yaml
2.3.4 部署目标
2.3.4.1 install(安装CRDs到Kubernetes集群)
.PHONY: install
install: manifests kustomize ## Install CRDs into the K8s cluster specified in ~/.kube/config.
$(KUSTOMIZE) build config/crd | $(KUBECTL) apply -f -
作用:安装CRDs到Kubernetes集群
解释:
- 先运行manifests和kustomize目标
- 使用kustomize 构建config/crd目录中的资源,并使用kubectl将其应用到集群。
2.3.4.2 uninstall(从Kubernetes集群卸载CRDs)
.PHONY: uninstall
uninstall: manifests kustomize ## Uninstall CRDs from the K8s cluster specified in ~/.kube/config. Call with ignore-not-found=true to ignore resource not found errors during deletion.
$(KUSTOMIZE) build config/crd | $(KUBECTL) delete --ignore-not-found=$(ignore-not-found) -f -
作用:从Kubernetes集群卸载CRDs
解释:
- 先运行manifests和kustomize目标
- 使用kustomize 构建config/crd目录中的资源,并使用kubectl将其从集群中删除,可以通过
ignore-not-found=true忽略资源未找到的错误
2.3.4.3 deploy(部署controller到Kubernetes集群)
.PHONY: deploy
deploy: manifests kustomize ## Deploy controller to the K8s cluster specified in ~/.kube/config.
cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG}
$(KUSTOMIZE) build config/default | $(KUBECTL) apply -f -
作用:部署controller到Kubernetes集群
解释:
- 先运行manifests和kustomize目标
- 使用kustomize设置controller镜像为IMG
- 使用kustomize构建config/default目录中的资源,并使用kubectl将其应用到集群
2.3.4.4 undeploy(从Kubernetes集群中卸载Controller)
.PHONY: undeploy
undeploy: kustomize ## Undeploy controller from the K8s cluster specified in ~/.kube/config. Call with ignore-not-found=true to ignore resource not found errors during deletion.
$(KUSTOMIZE) build config/default | $(KUBECTL) delete --ignore-not-found=$(ignore-not-found) -f -
作用:从Kubernetes集群中卸载Controller
解释:使用kustomize 构建config/default目录中的资源,并使用kubectl将其从集群中删除。可以通过ignore-not-found=true忽略资源未找到的错误
2.3.5 依赖目标
2.3.5.1 ignore-not-found(定义ignore-not-found变量,默认值为false)
ifndef ignore-not-found
ignore-not-found = false
endif
作用:定义ignore-not-found变量,默认值为false
解释:如果命令行中未指定ignore-not-found,则默认值为false
2.3.5.2 LOCALBIN(定义本地二进制文件的安装目录)
## Location to install dependencies to
LOCALBIN ?= $(shell pwd)/bin
$(LOCALBIN):
mkdir -p $(LOCALBIN)
作用:定义本地二进制文件的安装目录,默认为当前目录下的bin目录
解释:如果LOCALBIN未设置,则默认为$(shell pwd)/bin
。如果LOCALBIN目录不存在,则创建它。
2.3.5.3 工具二进制文件(定义各种工具的路径和默认值)
## Tool Binaries
KUBECTL ?= kubectl
KUSTOMIZE ?= $(LOCALBIN)/kustomize
CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen
ENVTEST ?= $(LOCALBIN)/setup-envtest
GOLANGCI_LINT = $(LOCALBIN)/golangci-lint
作用:定义各种工具的路径和默认值
解释:
- KUBECTL:默认为kubectl
- KUSTOMIZE:默认为$(LOCALBIN)/kustomize
- CONTROLLER_GEN:默认为$(LOCALBIN)/controller-gen
- ENVTEST:默认为$(LOCALBIN)/setup-envtest
- GOLANGCI_LINT: 默认为$(LOCALBIN)/golangci-lint
2.3.5.4 工具版本(定义各个工具的版本)
## Tool Versions
KUSTOMIZE_VERSION ?= v5.4.3
CONTROLLER_TOOLS_VERSION ?= v0.16.1
ENVTEST_VERSION ?= release-0.19
GOLANGCI_LINT_VERSION ?= v1.59.1
作用:定义各个工具的版本
解释:
- KUSTOMIZE_VERSION:默认为v5.4.3
- CONTROLLER_TOOLS_VERSION:默认为v0.16.1
- ENVTEST_VERSION:默认为release-0.19
- GOLANGCI_LINT_VERSION:默认为v1.59.1
2.3.5.5 kustomize(下载kustomize工具)
.PHONY: kustomize
kustomize: $(KUSTOMIZE) ## Download kustomize locally if necessary.
$(KUSTOMIZE): $(LOCALBIN)
$(call go-install-tool,$(KUSTOMIZE),sigs.k8s.io/kustomize/kustomize/v5,$(KUSTOMIZE_VERSION))
作用:下载kustomize工具(如有必要)
解释:如果kustomize文件不存在,则调用 go-install-tool函数下载kustomize工具
2.3.5.6 controller-gen(下载controller-gen工具)
.PHONY: controller-gen
controller-gen: $(CONTROLLER_GEN) ## Download controller-gen locally if necessary.
$(CONTROLLER_GEN): $(LOCALBIN)
$(call go-install-tool,$(CONTROLLER_GEN),sigs.k8s.io/controller-tools/cmd/controller-gen,$(CONTROLLER_TOOLS_VERSION))
作用:下载controller-gen工具(如有必要)
解释:如果$(CONTROLLER_GEN)文件不存在,则调用 go-install-tool函数下载controller-gen工具
2.3.5.7 envtest(下载setup-envtest工具)
.PHONY: envtest
envtest: $(ENVTEST) ## Download setup-envtest locally if necessary.
$(ENVTEST): $(LOCALBIN)
$(call go-install-tool,$(ENVTEST),sigs.k8s.io/controller-runtime/tools/setup-envtest,$(ENVTEST_VERSION))
作用:下载setup-envtest工具(如有必要)
解释:如果$(ENVTEST)文件不存在,则调用go-install-tool函数下载setup-envtes工具
2.3.5.8 golangci-lint(下载golangci-lint工具)
.PHONY: golangci-lint
golangci-lint: $(GOLANGCI_LINT) ## Download golangci-lint locally if necessary.
$(GOLANGCI_LINT): $(LOCALBIN)
$(call go-install-tool,$(GOLANGCI_LINT),github.com/golangci/golangci-lint/cmd/golangci-lint,$(GOLANGCI_LINT_VERSION))
作用:下载golangci-lint工具(如有必要)
解释:如果$(GOLANGCI_LINT)文件不存在,则调用go-install-tool函数下载golangci-lint工具。
2.4 自定义函数
2.4.1 go-install-tool(下载并安装指定的Go包)
# go-install-tool will 'go install' any package with custom target and name of binary, if it doesn't exist
# $1 - target path with name of binary
# $2 - package url which can be installed
# $3 - specific version of package
define go-install-tool
@[ -f "$(1)-$(3)" ] || { \
set -e; \
package=$(2)@$(3) ;\
echo "Downloading $${package}" ;\
rm -f $(1) || true ;\
GOBIN=$(LOCALBIN) go install $${package} ;\
mv $(1) $(1)-$(3) ;\
} ;\
ln -sf $(1)-$(3) $(1)
endef
作用:下载并安装指定的Go包
解释:
- $1:目标路径和二进制文件名
- $2:包的URL
- $3:包的具体版本
- 如果目标文件$(1)~$(3)不存在,则执行以下步骤
- 设置set -e,确保任何命令执行失败立即退出
- 设置package变量为包的URL和版本
- 输出下载信息
- 删除旧的二进制文件(如果存在)
- 使用go install命令安装包,并将二进制文件保存在LOCALBIN目录
- 将生成的二进制文件重命令为$(1)-$(3)
- 最后创建一个符号链接,指向$(1)-$(3)