文件路径
Makefile -> build/root/Makefile.generated_files
make -f Makefile.generated_files generated_files CALLED_FROM_MAIN_MAKEFILE=1
准备工作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
ifeq ($(CALLED_FROM_MAIN_MAKEFILE),)
$(error Please use the main Makefile, e.g. `make generated_files`)
endif
# Don't allow an implicit 'all' rule. This is not a user-facing file.
ifeq ($(MAKECMDGOALS),)
$(error This Makefile requires an explicit rule to be specified)
endif
ifeq ($(DBG_MAKEFILE),1)
$(warning ***** starting Makefile.generated_files for goal(s) "$(MAKECMDGOALS)")
$(warning ***** $(shell date))
endif
SHELL := /bin/bash
This rule collects all the generated file sets into a single rule. Other
rules should depend on this to ensure generated files are rebuilt.
.PHONY: generated_files generated_files: gen_deepcopy gen_defaulter gen_conversion gen_openapi gen_bindata
#
Helper logic to calculate Go’s dependency DAG ourselves.
#
This is a file that will be emitted by the go2make tool, containing a
variable for each Go package in the project (including deps) which lists all
of the transitive deps of that package. Each variable is named the same as
the package - for example the variable for 1
k8s.io/kubernetes/pkg/api
is
1 | k8s.io/kubernetes/pkg/api |
$(k8s.io/kubernetes/pkg/api). This is roughly the same DAG that the Go
compiler uses. These variables can be used to figure out if, for example,
generated code needs to be regenerated.
GO_PKGDEPS_FILE = go-pkgdeps.mk
Include the Go package dependencies file. This will cause the rule of
the same name to be considered and if it is updated, make will restart and
reload the updated deps.
sinclude $(META_DIR)/$(GO_PKGDEPS_FILE)
Update the set of Go deps for our project. This will let us determine if
we really need to do expensive codegen. We use FORCE because it is not a
PHONY file, but we do want it to be re-evaluated every time make is run. The
file will only be touched if it actually changes.
$(META_DIR)/$(GO_PKGDEPS_FILE): FORCE
if [[ “$(DBG_CODEGEN)” == 1 ]]; then
echo “DBG: calculating Go dependencies”;
fi
hack/run-in-gopath.sh go install ./hack/make-rules/helpers/go2make
hack/run-in-gopath.sh go2make
k8s.io/kubernetes/…
–prune k8s.io/kubernetes/staging
–prune k8s.io/kubernetes/vendor
k8s.io/kubernetes/vendor/k8s.io/…
github.com/jteeuwen/go-bindata/go-bindata/…
> $@.tmp
if ! cmp -s $@.tmp $@; then
if [[ “$(DBG_CODEGEN)” == 1 ]]; then
echo “DBG: $(GO_PKGDEPS_FILE) changed”;
fi;
cat $@.tmp > $@;
fi
rm -f $@.tmp
.PHONY: FORCE FORCE:
#
Helper logic to find which directories need codegen as quickly as possible.
#
This variable holds a list of every directory that contains Go files in this
project. Other rules and variables can use this as a starting point to
reduce filesystem accesses.
ifeq ($(DBG_MAKEFILE),1)
$(warning ***** finding all *.go dirs)
endif
ALL_GO_DIRS := $(shell
hack/make-rules/helpers/cache_go_dirs.sh $(META_DIR)/all_go_dirs.mk
)
Generate a list of all files that have a 1
+k8s:
comment-tag. This will be
1 | +k8s: |
used to derive lists of files/dirs for generation tools.
ifeq ($(DBG_MAKEFILE),1)
$(warning ***** finding all +k8s: tags)
endif
ALL_K8S_TAG_FILES := $(shell
find $(ALL_GO_DIRS) -maxdepth 1 -type f -name *.go
| xargs grep –color=never -l ‘^// *+k8s:’
)
#
Code generation logic.
#
Deep-copy generation
#
Any package that wants deep-copy functions generated must include a
comment-tag in column 0 of one file of the form:
// +k8s:deepcopy-gen=
#
The may be one of:
generate: generate deep-copy functions into the package
register: generate deep-copy functions and register them with a
scheme
The result file, in each pkg, of deep-copy generation.
DEEPCOPY_BASENAME := $(GENERATED_FILE_PREFIX)deepcopy DEEPCOPY_FILENAME := $(DEEPCOPY_BASENAME).go
The tool used to generate deep copies.
DEEPCOPY_GEN := $(BIN_DIR)/deepcopy-gen
Find all the directories that request deep-copy generation.
ifeq ($(DBG_MAKEFILE),1)
$(warning ***** finding all +k8s:deepcopy-gen tags)
endif
DEEPCOPY_DIRS := $(shell
grep –color=never -l ‘+k8s:deepcopy-gen=’ $(ALL_K8S_TAG_FILES)
| xargs -n1 dirname
| LC_ALL=C sort -u
)
DEEPCOPY_FILES := $(addsuffix /$(DEEPCOPY_FILENAME), $(DEEPCOPY_DIRS))
Reset the list of packages that need generation.
$(shell mkdir -p $$(dirname $(META_DIR)/$(DEEPCOPY_GEN))) $(shell rm -f $(META_DIR)/$(DEEPCOPY_GEN).todo)
This rule aggregates the set of files to generate and then generates them all
in a single run of the tool.
.PHONY: gen_deepcopy
gen_deepcopy: $(DEEPCOPY_GEN) $(META_DIR)/$(DEEPCOPY_GEN).todo
if [[ -s $(META_DIR)/$(DEEPCOPY_GEN).todo ]]; then
pkgs=\((cat $(META_DIR)/$(DEEPCOPY_GEN).todo | paste -sd, -); \
if [[ "$(DBG_CODEGEN)" == 1 ]]; then \
echo "DBG: running $(DEEPCOPY_GEN) for\)pkgs”;
fi;
./hack/run-in-gopath.sh $(DEEPCOPY_GEN)
–v $(KUBE_VERBOSE)
–logtostderr
-i “\(pkgs" \
--bounding-dirs $(PRJ_SRC_PATH),"k8s.io/api" \
-O $(DEEPCOPY_BASENAME) \
"\)@”;
fi \
For each dir in DEEPCOPY_DIRS, this establishes a dependency between the
output file and the input files that should trigger a rebuild.
#
Note that this is a deps-only statement, not a full rule (see below). This
has to be done in a distinct step because wildcards don’t work in static
pattern rules.
#
The ‘$(eval)’ is needed because this has a different RHS for each LHS, and
would otherwise produce results that make can’t parse.
$(foreach dir, $(DEEPCOPY_DIRS), $(eval
$(dir)/$(DEEPCOPY_FILENAME): $($(PRJ_SRC_PATH)/$(dir))
))
How to regenerate deep-copy code. This is a little slow to run, so we batch
it up and trigger the batch from the ‘generated_files’ target.
$(META_DIR)/$(DEEPCOPY_GEN).todo: $(DEEPCOPY_FILES)
$(DEEPCOPY_FILES): $(DEEPCOPY_GEN)
if [[ “$(DBG_CODEGEN)” == 1 ]]; then
echo “DBG: deepcopy needed $(@D): $?”;
ls -lf –full-time $@ $? || true;
fi
echo $(PRJ_SRC_PATH)/$(@D) » $(META_DIR)/$(DEEPCOPY_GEN).todo
How to build the generator tool. The deps for this are defined in
the $(GO_PKGDEPS_FILE), above.
#
A word on the need to touch: This rule might trigger if, for example, a
non-Go file was added or deleted from a directory on which this depends.
This target needs to be reconsidered, but Go realizes it doesn’t actually
have to be rebuilt. In that case, make will forever see the dependency as
newer than the binary, and try to “rebuild” it over and over. So we touch
it, and make is happy.
$(DEEPCOPY_GEN): $(k8s.io/kubernetes/vendor/k8s.io/code-generator/cmd/deepcopy-gen) KUBE_BUILD_PLATFORMS=”” hack/make-rules/build.sh ./vendor/k8s.io/code-generator/cmd/deepcopy-gen touch $@
Defaulter generation
#
Any package that wants defaulter functions generated must include a
comment-tag in column 0 of one file of the form:
// +k8s:defaulter-gen=
#
The depends on context:
on types:
true: always generate a defaulter for this type
false: never generate a defaulter for this type
on functions:
covers: if the function name matches SetDefault_NAME, instructs
the generator not to recurse
on packages:
FIELDNAME: any object with a field of this name is a candidate
for having a defaulter generated
The result file, in each pkg, of defaulter generation.
DEFAULTER_BASENAME := $(GENERATED_FILE_PREFIX)defaults DEFAULTER_FILENAME := $(DEFAULTER_BASENAME).go
The tool used to generate defaulters.
DEFAULTER_GEN := $(BIN_DIR)/defaulter-gen
All directories that request any form of defaulter generation.
ifeq ($(DBG_MAKEFILE),1)
$(warning ***** finding all +k8s:defaulter-gen tags)
endif
DEFAULTER_DIRS := $(shell
grep –color=never -l ‘+k8s:defaulter-gen=’ $(ALL_K8S_TAG_FILES)
| xargs -n1 dirname
| LC_ALL=C sort -u
)
DEFAULTER_FILES := $(addsuffix /$(DEFAULTER_FILENAME), $(DEFAULTER_DIRS))
Reset the list of packages that need generation.
$(shell mkdir -p $$(dirname $(META_DIR)/$(DEFAULTER_GEN))) $(shell rm -f $(META_DIR)/$(DEFAULTER_GEN).todo)
This rule aggregates the set of files to generate and then generates them all
in a single run of the tool.
.PHONY: gen_defaulter
gen_defaulter: $(DEFAULTER_GEN) $(META_DIR)/$(DEFAULTER_GEN).todo
if [[ -s $(META_DIR)/$(DEFAULTER_GEN).todo ]]; then
pkgs=\((cat $(META_DIR)/$(DEFAULTER_GEN).todo | paste -sd, -); \
if [[ "$(DBG_CODEGEN)" == 1 ]]; then \
echo "DBG: running $(DEFAULTER_GEN) for\)pkgs”;
fi;
./hack/run-in-gopath.sh $(DEFAULTER_GEN)
–v $(KUBE_VERBOSE)
–logtostderr
-i “\(pkgs" \
--extra-peer-dirs\)(echo $(addprefix $(PRJ_SRC_PATH)/, $(DEFAULTER_DIRS)) | sed ‘s/ /,/g’)
-O $(DEFAULTER_BASENAME)
“$$@”;
fi
For each dir in DEFAULTER_DIRS, this establishes a dependency between the
output file and the input files that should trigger a rebuild.
#
Note that this is a deps-only statement, not a full rule (see below for that).
#
The ‘$(eval)’ is needed because this has a different RHS for each LHS, and
would otherwise produce results that make can’t parse.
$(foreach dir, $(DEFAULTER_DIRS), $(eval
$(dir)/$(DEFAULTER_FILENAME): $($(PRJ_SRC_PATH)/$(dir))
))
How to regenerate defaulter code. This is a little slow to run, so we batch
it up and trigger the batch from the ‘generated_files’ target.
$(META_DIR)/$(DEFAULTER_GEN).todo: $(DEFAULTER_FILES)
$(DEFAULTER_FILES): $(DEFAULTER_GEN)
if [[ “$(DBG_CODEGEN)” == 1 ]]; then
echo “DBG: defaulter needed $(@D): $?”;
ls -lf –full-time $@ $? || true;
fi
echo $(PRJ_SRC_PATH)/$(@D) » $(META_DIR)/$(DEFAULTER_GEN).todo
How to build the generator tool. The deps for this are defined in
the $(GO_PKGDEPS_FILE), above.
#
A word on the need to touch: This rule might trigger if, for example, a
non-Go file was added or deleted from a directory on which this depends.
This target needs to be reconsidered, but Go realizes it doesn’t actually
have to be rebuilt. In that case, make will forever see the dependency as
newer than the binary, and try to “rebuild” it over and over. So we touch
it, and make is happy.
$(DEFAULTER_GEN): $(k8s.io/kubernetes/vendor/k8s.io/code-generator/cmd/defaulter-gen) KUBE_BUILD_PLATFORMS=”” hack/make-rules/build.sh ./vendor/k8s.io/code-generator/cmd/defaulter-gen touch $@
Conversion generation
#
Any package that wants conversion functions generated must include one or
more comment-tags in any .go file, in column 0, of the form:
// +k8s:conversion-gen=
#
The CONVERSION_TARGET_DIR is a project-local path to another directory which
should be considered when evaluating peer types for conversions. Types which
are found in the source package (where conversions are being generated)
but do not have a peer in one of the target directories will not have
conversions generated.
#
TODO: it might be better in the long term to make peer-types explicit in the
IDL.
The result file, in each pkg, of conversion generation.
CONVERSION_BASENAME := $(GENERATED_FILE_PREFIX)conversion CONVERSION_FILENAME := $(CONVERSION_BASENAME).go
The tool used to generate conversions.
CONVERSION_GEN := $(BIN_DIR)/conversion-gen
The name of the metadata file listing conversion peers for each pkg.
CONVERSIONS_META := conversions.mk
All directories that request any form of conversion generation.
ifeq ($(DBG_MAKEFILE),1)
$(warning ***** finding all +k8s:conversion-gen tags)
endif
CONVERSION_DIRS := $(shell
grep –color=never ‘^// *+k8s:conversion-gen=’ $(ALL_K8S_TAG_FILES)
| cut -f1 -d:
| xargs -n1 dirname
| LC_ALL=C sort -u
)
CONVERSION_FILES := $(addsuffix /$(CONVERSION_FILENAME), $(CONVERSION_DIRS)) CONVERSION_EXTRA_PEER_DIRS := k8s.io/kubernetes/pkg/apis/core,k8s.io/kubernetes/pkg/apis/core/v1,k8s.io/api/core/v1
Reset the list of packages that need generation.
$(shell mkdir -p $$(dirname $(META_DIR)/$(CONVERSION_GEN))) $(shell rm -f $(META_DIR)/$(CONVERSION_GEN).todo)
This rule aggregates the set of files to generate and then generates them all
in a single run of the tool.
.PHONY: gen_conversion
gen_conversion: $(CONVERSION_GEN) $(META_DIR)/$(CONVERSION_GEN).todo
if [[ -s $(META_DIR)/$(CONVERSION_GEN).todo ]]; then
pkgs=\((cat $(META_DIR)/$(CONVERSION_GEN).todo | paste -sd, -); \
if [[ "$(DBG_CODEGEN)" == 1 ]]; then \
echo "DBG: running $(CONVERSION_GEN) for\)pkgs”;
fi;
./hack/run-in-gopath.sh $(CONVERSION_GEN)
–extra-peer-dirs $(CONVERSION_EXTRA_PEER_DIRS)
–v $(KUBE_VERBOSE)
–logtostderr
-i “\(pkgs" \
-O $(CONVERSION_BASENAME) \
"\)@”;
fi
For each dir in CONVERSION_DIRS, this establishes a dependency between the
output file and the input files that should trigger a rebuild.
#
Note that this is a deps-only statement, not a full rule (see below for that).
#
The ‘$(eval)’ is needed because this has a different RHS for each LHS, and
would otherwise produce results that make can’t parse.
$(foreach dir, $(CONVERSION_DIRS), $(eval
$(dir)/$(CONVERSION_FILENAME): $($(PRJ_SRC_PATH)/$(dir))
))
How to regenerate conversion code. This is a little slow to run, so we batch
it up and trigger the batch from the ‘generated_files’ target.
$(META_DIR)/$(CONVERSION_GEN).todo: $(CONVERSION_FILES)
$(CONVERSION_FILES): $(CONVERSION_GEN)
if [[ “$(DBG_CODEGEN)” == 1 ]]; then
echo “DBG: conversion needed $(@D): $?”;
ls -lf –full-time $@ $? || true;
fi
echo $(PRJ_SRC_PATH)/$(@D) » $(META_DIR)/$(CONVERSION_GEN).todo
How to build the generator tool. The deps for this are defined in
the $(GO_PKGDEPS_FILE), above.
#
A word on the need to touch: This rule might trigger if, for example, a
non-Go file was added or deleted from a directory on which this depends.
This target needs to be reconsidered, but Go realizes it doesn’t actually
have to be rebuilt. In that case, make will forever see the dependency as
newer than the binary, and try to rebuild it over and over. So we touch it,
and make is happy.
$(CONVERSION_GEN): $(k8s.io/kubernetes/vendor/k8s.io/code-generator/cmd/conversion-gen) KUBE_BUILD_PLATFORMS=”” hack/make-rules/build.sh ./vendor/k8s.io/code-generator/cmd/conversion-gen touch $@
OpenAPI generation
#
Any package that wants open-api functions generated must include a
comment-tag in column 0 of one file of the form:
// +k8s:openapi-gen=true
#
The result file, in each pkg, of open-api generation.
OPENAPI_BASENAME := $(GENERATED_FILE_PREFIX)openapi OPENAPI_FILENAME := $(OPENAPI_BASENAME).go OPENAPI_OUTPUT_PKG := pkg/generated/openapi BOILERPLATE_FILENAME := vendor/k8s.io/code-generator/hack/boilerplate.go.txt REPORT_FILENAME := $(OUT_DIR)/violations.report KNOWN_VIOLATION_FILENAME := api/api-rules/violation_exceptions.list
When UPDATE_API_KNOWN_VIOLATIONS is set to be true, let the generator to write
updated API violations to the known API violation exceptions list.
ifeq ($(UPDATE_API_KNOWN_VIOLATIONS),true) REPORT_FILENAME:=$(KNOWN_VIOLATION_FILENAME) # When UPDATE_API_KNOWN_VIOLATIONS is set to be true, touch the exceptions # list so that the OPENAPI_OUTFILE target re-run instead of being cached. $(shell touch $(KNOWN_VIOLATION_FILENAME)) endif API_RULE_CHECK_FAILURE_MESSAGE := “ERROR: \n\t API rule check failed. Reported violations differ from known violations. Please read api/api-rules/README.md to resolve the failure. \n”
The tool used to generate open apis.
OPENAPI_GEN := $(BIN_DIR)/openapi-gen
Find all the directories that request open-api generation.
ifeq ($(DBG_MAKEFILE),1)
$(warning ***** finding all +k8s:openapi-gen tags)
endif
OPENAPI_DIRS := $(shell
grep –color=never -l ‘+k8s:openapi-gen=’ $(ALL_K8S_TAG_FILES)
| xargs -n1 dirname
| LC_ALL=C sort -u
)
OPENAPI_OUTFILE := $(OPENAPI_OUTPUT_PKG)/$(OPENAPI_FILENAME)
This rule is the user-friendly entrypoint for openapi generation.
.PHONY: gen_openapi gen_openapi: $(OPENAPI_OUTFILE) $(OPENAPI_GEN)
For each dir in OPENAPI_DIRS, this establishes a dependency between the
output file and the input files that should trigger a rebuild.
#
Note that this is a deps-only statement, not a full rule (see below for that).
#
The ‘$(eval)’ is needed because this has a different RHS for each LHS, and
would otherwise produce results that make can’t parse.
$(foreach dir, $(OPENAPI_DIRS), $(eval
$(OPENAPI_OUTFILE): $($(PRJ_SRC_PATH)/$(dir))
))
How to regenerate open-api code. This emits a single file for all results.
The Make rule fails if generated API rule violation report differs from the checked-in
violation file, and prints error message to request developer to fix either the API
source code, or the known API rule violation file.
$(OPENAPI_OUTFILE): $(OPENAPI_GEN) $(KNOWN_VIOLATION_FILENAME)
./hack/run-in-gopath.sh $(OPENAPI_GEN)
–v $(KUBE_VERBOSE)
–logtostderr
-i \((echo $(addprefix $(PRJ_SRC_PATH)/, $(OPENAPI_DIRS)) | sed 's/ /,/g') \
-p $(PRJ_SRC_PATH)/$(OPENAPI_OUTPUT_PKG) \
-O $(OPENAPI_BASENAME) \
-h $(BOILERPLATE_FILENAME) \
-r $(REPORT_FILENAME) \
"\)@”;
diff $(REPORT_FILENAME) $(KNOWN_VIOLATION_FILENAME) ||
(echo -e $(API_RULE_CHECK_FAILURE_MESSAGE); exit 1)
How to build the generator tool. The deps for this are defined in
the $(GO_PKGDEPS_FILE), above.
#
A word on the need to touch: This rule might trigger if, for example, a
non-Go file was added or deleted from a directory on which this depends.
This target needs to be reconsidered, but Go realizes it doesn’t actually
have to be rebuilt. In that case, make will forever see the dependency as
newer than the binary, and try to “rebuild” it over and over. So we touch
it, and make is happy.
$(OPENAPI_GEN): $(k8s.io/kubernetes/vendor/k8s.io/kube-openapi/cmd/openapi-gen) KUBE_BUILD_PLATFORMS=”” hack/make-rules/build.sh ./vendor/k8s.io/kube-openapi/cmd/openapi-gen touch $@
bindata generation
#
The tool used to generate bindata files.
BINDATA_GEN := $(BIN_DIR)/go-bindata
A wrapper script that generates all bindata files. It is fast enough that we
don’t care.
BINDATA_SCRIPT := hack/generate-bindata.sh
This rule is the user-friendly entrypoint for bindata generation.
.PHONY: gen_bindata gen_bindata: $(BINDATA_GEN) FORCE ./hack/run-in-gopath.sh $(BINDATA_SCRIPT)
How to build the generator tool. The deps for this are defined in
the $(BINDATA_GEN).mk, above.
#
A word on the need to touch: This rule might trigger if, for example, a
non-Go file was added or deleted from a directory on which this depends.
This target needs to be reconsidered, but Go realizes it doesn’t actually
have to be rebuilt. In that case, make will forever see the dependency as
newer than the binary, and try to rebuild it over and over. So we touch it,
and make is happy.
$(BINDATA_GEN): $(k8s.io/kubernetes/vendor/github.com/jteeuwen/go-bindata/go-bindata) KUBE_BUILD_PLATFORMS=”” hack/make-rules/build.sh ./vendor/github.com/jteeuwen/go-bindata/go-bindata touch $@