mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 19:56:01 +00:00
Merge pull request #54372 from thockin/make-genfiles-cleanup
Automatic merge from submit-queue. If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>. Overhaul Makefile for generated code Calculate all go dependencies in a single Go program, rather than a complicated series of `go list` invocations and `Makefile` logic. This simplifies the Makefile dramatically. Also adds tests to ensure the dependencies stay correct. This test is pretty slow, though. Also fixes a few anomalies found by the test. Fixes #54371 ```release-note NONE ```
This commit is contained in:
commit
8bc2fb0207
@ -124,7 +124,7 @@ ifeq ($(PRINT_HELP),y)
|
|||||||
verify:
|
verify:
|
||||||
@echo "$$VERIFY_HELP_INFO"
|
@echo "$$VERIFY_HELP_INFO"
|
||||||
else
|
else
|
||||||
verify: verify_generated_files
|
verify:
|
||||||
KUBE_VERIFY_GIT_BRANCH=$(BRANCH) hack/make-rules/verify.sh
|
KUBE_VERIFY_GIT_BRANCH=$(BRANCH) hack/make-rules/verify.sh
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@ -139,7 +139,7 @@ ifeq ($(PRINT_HELP),y)
|
|||||||
quick-verify:
|
quick-verify:
|
||||||
@echo "$$QUICK_VERIFY_HELP_INFO"
|
@echo "$$QUICK_VERIFY_HELP_INFO"
|
||||||
else
|
else
|
||||||
quick-verify: verify_generated_files
|
quick-verify:
|
||||||
QUICK=true SILENT=false hack/make-rules/verify.sh
|
QUICK=true SILENT=false hack/make-rules/verify.sh
|
||||||
endif
|
endif
|
||||||
|
|
||||||
@ -483,21 +483,6 @@ generated_files:
|
|||||||
$(MAKE) -f Makefile.generated_files $@ CALLED_FROM_MAIN_MAKEFILE=1
|
$(MAKE) -f Makefile.generated_files $@ CALLED_FROM_MAIN_MAKEFILE=1
|
||||||
endif
|
endif
|
||||||
|
|
||||||
define VERIFY_GENERATED_FILES_HELP_INFO
|
|
||||||
# Verify auto-generated files needed for the build.
|
|
||||||
#
|
|
||||||
# Example:
|
|
||||||
# make verify_generated_files
|
|
||||||
endef
|
|
||||||
.PHONY: verify_generated_files
|
|
||||||
ifeq ($(PRINT_HELP),y)
|
|
||||||
verify_generated_files:
|
|
||||||
@echo "$$VERIFY_GENERATED_FILES_HELP_INFO"
|
|
||||||
else
|
|
||||||
verify_generated_files:
|
|
||||||
$(MAKE) -f Makefile.generated_files $@ CALLED_FROM_MAIN_MAKEFILE=1
|
|
||||||
endif
|
|
||||||
|
|
||||||
define HELP_INFO
|
define HELP_INFO
|
||||||
# Print make targets and help info
|
# Print make targets and help info
|
||||||
#
|
#
|
||||||
|
@ -37,81 +37,54 @@ SHELL := /bin/bash
|
|||||||
.PHONY: generated_files
|
.PHONY: generated_files
|
||||||
generated_files: gen_deepcopy gen_defaulter gen_conversion gen_openapi gen_bindata
|
generated_files: gen_deepcopy gen_defaulter gen_conversion gen_openapi gen_bindata
|
||||||
|
|
||||||
.PHONY: verify_generated_files
|
#
|
||||||
verify_generated_files: verify_gen_deepcopy \
|
# Helper logic to calculate Go's dependency DAG ourselves.
|
||||||
verify_gen_defaulter \
|
#
|
||||||
verify_gen_conversion
|
|
||||||
|
# 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 `k8s.io/kubernetes/pkg/api` is
|
||||||
|
# $(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:
|
||||||
|
|
||||||
# Code-generation logic.
|
|
||||||
#
|
#
|
||||||
# This stuff can be pretty tricky, and there's probably some corner cases that
|
# Helper logic to find which directories need codegen as quickly as possible.
|
||||||
# we don't handle well. That said, here's a straightforward test to prove that
|
|
||||||
# the most common cases work. Sadly, it is manual.
|
|
||||||
#
|
#
|
||||||
# make clean
|
|
||||||
# find . -name .make\* | xargs rm -f
|
|
||||||
# find . -name zz_generated\* | xargs rm -f
|
|
||||||
# # verify `find . -name zz_generated.deepcopy.go | wc -l` is 0
|
|
||||||
# # verify `find . -name .make | wc -l` is 0
|
|
||||||
#
|
|
||||||
# make nonexistent
|
|
||||||
# # expect "No rule to make target"
|
|
||||||
# # verify `find .make/ -type f | wc -l` has many files
|
|
||||||
#
|
|
||||||
# make gen_deepcopy
|
|
||||||
# # expect deepcopy-gen is built exactly once
|
|
||||||
# # expect many files to be regenerated
|
|
||||||
# # verify `find . -name zz_generated.deepcopy.go | wc -l` has files
|
|
||||||
# make gen_deepcopy
|
|
||||||
# # expect nothing to be rebuilt, finish in O(seconds)
|
|
||||||
# touch pkg/api/types.go
|
|
||||||
# make gen_deepcopy
|
|
||||||
# # expect one file to be regenerated
|
|
||||||
# make gen_deepcopy
|
|
||||||
# # expect nothing to be rebuilt, finish in O(seconds)
|
|
||||||
# touch vendor/k8s.io/code-generator/cmd/deepcopy-gen/main.go
|
|
||||||
# make gen_deepcopy
|
|
||||||
# # expect deepcopy-gen is built exactly once
|
|
||||||
# # expect many files to be regenerated
|
|
||||||
# # verify `find . -name zz_generated.deepcopy.go | wc -l` has files
|
|
||||||
# make gen_deepcopy
|
|
||||||
# # expect nothing to be rebuilt, finish in O(seconds)
|
|
||||||
#
|
|
||||||
# make gen_conversion
|
|
||||||
# # expect conversion-gen is built exactly once
|
|
||||||
# # expect many files to be regenerated
|
|
||||||
# # verify `find . -name zz_generated.conversion.go | wc -l` has files
|
|
||||||
# make gen_conversion
|
|
||||||
# # expect nothing to be rebuilt, finish in O(seconds)
|
|
||||||
# touch pkg/api/types.go
|
|
||||||
# make gen_conversion
|
|
||||||
# # expect one file to be regenerated
|
|
||||||
# make gen_conversion
|
|
||||||
# # expect nothing to be rebuilt, finish in O(seconds)
|
|
||||||
# touch vendor/k8s.io/code-generator/cmd/conversion-gen/main.go
|
|
||||||
# make gen_conversion
|
|
||||||
# # expect conversion-gen is built exactly once
|
|
||||||
# # expect many files to be regenerated
|
|
||||||
# # verify `find . -name zz_generated.conversion.go | wc -l` has files
|
|
||||||
# make gen_conversion
|
|
||||||
# # expect nothing to be rebuilt, finish in O(seconds)
|
|
||||||
#
|
|
||||||
# make all
|
|
||||||
# # expect it to build
|
|
||||||
#
|
|
||||||
# make test
|
|
||||||
# # expect it to pass
|
|
||||||
#
|
|
||||||
# make clean
|
|
||||||
# # verify `find . -name zz_generated.deepcopy.go | wc -l` is 0
|
|
||||||
# # verify `find . -name .make | wc -l` is 0
|
|
||||||
#
|
|
||||||
# make all WHAT=cmd/kube-proxy
|
|
||||||
# # expect it to build
|
|
||||||
#
|
|
||||||
# make clean
|
|
||||||
# make test WHAT=cmd/kube-proxy
|
|
||||||
# # expect it to pass
|
|
||||||
|
|
||||||
# This variable holds a list of every directory that contains Go files in this
|
# 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
|
# project. Other rules and variables can use this as a starting point to
|
||||||
@ -123,63 +96,6 @@ ALL_GO_DIRS := $(shell \
|
|||||||
hack/make-rules/helpers/cache_go_dirs.sh $(META_DIR)/all_go_dirs.mk \
|
hack/make-rules/helpers/cache_go_dirs.sh $(META_DIR)/all_go_dirs.mk \
|
||||||
)
|
)
|
||||||
|
|
||||||
# The name of the metadata file which lists *.go files in each pkg.
|
|
||||||
GOFILES_META := gofiles.mk
|
|
||||||
|
|
||||||
# Establish a dependency between the deps file and the dir. Whenever a dir
|
|
||||||
# changes (files added or removed) the deps file will be considered stale.
|
|
||||||
#
|
|
||||||
# The variable value was set in $(GOFILES_META) and included as part of the
|
|
||||||
# dependency management logic.
|
|
||||||
#
|
|
||||||
# This is looser than we really need (e.g. we don't really care about non *.go
|
|
||||||
# files or even *_test.go files), but this is much easier to represent.
|
|
||||||
#
|
|
||||||
# Because we 'sinclude' the deps file, it is considered for rebuilding, as part
|
|
||||||
# of make's normal evaluation. If it gets rebuilt, make will restart.
|
|
||||||
#
|
|
||||||
# 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, $(ALL_GO_DIRS), $(eval \
|
|
||||||
$(META_DIR)/$(dir)/$(GOFILES_META): $(dir) \
|
|
||||||
))
|
|
||||||
|
|
||||||
# How to rebuild a deps file. When make determines that the deps file is stale
|
|
||||||
# (see above), it executes this rule, and then re-loads the deps file.
|
|
||||||
#
|
|
||||||
# This is looser than we really need (e.g. we don't really care about test
|
|
||||||
# files), but this is MUCH faster than calling `go list`.
|
|
||||||
#
|
|
||||||
# We regenerate the output file in order to satisfy make's "newer than" rules,
|
|
||||||
# but we only need to rebuild targets if the contents actually changed. That
|
|
||||||
# is what the .stamp file represents.
|
|
||||||
$(foreach dir, $(ALL_GO_DIRS), \
|
|
||||||
$(META_DIR)/$(dir)/$(GOFILES_META)):
|
|
||||||
FILES=$$(ls $</*.go | grep --color=never -v $(GENERATED_FILE_PREFIX)); \
|
|
||||||
mkdir -p $(@D); \
|
|
||||||
echo "gofiles__$< := $$(echo $${FILES})" >$@.tmp; \
|
|
||||||
if ! cmp -s $@.tmp $@; then \
|
|
||||||
if [[ "$(DBG_CODEGEN)" == 1 ]]; then \
|
|
||||||
echo "DBG: gofiles changed for $@"; \
|
|
||||||
fi; \
|
|
||||||
touch $@.stamp; \
|
|
||||||
fi; \
|
|
||||||
mv $@.tmp $@
|
|
||||||
|
|
||||||
# This is required to fill in the DAG, since some cases (e.g. 'make clean all')
|
|
||||||
# will reference the .stamp file when it doesn't exist. We don't need to
|
|
||||||
# rebuild it in that case, just keep make happy.
|
|
||||||
$(foreach dir, $(ALL_GO_DIRS), \
|
|
||||||
$(META_DIR)/$(dir)/$(GOFILES_META).stamp):
|
|
||||||
|
|
||||||
# Include any deps files as additional Makefile rules. This triggers make to
|
|
||||||
# consider the deps files for rebuild, which makes the whole
|
|
||||||
# dependency-management logic work. 'sinclude' is "silent include" which does
|
|
||||||
# not fail if the file does not exist.
|
|
||||||
$(foreach dir, $(ALL_GO_DIRS), $(eval \
|
|
||||||
sinclude $(META_DIR)/$(dir)/$(GOFILES_META) \
|
|
||||||
))
|
|
||||||
|
|
||||||
# Generate a list of all files that have a `+k8s:` comment-tag. This will be
|
# Generate a list of all files that have a `+k8s:` comment-tag. This will be
|
||||||
# used to derive lists of files/dirs for generation tools.
|
# used to derive lists of files/dirs for generation tools.
|
||||||
ifeq ($(DBG_MAKEFILE),1)
|
ifeq ($(DBG_MAKEFILE),1)
|
||||||
@ -190,7 +106,12 @@ ALL_K8S_TAG_FILES := $(shell \
|
|||||||
| xargs grep --color=never -l '^// *+k8s:' \
|
| xargs grep --color=never -l '^// *+k8s:' \
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
|
# Code generation logic.
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
# Deep-copy generation
|
# Deep-copy generation
|
||||||
#
|
#
|
||||||
# Any package that wants deep-copy functions generated must include a
|
# Any package that wants deep-copy functions generated must include a
|
||||||
@ -220,34 +141,27 @@ DEEPCOPY_DIRS := $(shell \
|
|||||||
)
|
)
|
||||||
DEEPCOPY_FILES := $(addsuffix /$(DEEPCOPY_FILENAME), $(DEEPCOPY_DIRS))
|
DEEPCOPY_FILES := $(addsuffix /$(DEEPCOPY_FILENAME), $(DEEPCOPY_DIRS))
|
||||||
|
|
||||||
# Shell function for reuse in rules.
|
# Reset the list of packages that need generation.
|
||||||
RUN_GEN_DEEPCOPY = \
|
$(shell mkdir -p $$(dirname $(META_DIR)/$(DEEPCOPY_GEN)))
|
||||||
function run_gen_deepcopy() { \
|
$(shell rm -f $(META_DIR)/$(DEEPCOPY_GEN).todo)
|
||||||
if [[ -f $(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 \
|
|
||||||
}; \
|
|
||||||
run_gen_deepcopy
|
|
||||||
|
|
||||||
# This rule aggregates the set of files to generate and then generates them all
|
# This rule aggregates the set of files to generate and then generates them all
|
||||||
# in a single run of the tool.
|
# in a single run of the tool.
|
||||||
.PHONY: gen_deepcopy
|
.PHONY: gen_deepcopy
|
||||||
gen_deepcopy: $(DEEPCOPY_FILES) $(DEEPCOPY_GEN)
|
gen_deepcopy: $(DEEPCOPY_GEN) $(META_DIR)/$(DEEPCOPY_GEN).todo
|
||||||
$(RUN_GEN_DEEPCOPY)
|
if [[ -s $(META_DIR)/$(DEEPCOPY_GEN).todo ]]; then \
|
||||||
|
pkgs=$$(cat $(META_DIR)/$(DEEPCOPY_GEN).todo | paste -sd, -); \
|
||||||
.PHONY: verify_gen_deepcopy
|
if [[ "$(DBG_CODEGEN)" == 1 ]]; then \
|
||||||
verify_gen_deepcopy: $(DEEPCOPY_GEN)
|
echo "DBG: running $(DEEPCOPY_GEN) for $$pkgs"; \
|
||||||
$(RUN_GEN_DEEPCOPY) --verify-only
|
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
|
# For each dir in DEEPCOPY_DIRS, this establishes a dependency between the
|
||||||
# output file and the input files that should trigger a rebuild.
|
# output file and the input files that should trigger a rebuild.
|
||||||
@ -258,71 +172,35 @@ verify_gen_deepcopy: $(DEEPCOPY_GEN)
|
|||||||
#
|
#
|
||||||
# The '$(eval)' is needed because this has a different RHS for each LHS, and
|
# The '$(eval)' is needed because this has a different RHS for each LHS, and
|
||||||
# would otherwise produce results that make can't parse.
|
# would otherwise produce results that make can't parse.
|
||||||
#
|
$(foreach dir, $(DEEPCOPY_DIRS), $(eval \
|
||||||
# We depend on the $(GOFILES_META).stamp to detect when the set of input files
|
$(dir)/$(DEEPCOPY_FILENAME): $($(PRJ_SRC_PATH)/$(dir)) \
|
||||||
# has changed. This allows us to detect deleted input files.
|
|
||||||
$(foreach dir, $(DEEPCOPY_DIRS), $(eval \
|
|
||||||
$(dir)/$(DEEPCOPY_FILENAME): $(META_DIR)/$(dir)/$(GOFILES_META).stamp \
|
|
||||||
$(gofiles__$(dir)) \
|
|
||||||
))
|
))
|
||||||
|
|
||||||
# Unilaterally remove any leftovers from previous runs.
|
|
||||||
$(shell rm -f $(META_DIR)/$(DEEPCOPY_GEN)*.todo)
|
|
||||||
|
|
||||||
# How to regenerate deep-copy code. This is a little slow to run, so we batch
|
# 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.
|
# it up and trigger the batch from the 'generated_files' target.
|
||||||
|
$(META_DIR)/$(DEEPCOPY_GEN).todo: $(DEEPCOPY_FILES)
|
||||||
|
|
||||||
$(DEEPCOPY_FILES): $(DEEPCOPY_GEN)
|
$(DEEPCOPY_FILES): $(DEEPCOPY_GEN)
|
||||||
mkdir -p $$(dirname $(META_DIR)/$(DEEPCOPY_GEN))
|
|
||||||
if [[ "$(DBG_CODEGEN)" == 1 ]]; then \
|
if [[ "$(DBG_CODEGEN)" == 1 ]]; then \
|
||||||
echo "DBG: deepcopy needed $(@D): $?"; \
|
echo "DBG: deepcopy needed $(@D): $?"; \
|
||||||
ls -lf --full-time $@ $? || true; \
|
ls -lf --full-time $@ $? || true; \
|
||||||
fi
|
fi
|
||||||
echo $(PRJ_SRC_PATH)/$(@D) >> $(META_DIR)/$(DEEPCOPY_GEN).todo
|
echo $(PRJ_SRC_PATH)/$(@D) >> $(META_DIR)/$(DEEPCOPY_GEN).todo
|
||||||
|
|
||||||
# This calculates the dependencies for the generator tool, so we only rebuild
|
|
||||||
# it when needed. It is PHONY so that it always runs, but it only updates the
|
|
||||||
# file if the contents have actually changed. We 'sinclude' this later.
|
|
||||||
.PHONY: $(META_DIR)/$(DEEPCOPY_GEN).mk
|
|
||||||
$(META_DIR)/$(DEEPCOPY_GEN).mk:
|
|
||||||
mkdir -p $(@D); \
|
|
||||||
(echo -n "$(DEEPCOPY_GEN): "; \
|
|
||||||
./hack/run-in-gopath.sh go list \
|
|
||||||
-f '{{.ImportPath}}{{"\n"}}{{range .Deps}}{{.}}{{"\n"}}{{end}}' \
|
|
||||||
./vendor/k8s.io/code-generator/cmd/deepcopy-gen \
|
|
||||||
| grep --color=never "^$(PRJ_SRC_PATH)/" \
|
|
||||||
| xargs ./hack/run-in-gopath.sh go list \
|
|
||||||
-f '{{$$d := .Dir}}{{$$d}}{{"\n"}}{{range .GoFiles}}{{$$d}}/{{.}}{{"\n"}}{{end}}' \
|
|
||||||
| paste -sd' ' - \
|
|
||||||
| sed 's/ / \\=,/g' \
|
|
||||||
| tr '=,' '\n\t' \
|
|
||||||
| sed "s|$$(pwd -P)/||"; \
|
|
||||||
) > $@.tmp; \
|
|
||||||
if ! cmp -s $@.tmp $@; then \
|
|
||||||
if [[ "$(DBG_CODEGEN)" == 1 ]]; then \
|
|
||||||
echo "DBG: $(DEEPCOPY_GEN).mk changed"; \
|
|
||||||
fi; \
|
|
||||||
cat $@.tmp > $@; \
|
|
||||||
rm -f $@.tmp; \
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Include dependency info for the generator tool. This will cause the rule of
|
|
||||||
# the same name to be considered and if it is updated, make will restart.
|
|
||||||
sinclude $(META_DIR)/$(DEEPCOPY_GEN).mk
|
|
||||||
|
|
||||||
# How to build the generator tool. The deps for this are defined in
|
# How to build the generator tool. The deps for this are defined in
|
||||||
# the $(DEEPCOPY_GEN).mk, above.
|
# the $(GO_PKGDEPS_FILE), above.
|
||||||
#
|
#
|
||||||
# A word on the need to touch: This rule might trigger if, for example, a
|
# 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.
|
# 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
|
# 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
|
# 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,
|
# newer than the binary, and try to "rebuild" it over and over. So we touch
|
||||||
# and make is happy.
|
# it, and make is happy.
|
||||||
$(DEEPCOPY_GEN):
|
$(DEEPCOPY_GEN): $(k8s.io/kubernetes/vendor/k8s.io/code-generator/cmd/deepcopy-gen)
|
||||||
hack/make-rules/build.sh ./vendor/k8s.io/code-generator/cmd/deepcopy-gen
|
hack/make-rules/build.sh ./vendor/k8s.io/code-generator/cmd/deepcopy-gen
|
||||||
touch $@
|
touch $@
|
||||||
|
|
||||||
#
|
|
||||||
# Defaulter generation
|
# Defaulter generation
|
||||||
#
|
#
|
||||||
# Any package that wants defaulter functions generated must include a
|
# Any package that wants defaulter functions generated must include a
|
||||||
@ -359,134 +237,64 @@ DEFAULTER_DIRS := $(shell \
|
|||||||
|
|
||||||
DEFAULTER_FILES := $(addsuffix /$(DEFAULTER_FILENAME), $(DEFAULTER_DIRS))
|
DEFAULTER_FILES := $(addsuffix /$(DEFAULTER_FILENAME), $(DEFAULTER_DIRS))
|
||||||
|
|
||||||
RUN_GEN_DEFAULTER := \
|
# Reset the list of packages that need generation.
|
||||||
function run_gen_defaulter() { \
|
$(shell mkdir -p $$(dirname $(META_DIR)/$(DEFAULTER_GEN)))
|
||||||
if [[ -f $(META_DIR)/$(DEFAULTER_GEN).todo ]]; then \
|
$(shell rm -f $(META_DIR)/$(DEFAULTER_GEN).todo)
|
||||||
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 \
|
|
||||||
}; \
|
|
||||||
run_gen_defaulter
|
|
||||||
|
|
||||||
# This rule aggregates the set of files to generate and then generates them all
|
# This rule aggregates the set of files to generate and then generates them all
|
||||||
# in a single run of the tool.
|
# in a single run of the tool.
|
||||||
.PHONY: gen_defaulter
|
.PHONY: gen_defaulter
|
||||||
gen_defaulter: $(DEFAULTER_FILES) $(DEFAULTER_GEN)
|
gen_defaulter: $(DEFAULTER_GEN) $(META_DIR)/$(DEFAULTER_GEN).todo
|
||||||
$(RUN_GEN_DEFAULTER)
|
if [[ -s $(META_DIR)/$(DEFAULTER_GEN).todo ]]; then \
|
||||||
|
pkgs=$$(cat $(META_DIR)/$(DEFAULTER_GEN).todo | paste -sd, -); \
|
||||||
.PHONY: verify_gen_deepcopy
|
if [[ "$(DBG_CODEGEN)" == 1 ]]; then \
|
||||||
verify_gen_defaulter: $(DEFAULTER_GEN)
|
echo "DBG: running $(DEFAULTER_GEN) for $$pkgs"; \
|
||||||
$(RUN_GEN_DEFAULTER) --verify-only
|
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
|
# For each dir in DEFAULTER_DIRS, this establishes a dependency between the
|
||||||
# output file and the input files that should trigger a rebuild.
|
# output file and the input files that should trigger a rebuild.
|
||||||
#
|
#
|
||||||
# The variable value was set in $(GOFILES_META) and included as part of the
|
# Note that this is a deps-only statement, not a full rule (see below for that).
|
||||||
# dependency management logic.
|
|
||||||
#
|
|
||||||
# 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
|
# The '$(eval)' is needed because this has a different RHS for each LHS, and
|
||||||
# would otherwise produce results that make can't parse.
|
# would otherwise produce results that make can't parse.
|
||||||
#
|
$(foreach dir, $(DEFAULTER_DIRS), $(eval \
|
||||||
# We depend on the $(GOFILES_META).stamp to detect when the set of input files
|
$(dir)/$(DEFAULTER_FILENAME): $($(PRJ_SRC_PATH)/$(dir)) \
|
||||||
# has changed. This allows us to detect deleted input files.
|
|
||||||
$(foreach dir, $(DEFAULTER_DIRS), $(eval \
|
|
||||||
$(dir)/$(DEFAULTER_FILENAME): $(META_DIR)/$(dir)/$(GOFILES_META).stamp \
|
|
||||||
$(gofiles__$(dir)) \
|
|
||||||
))
|
))
|
||||||
|
|
||||||
# For each dir in DEFAULTER_DIRS, for each target in $(defaulters__$(dir)),
|
|
||||||
# this establishes a dependency between the output file and the input files
|
|
||||||
# that should trigger a rebuild.
|
|
||||||
#
|
|
||||||
# The variable value was set in $(GOFILES_META) and included as part of the
|
|
||||||
# dependency management logic.
|
|
||||||
#
|
|
||||||
# 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.
|
|
||||||
#
|
|
||||||
# We depend on the $(GOFILES_META).stamp to detect when the set of input files
|
|
||||||
# has changed. This allows us to detect deleted input files.
|
|
||||||
$(foreach dir, $(DEFAULTER_DIRS), \
|
|
||||||
$(foreach tgt, $(defaulters__$(dir)), $(eval \
|
|
||||||
$(dir)/$(DEFAULTER_FILENAME): $(META_DIR)/$(tgt)/$(GOFILES_META).stamp \
|
|
||||||
$(gofiles__$(tgt)) \
|
|
||||||
)) \
|
|
||||||
)
|
|
||||||
|
|
||||||
# Unilaterally remove any leftovers from previous runs.
|
|
||||||
$(shell rm -f $(META_DIR)/$(DEFAULTER_GEN)*.todo)
|
|
||||||
|
|
||||||
# How to regenerate defaulter code. This is a little slow to run, so we batch
|
# 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.
|
# it up and trigger the batch from the 'generated_files' target.
|
||||||
|
$(META_DIR)/$(DEFAULTER_GEN).todo: $(DEFAULTER_FILES)
|
||||||
|
|
||||||
$(DEFAULTER_FILES): $(DEFAULTER_GEN)
|
$(DEFAULTER_FILES): $(DEFAULTER_GEN)
|
||||||
mkdir -p $$(dirname $(META_DIR)/$(DEFAULTER_GEN))
|
|
||||||
if [[ "$(DBG_CODEGEN)" == 1 ]]; then \
|
if [[ "$(DBG_CODEGEN)" == 1 ]]; then \
|
||||||
echo "DBG: defaulter needed $(@D): $?"; \
|
echo "DBG: defaulter needed $(@D): $?"; \
|
||||||
ls -lf --full-time $@ $? || true; \
|
ls -lf --full-time $@ $? || true; \
|
||||||
fi
|
fi
|
||||||
echo $(PRJ_SRC_PATH)/$(@D) >> $(META_DIR)/$(DEFAULTER_GEN).todo
|
echo $(PRJ_SRC_PATH)/$(@D) >> $(META_DIR)/$(DEFAULTER_GEN).todo
|
||||||
|
|
||||||
# This calculates the dependencies for the generator tool, so we only rebuild
|
|
||||||
# it when needed. It is PHONY so that it always runs, but it only updates the
|
|
||||||
# file if the contents have actually changed. We 'sinclude' this later.
|
|
||||||
.PHONY: $(META_DIR)/$(DEFAULTER_GEN).mk
|
|
||||||
$(META_DIR)/$(DEFAULTER_GEN).mk:
|
|
||||||
mkdir -p $(@D); \
|
|
||||||
(echo -n "$(DEFAULTER_GEN): "; \
|
|
||||||
./hack/run-in-gopath.sh go list \
|
|
||||||
-f '{{.ImportPath}}{{"\n"}}{{range .Deps}}{{.}}{{"\n"}}{{end}}' \
|
|
||||||
./vendor/k8s.io/code-generator/cmd/defaulter-gen \
|
|
||||||
| grep --color=never "^$(PRJ_SRC_PATH)/" \
|
|
||||||
| xargs ./hack/run-in-gopath.sh go list \
|
|
||||||
-f '{{$$d := .Dir}}{{$$d}}{{"\n"}}{{range .GoFiles}}{{$$d}}/{{.}}{{"\n"}}{{end}}' \
|
|
||||||
| paste -sd' ' - \
|
|
||||||
| sed 's/ / \\=,/g' \
|
|
||||||
| tr '=,' '\n\t' \
|
|
||||||
| sed "s|$$(pwd -P)/||"; \
|
|
||||||
) > $@.tmp; \
|
|
||||||
if ! cmp -s $@.tmp $@; then \
|
|
||||||
if [[ "$(DBG_CODEGEN)" == 1 ]]; then \
|
|
||||||
echo "DBG: $(DEFAULTER_GEN).mk changed"; \
|
|
||||||
fi; \
|
|
||||||
cat $@.tmp > $@; \
|
|
||||||
rm -f $@.tmp; \
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Include dependency info for the generator tool. This will cause the rule of
|
|
||||||
# the same name to be considered and if it is updated, make will restart.
|
|
||||||
sinclude $(META_DIR)/$(DEFAULTER_GEN).mk
|
|
||||||
|
|
||||||
# How to build the generator tool. The deps for this are defined in
|
# How to build the generator tool. The deps for this are defined in
|
||||||
# the $(DEFAULTER_GEN).mk, above.
|
# the $(GO_PKGDEPS_FILE), above.
|
||||||
#
|
#
|
||||||
# A word on the need to touch: This rule might trigger if, for example, a
|
# 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.
|
# 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
|
# 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
|
# 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,
|
# newer than the binary, and try to "rebuild" it over and over. So we touch
|
||||||
# and make is happy.
|
# it, and make is happy.
|
||||||
$(DEFAULTER_GEN):
|
$(DEFAULTER_GEN): $(k8s.io/kubernetes/vendor/k8s.io/code-generator/cmd/defaulter-gen)
|
||||||
hack/make-rules/build.sh ./vendor/k8s.io/code-generator/cmd/defaulter-gen
|
hack/make-rules/build.sh ./vendor/k8s.io/code-generator/cmd/defaulter-gen
|
||||||
touch $@
|
touch $@
|
||||||
|
|
||||||
#
|
|
||||||
# Conversion generation
|
# Conversion generation
|
||||||
#
|
#
|
||||||
# Any package that wants conversion functions generated must include one or
|
# Any package that wants conversion functions generated must include one or
|
||||||
@ -526,171 +334,52 @@ CONVERSION_DIRS := $(shell \
|
|||||||
CONVERSION_FILES := $(addsuffix /$(CONVERSION_FILENAME), $(CONVERSION_DIRS))
|
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
|
CONVERSION_EXTRA_PEER_DIRS := k8s.io/kubernetes/pkg/apis/core,k8s.io/kubernetes/pkg/apis/core/v1,k8s.io/api/core/v1
|
||||||
|
|
||||||
# Shell function for reuse in rules.
|
# Reset the list of packages that need generation.
|
||||||
RUN_GEN_CONVERSION = \
|
$(shell mkdir -p $$(dirname $(META_DIR)/$(CONVERSION_GEN)))
|
||||||
function run_gen_conversion() { \
|
$(shell rm -f $(META_DIR)/$(CONVERSION_GEN).todo)
|
||||||
if [[ -f $(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 \
|
|
||||||
}; \
|
|
||||||
run_gen_conversion
|
|
||||||
|
|
||||||
# This rule aggregates the set of files to generate and then generates them all
|
# This rule aggregates the set of files to generate and then generates them all
|
||||||
# in a single run of the tool.
|
# in a single run of the tool.
|
||||||
.PHONY: gen_conversion
|
.PHONY: gen_conversion
|
||||||
gen_conversion: $(CONVERSION_FILES) $(CONVERSION_GEN)
|
gen_conversion: $(CONVERSION_GEN) $(META_DIR)/$(CONVERSION_GEN).todo
|
||||||
$(RUN_GEN_CONVERSION)
|
if [[ -s $(META_DIR)/$(CONVERSION_GEN).todo ]]; then \
|
||||||
|
pkgs=$$(cat $(META_DIR)/$(CONVERSION_GEN).todo | paste -sd, -); \
|
||||||
.PHONY: verify_gen_conversion
|
if [[ "$(DBG_CODEGEN)" == 1 ]]; then \
|
||||||
verify_gen_conversion: $(CONVERSION_GEN)
|
echo "DBG: running $(CONVERSION_GEN) for $$pkgs"; \
|
||||||
$(RUN_GEN_CONVERSION) --verify-only
|
fi; \
|
||||||
|
./hack/run-in-gopath.sh $(CONVERSION_GEN) \
|
||||||
# Establish a dependency between the deps file and the dir. Whenever a dir
|
--extra-peer-dirs $(CONVERSION_EXTRA_PEER_DIRS) \
|
||||||
# changes (files added or removed) the deps file will be considered stale.
|
--v $(KUBE_VERBOSE) \
|
||||||
#
|
--logtostderr \
|
||||||
# This is looser than we really need (e.g. we don't really care about non *.go
|
-i "$$pkgs" \
|
||||||
# files or even *_test.go files), but this is much easier to represent.
|
-O $(CONVERSION_BASENAME) \
|
||||||
#
|
"$$@"; \
|
||||||
# Because we 'sinclude' the deps file, it is considered for rebuilding, as part
|
fi
|
||||||
# of make's normal evaluation. If it gets rebuilt, make will restart.
|
|
||||||
#
|
|
||||||
# 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 \
|
|
||||||
$(META_DIR)/$(dir)/$(CONVERSIONS_META): $(dir) \
|
|
||||||
))
|
|
||||||
|
|
||||||
# How to rebuild a deps file. When make determines that the deps file is stale
|
|
||||||
# (see above), it executes this rule, and then re-loads the deps file.
|
|
||||||
#
|
|
||||||
# This is looser than we really need (e.g. we don't really care about test
|
|
||||||
# files), but this is MUCH faster than calling `go list`.
|
|
||||||
#
|
|
||||||
# We regenerate the output file in order to satisfy make's "newer than" rules,
|
|
||||||
# but we only need to rebuild targets if the contents actually changed. That
|
|
||||||
# is what the .stamp file represents.
|
|
||||||
$(foreach dir, $(CONVERSION_DIRS), \
|
|
||||||
$(META_DIR)/$(dir)/$(CONVERSIONS_META)):
|
|
||||||
TAGS=$$(grep --color=never -h '^// *+k8s:conversion-gen=' $</*.go \
|
|
||||||
| cut -f2- -d= \
|
|
||||||
| sed 's|$(PRJ_SRC_PATH)/||' \
|
|
||||||
| sed 's|^k8s.io/|vendor/k8s.io/|'); \
|
|
||||||
mkdir -p $(@D); \
|
|
||||||
echo "conversions__$< := $$(echo $${TAGS})" >$@.tmp; \
|
|
||||||
if ! cmp -s $@.tmp $@; then \
|
|
||||||
if [[ "$(DBG_CODEGEN)" == 1 ]]; then \
|
|
||||||
echo "DBG: conversions changed for $@"; \
|
|
||||||
fi; \
|
|
||||||
touch $@.stamp; \
|
|
||||||
fi; \
|
|
||||||
mv $@.tmp $@
|
|
||||||
|
|
||||||
# Include any deps files as additional Makefile rules. This triggers make to
|
|
||||||
# consider the deps files for rebuild, which makes the whole
|
|
||||||
# dependency-management logic work. 'sinclude' is "silent include" which does
|
|
||||||
# not fail if the file does not exist.
|
|
||||||
$(foreach dir, $(CONVERSION_DIRS), $(eval \
|
|
||||||
sinclude $(META_DIR)/$(dir)/$(CONVERSIONS_META) \
|
|
||||||
))
|
|
||||||
|
|
||||||
# For each dir in CONVERSION_DIRS, this establishes a dependency between the
|
# For each dir in CONVERSION_DIRS, this establishes a dependency between the
|
||||||
# output file and the input files that should trigger a rebuild.
|
# output file and the input files that should trigger a rebuild.
|
||||||
#
|
#
|
||||||
# The variable value was set in $(GOFILES_META) and included as part of the
|
# Note that this is a deps-only statement, not a full rule (see below for that).
|
||||||
# dependency management logic.
|
|
||||||
#
|
|
||||||
# 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
|
# The '$(eval)' is needed because this has a different RHS for each LHS, and
|
||||||
# would otherwise produce results that make can't parse.
|
# would otherwise produce results that make can't parse.
|
||||||
#
|
$(foreach dir, $(CONVERSION_DIRS), $(eval \
|
||||||
# We depend on the $(GOFILES_META).stamp to detect when the set of input files
|
$(dir)/$(CONVERSION_FILENAME): $($(PRJ_SRC_PATH)/$(dir)) \
|
||||||
# has changed. This allows us to detect deleted input files.
|
|
||||||
$(foreach dir, $(CONVERSION_DIRS), $(eval \
|
|
||||||
$(dir)/$(CONVERSION_FILENAME): $(META_DIR)/$(dir)/$(GOFILES_META).stamp \
|
|
||||||
$(gofiles__$(dir)) \
|
|
||||||
))
|
))
|
||||||
|
|
||||||
# For each dir in CONVERSION_DIRS, for each target in $(conversions__$(dir)),
|
|
||||||
# this establishes a dependency between the output file and the input files
|
|
||||||
# that should trigger a rebuild.
|
|
||||||
#
|
|
||||||
# The variable value was set in $(GOFILES_META) and included as part of the
|
|
||||||
# dependency management logic.
|
|
||||||
#
|
|
||||||
# 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.
|
|
||||||
#
|
|
||||||
# We depend on the $(GOFILES_META).stamp to detect when the set of input files
|
|
||||||
# has changed. This allows us to detect deleted input files.
|
|
||||||
$(foreach dir, $(CONVERSION_DIRS), \
|
|
||||||
$(foreach tgt, $(conversions__$(dir)), $(eval \
|
|
||||||
$(dir)/$(CONVERSION_FILENAME): $(META_DIR)/$(tgt)/$(GOFILES_META).stamp \
|
|
||||||
$(gofiles__$(tgt)) \
|
|
||||||
)) \
|
|
||||||
)
|
|
||||||
|
|
||||||
# Unilaterally remove any leftovers from previous runs.
|
|
||||||
$(shell rm -f $(META_DIR)/$(CONVERSION_GEN)*.todo)
|
|
||||||
|
|
||||||
# How to regenerate conversion code. This is a little slow to run, so we batch
|
# 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.
|
# it up and trigger the batch from the 'generated_files' target.
|
||||||
|
$(META_DIR)/$(CONVERSION_GEN).todo: $(CONVERSION_FILES)
|
||||||
|
|
||||||
$(CONVERSION_FILES): $(CONVERSION_GEN)
|
$(CONVERSION_FILES): $(CONVERSION_GEN)
|
||||||
mkdir -p $$(dirname $(META_DIR)/$(CONVERSION_GEN))
|
|
||||||
if [[ "$(DBG_CODEGEN)" == 1 ]]; then \
|
if [[ "$(DBG_CODEGEN)" == 1 ]]; then \
|
||||||
echo "DBG: conversion needed $(@D): $?"; \
|
echo "DBG: conversion needed $(@D): $?"; \
|
||||||
ls -lf --full-time $@ $? || true; \
|
ls -lf --full-time $@ $? || true; \
|
||||||
fi
|
fi
|
||||||
echo $(PRJ_SRC_PATH)/$(@D) >> $(META_DIR)/$(CONVERSION_GEN).todo
|
echo $(PRJ_SRC_PATH)/$(@D) >> $(META_DIR)/$(CONVERSION_GEN).todo
|
||||||
|
|
||||||
# This calculates the dependencies for the generator tool, so we only rebuild
|
|
||||||
# it when needed. It is PHONY so that it always runs, but it only updates the
|
|
||||||
# file if the contents have actually changed. We 'sinclude' this later.
|
|
||||||
.PHONY: $(META_DIR)/$(CONVERSION_GEN).mk
|
|
||||||
$(META_DIR)/$(CONVERSION_GEN).mk:
|
|
||||||
mkdir -p $(@D); \
|
|
||||||
(echo -n "$(CONVERSION_GEN): "; \
|
|
||||||
./hack/run-in-gopath.sh go list \
|
|
||||||
-f '{{.ImportPath}}{{"\n"}}{{range .Deps}}{{.}}{{"\n"}}{{end}}' \
|
|
||||||
./vendor/k8s.io/code-generator/cmd/conversion-gen \
|
|
||||||
| grep --color=never "^$(PRJ_SRC_PATH)/" \
|
|
||||||
| xargs ./hack/run-in-gopath.sh go list \
|
|
||||||
-f '{{$$d := .Dir}}{{$$d}}{{"\n"}}{{range .GoFiles}}{{$$d}}/{{.}}{{"\n"}}{{end}}' \
|
|
||||||
| paste -sd' ' - \
|
|
||||||
| sed 's/ / \\=,/g' \
|
|
||||||
| tr '=,' '\n\t' \
|
|
||||||
| sed "s|$$(pwd -P)/||"; \
|
|
||||||
) > $@.tmp; \
|
|
||||||
if ! cmp -s $@.tmp $@; then \
|
|
||||||
if [[ "$(DBG_CODEGEN)" == 1 ]]; then \
|
|
||||||
echo "DBG: $(CONVERSION_GEN).mk changed"; \
|
|
||||||
fi; \
|
|
||||||
cat $@.tmp > $@; \
|
|
||||||
rm -f $@.tmp; \
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Include dependency info for the generator tool. This will cause the rule of
|
|
||||||
# the same name to be considered and if it is updated, make will restart.
|
|
||||||
sinclude $(META_DIR)/$(CONVERSION_GEN).mk
|
|
||||||
|
|
||||||
# How to build the generator tool. The deps for this are defined in
|
# How to build the generator tool. The deps for this are defined in
|
||||||
# the $(CONVERSION_GEN).mk, above.
|
# the $(GO_PKGDEPS_FILE), above.
|
||||||
#
|
#
|
||||||
# A word on the need to touch: This rule might trigger if, for example, a
|
# 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.
|
# non-Go file was added or deleted from a directory on which this depends.
|
||||||
@ -698,12 +387,12 @@ sinclude $(META_DIR)/$(CONVERSION_GEN).mk
|
|||||||
# have to be rebuilt. In that case, make will forever see the dependency as
|
# 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,
|
# newer than the binary, and try to rebuild it over and over. So we touch it,
|
||||||
# and make is happy.
|
# and make is happy.
|
||||||
$(CONVERSION_GEN):
|
$(CONVERSION_GEN): $(k8s.io/kubernetes/vendor/k8s.io/code-generator/cmd/conversion-gen)
|
||||||
hack/make-rules/build.sh ./vendor/k8s.io/code-generator/cmd/conversion-gen
|
hack/make-rules/build.sh ./vendor/k8s.io/code-generator/cmd/conversion-gen
|
||||||
touch $@
|
touch $@
|
||||||
|
|
||||||
#
|
|
||||||
# Open-api generation
|
# OpenAPI generation
|
||||||
#
|
#
|
||||||
# Any package that wants open-api functions generated must include a
|
# Any package that wants open-api functions generated must include a
|
||||||
# comment-tag in column 0 of one file of the form:
|
# comment-tag in column 0 of one file of the form:
|
||||||
@ -736,77 +425,38 @@ gen_openapi: $(OPENAPI_OUTFILE) $(OPENAPI_GEN)
|
|||||||
# For each dir in OPENAPI_DIRS, this establishes a dependency between the
|
# For each dir in OPENAPI_DIRS, this establishes a dependency between the
|
||||||
# output file and the input files that should trigger a rebuild.
|
# 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
|
# Note that this is a deps-only statement, not a full rule (see below for that).
|
||||||
# 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
|
# The '$(eval)' is needed because this has a different RHS for each LHS, and
|
||||||
# would otherwise produce results that make can't parse.
|
# would otherwise produce results that make can't parse.
|
||||||
#
|
$(foreach dir, $(OPENAPI_DIRS), $(eval \
|
||||||
# We depend on the $(GOFILES_META).stamp to detect when the set of input files
|
$(OPENAPI_OUTFILE): $($(PRJ_SRC_PATH)/$(dir)) \
|
||||||
# has changed. This allows us to detect deleted input files.
|
|
||||||
$(foreach dir, $(OPENAPI_DIRS), $(eval \
|
|
||||||
$(OPENAPI_OUTFILE): $(META_DIR)/$(dir)/$(GOFILES_META).stamp \
|
|
||||||
$(gofiles__$(dir)) \
|
|
||||||
))
|
))
|
||||||
|
|
||||||
# How to regenerate open-api code. This emits a single file for all results.
|
# How to regenerate open-api code. This emits a single file for all results.
|
||||||
$(OPENAPI_OUTFILE): $(OPENAPI_GEN) $(OPENAPI_GEN)
|
$(OPENAPI_OUTFILE): $(OPENAPI_GEN)
|
||||||
function run_gen_openapi() { \
|
./hack/run-in-gopath.sh $(OPENAPI_GEN) \
|
||||||
./hack/run-in-gopath.sh $(OPENAPI_GEN) \
|
--v $(KUBE_VERBOSE) \
|
||||||
--v $(KUBE_VERBOSE) \
|
--logtostderr \
|
||||||
--logtostderr \
|
-i $$(echo $(addprefix $(PRJ_SRC_PATH)/, $(OPENAPI_DIRS)) | sed 's/ /,/g') \
|
||||||
-i $$(echo $(addprefix $(PRJ_SRC_PATH)/, $(OPENAPI_DIRS)) | sed 's/ /,/g') \
|
-p $(PRJ_SRC_PATH)/$(OPENAPI_OUTPUT_PKG) \
|
||||||
-p $(PRJ_SRC_PATH)/$(OPENAPI_OUTPUT_PKG) \
|
-O $(OPENAPI_BASENAME) \
|
||||||
-O $(OPENAPI_BASENAME) \
|
"$$@"
|
||||||
"$$@"; \
|
|
||||||
}; \
|
|
||||||
run_gen_openapi
|
|
||||||
|
|
||||||
# This calculates the dependencies for the generator tool, so we only rebuild
|
|
||||||
# it when needed. It is PHONY so that it always runs, but it only updates the
|
|
||||||
# file if the contents have actually changed. We 'sinclude' this later.
|
|
||||||
.PHONY: $(META_DIR)/$(OPENAPI_GEN).mk
|
|
||||||
$(META_DIR)/$(OPENAPI_GEN).mk:
|
|
||||||
mkdir -p $(@D); \
|
|
||||||
(echo -n "$(OPENAPI_GEN): "; \
|
|
||||||
./hack/run-in-gopath.sh go list \
|
|
||||||
-f '{{.ImportPath}}{{"\n"}}{{range .Deps}}{{.}}{{"\n"}}{{end}}' \
|
|
||||||
./vendor/k8s.io/code-generator/cmd/openapi-gen \
|
|
||||||
| grep --color=never "^$(PRJ_SRC_PATH)/" \
|
|
||||||
| xargs ./hack/run-in-gopath.sh go list \
|
|
||||||
-f '{{$$d := .Dir}}{{$$d}}{{"\n"}}{{range .GoFiles}}{{$$d}}/{{.}}{{"\n"}}{{end}}' \
|
|
||||||
| paste -sd' ' - \
|
|
||||||
| sed 's/ / \\=,/g' \
|
|
||||||
| tr '=,' '\n\t' \
|
|
||||||
| sed "s|$$(pwd -P)/||"; \
|
|
||||||
) > $@.tmp; \
|
|
||||||
if ! cmp -s $@.tmp $@; then \
|
|
||||||
if [[ "$(DBG_CODEGEN)" == 1 ]]; then \
|
|
||||||
echo "DBG: $(OPENAPI_GEN).mk changed"; \
|
|
||||||
fi; \
|
|
||||||
cat $@.tmp > $@; \
|
|
||||||
rm -f $@.tmp; \
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Include dependency info for the generator tool. This will cause the rule of
|
|
||||||
# the same name to be considered and if it is updated, make will restart.
|
|
||||||
sinclude $(META_DIR)/$(OPENAPI_GEN).mk
|
|
||||||
|
|
||||||
# How to build the generator tool. The deps for this are defined in
|
# How to build the generator tool. The deps for this are defined in
|
||||||
# the $(OPENAPI_GEN).mk, above.
|
# the $(GO_PKGDEPS_FILE), above.
|
||||||
#
|
#
|
||||||
# A word on the need to touch: This rule might trigger if, for example, a
|
# 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.
|
# 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
|
# 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
|
# 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,
|
# newer than the binary, and try to "rebuild" it over and over. So we touch
|
||||||
# and make is happy.
|
# it, and make is happy.
|
||||||
$(OPENAPI_GEN):
|
$(OPENAPI_GEN): $(k8s.io/kubernetes/vendor/k8s.io/code-generator/cmd/openapi-gen)
|
||||||
hack/make-rules/build.sh ./vendor/k8s.io/code-generator/cmd/openapi-gen
|
hack/make-rules/build.sh ./vendor/k8s.io/code-generator/cmd/openapi-gen
|
||||||
touch $@
|
touch $@
|
||||||
|
|
||||||
#
|
|
||||||
# bindata generation
|
# bindata generation
|
||||||
#
|
#
|
||||||
|
|
||||||
@ -822,38 +472,6 @@ BINDATA_SCRIPT := hack/generate-bindata.sh
|
|||||||
gen_bindata: $(BINDATA_GEN) FORCE
|
gen_bindata: $(BINDATA_GEN) FORCE
|
||||||
./hack/run-in-gopath.sh $(BINDATA_SCRIPT)
|
./hack/run-in-gopath.sh $(BINDATA_SCRIPT)
|
||||||
|
|
||||||
FORCE:
|
|
||||||
|
|
||||||
# This calculates the dependencies for the generator tool, so we only rebuild
|
|
||||||
# it when needed. It is PHONY so that it always runs, but it only updates the
|
|
||||||
# file if the contents have actually changed. We 'sinclude' this later.
|
|
||||||
.PHONY: $(META_DIR)/$(BINDATA_GEN).mk
|
|
||||||
$(META_DIR)/$(BINDATA_GEN).mk:
|
|
||||||
mkdir -p $(@D); \
|
|
||||||
(echo -n "$(BINDATA_GEN): "; \
|
|
||||||
./hack/run-in-gopath.sh go list \
|
|
||||||
-f '{{.ImportPath}}{{"\n"}}{{range .Deps}}{{.}}{{"\n"}}{{end}}' \
|
|
||||||
./vendor/github.com/jteeuwen/go-bindata/go-bindata \
|
|
||||||
| grep --color=never "^$(PRJ_SRC_PATH)/" \
|
|
||||||
| xargs ./hack/run-in-gopath.sh go list \
|
|
||||||
-f '{{$$d := .Dir}}{{$$d}}{{"\n"}}{{range .GoFiles}}{{$$d}}/{{.}}{{"\n"}}{{end}}' \
|
|
||||||
| paste -sd' ' - \
|
|
||||||
| sed 's/ / \\=,/g' \
|
|
||||||
| tr '=,' '\n\t' \
|
|
||||||
| sed "s|$$(pwd -P)/||"; \
|
|
||||||
) > $@.tmp; \
|
|
||||||
if ! cmp -s $@.tmp $@; then \
|
|
||||||
if [[ "$(DBG_CODEGEN)" == 1 ]]; then \
|
|
||||||
echo "DBG: $(BINDATA_GEN).mk changed"; \
|
|
||||||
fi; \
|
|
||||||
cat $@.tmp > $@; \
|
|
||||||
rm -f $@.tmp; \
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Include dependency info for the generator tool. This will cause the rule of
|
|
||||||
# the same name to be considered and if it is updated, make will restart.
|
|
||||||
sinclude $(META_DIR)/$(BINDATA_GEN).mk
|
|
||||||
|
|
||||||
# How to build the generator tool. The deps for this are defined in
|
# How to build the generator tool. The deps for this are defined in
|
||||||
# the $(BINDATA_GEN).mk, above.
|
# the $(BINDATA_GEN).mk, above.
|
||||||
#
|
#
|
||||||
@ -863,6 +481,6 @@ sinclude $(META_DIR)/$(BINDATA_GEN).mk
|
|||||||
# have to be rebuilt. In that case, make will forever see the dependency as
|
# 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,
|
# newer than the binary, and try to rebuild it over and over. So we touch it,
|
||||||
# and make is happy.
|
# and make is happy.
|
||||||
$(BINDATA_GEN):
|
$(BINDATA_GEN): $(k8s.io/kubernetes/vendor/github.com/jteeuwen/go-bindata/go-bindata)
|
||||||
hack/make-rules/build.sh ./vendor/github.com/jteeuwen/go-bindata/go-bindata
|
hack/make-rules/build.sh ./vendor/github.com/jteeuwen/go-bindata/go-bindata
|
||||||
touch $@
|
touch $@
|
||||||
|
@ -106,7 +106,10 @@ filegroup(
|
|||||||
|
|
||||||
filegroup(
|
filegroup(
|
||||||
name = "all-srcs",
|
name = "all-srcs",
|
||||||
srcs = [":package-srcs"],
|
srcs = [
|
||||||
|
":package-srcs",
|
||||||
|
"//hack/make-rules/helpers/go2make:all-srcs",
|
||||||
|
],
|
||||||
tags = ["automanaged"],
|
tags = ["automanaged"],
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
)
|
)
|
||||||
|
@ -36,22 +36,23 @@ trap "rm -f '${CACHE}'" HUP INT TERM ERR
|
|||||||
# Example:
|
# Example:
|
||||||
# kfind -type f -name foobar.go
|
# kfind -type f -name foobar.go
|
||||||
function kfind() {
|
function kfind() {
|
||||||
# include the "special" vendor directories which are actually part
|
# We want to include the "special" vendor directories which are actually
|
||||||
# of the Kubernetes source tree - generators will use these for
|
# part of the Kubernetes source tree (./staging/*) but we need them to be
|
||||||
# including certain core API concepts.
|
# named as their ./vendor/* equivalents. Also, we do not want all of
|
||||||
find -H . ./vendor/k8s.io/apimachinery ./vendor/k8s.io/apiserver ./vendor/k8s.io/kube-aggregator ./vendor/k8s.io/apiextensions-apiserver ./vendor/k8s.io/metrics ./vendor/k8s.io/sample-apiserver ./vendor/k8s.io/api ./vendor/k8s.io/client-go ./vendor/k8s.io/code-generator ./vendor/k8s.io/sample-controller \
|
# ./vendor or even all of ./vendor/k8s.io.
|
||||||
|
find -H . \
|
||||||
\( \
|
\( \
|
||||||
-not \( \
|
-not \( \
|
||||||
\( \
|
\( \
|
||||||
-path ./vendor -o \
|
-path ./vendor -o \
|
||||||
-path ./staging -o \
|
|
||||||
-path ./_\* -o \
|
-path ./_\* -o \
|
||||||
-path ./.\* -o \
|
-path ./.\* -o \
|
||||||
-path ./docs \
|
-path ./docs \
|
||||||
\) -prune \
|
\) -prune \
|
||||||
\) \
|
\) \
|
||||||
\) \
|
\) \
|
||||||
"$@"
|
"$@" \
|
||||||
|
| sed 's|^./staging/src|vendor|'
|
||||||
}
|
}
|
||||||
|
|
||||||
NEED_FIND=true
|
NEED_FIND=true
|
||||||
|
41
hack/make-rules/helpers/go2make/BUILD
Normal file
41
hack/make-rules/helpers/go2make/BUILD
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
# gazelle:exclude testdata
|
||||||
|
|
||||||
|
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library", "go_test")
|
||||||
|
|
||||||
|
go_library(
|
||||||
|
name = "go_default_library",
|
||||||
|
srcs = [
|
||||||
|
"go2make.go",
|
||||||
|
"pkgwalk.go",
|
||||||
|
],
|
||||||
|
importpath = "k8s.io/kubernetes/hack/make-rules/helpers/go2make",
|
||||||
|
visibility = ["//visibility:private"],
|
||||||
|
deps = ["//vendor/github.com/spf13/pflag:go_default_library"],
|
||||||
|
)
|
||||||
|
|
||||||
|
go_binary(
|
||||||
|
name = "go2make",
|
||||||
|
embed = [":go_default_library"],
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
|
)
|
||||||
|
|
||||||
|
go_test(
|
||||||
|
name = "go_default_test",
|
||||||
|
srcs = ["pkgwalk_test.go"],
|
||||||
|
data = glob(["testdata/**"]),
|
||||||
|
embed = [":go_default_library"],
|
||||||
|
)
|
||||||
|
|
||||||
|
filegroup(
|
||||||
|
name = "package-srcs",
|
||||||
|
srcs = glob(["**"]),
|
||||||
|
tags = ["automanaged"],
|
||||||
|
visibility = ["//visibility:private"],
|
||||||
|
)
|
||||||
|
|
||||||
|
filegroup(
|
||||||
|
name = "all-srcs",
|
||||||
|
srcs = [":package-srcs"],
|
||||||
|
tags = ["automanaged"],
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
|
)
|
215
hack/make-rules/helpers/go2make/go2make.go
Normal file
215
hack/make-rules/helpers/go2make/go2make.go
Normal file
@ -0,0 +1,215 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2017 The Kubernetes Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
goflag "flag"
|
||||||
|
"fmt"
|
||||||
|
"go/build"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/spf13/pflag"
|
||||||
|
)
|
||||||
|
|
||||||
|
var flPrune = pflag.StringSlice("prune", nil, "sub-packages to prune (recursive, may be specified multiple times)")
|
||||||
|
var flDebug = pflag.BoolP("debug", "d", false, "enable debugging output")
|
||||||
|
var flHelp = pflag.BoolP("help", "h", false, "print help and exit")
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
pflag.CommandLine.AddGoFlagSet(goflag.CommandLine)
|
||||||
|
pflag.Usage = func() { help(os.Stderr) }
|
||||||
|
pflag.Parse()
|
||||||
|
|
||||||
|
debug("PWD", getwd())
|
||||||
|
|
||||||
|
build.Default.BuildTags = []string{"ignore_autogenerated"}
|
||||||
|
build.Default.UseAllFiles = false
|
||||||
|
|
||||||
|
if *flHelp {
|
||||||
|
help(os.Stdout)
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
if len(pflag.Args()) == 0 {
|
||||||
|
help(os.Stderr)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
for _, in := range pflag.Args() {
|
||||||
|
if strings.HasSuffix(in, "/...") {
|
||||||
|
// Recurse.
|
||||||
|
debug("starting", in)
|
||||||
|
pkgName := strings.TrimSuffix(in, "/...")
|
||||||
|
if err := WalkPkg(pkgName, visitPkg); err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Import one package.
|
||||||
|
if err := saveImport(in); err != nil {
|
||||||
|
fmt.Fprintln(os.Stderr, err)
|
||||||
|
os.Exit(2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func help(out io.Writer) {
|
||||||
|
fmt.Fprintf(out, "Usage: %s [FLAG...] <PKG...>\n", os.Args[0])
|
||||||
|
fmt.Fprintf(out, "\n")
|
||||||
|
fmt.Fprintf(out, "go2make calculates all of the dependencies of a set of Go packages and prints\n")
|
||||||
|
fmt.Fprintf(out, "them as variable definitions suitable for use as a Makefile.\n")
|
||||||
|
fmt.Fprintf(out, "\n")
|
||||||
|
fmt.Fprintf(out, "Package specifications may be simple (e.g. 'example.com/txt/color') or\n")
|
||||||
|
fmt.Fprintf(out, "recursive (e.g. 'example.com/txt/...')\n")
|
||||||
|
fmt.Fprintf(out, " Example:\n")
|
||||||
|
fmt.Fprintf(out, " $ %s ./example.com/pretty\n", os.Args[0])
|
||||||
|
fmt.Fprintf(out, " example.com/txt/split := \\\n")
|
||||||
|
fmt.Fprintf(out, " /go/src/example.com/txt/split/ \\\n")
|
||||||
|
fmt.Fprintf(out, " /go/src/example.com/txt/split/split.go \\\n")
|
||||||
|
fmt.Fprintf(out, " ./example.com/pretty := \\\n")
|
||||||
|
fmt.Fprintf(out, " /go/src/example.com/pretty/ \\\n")
|
||||||
|
fmt.Fprintf(out, " /go/src/example.com/pretty/print.go \\\n")
|
||||||
|
fmt.Fprintf(out, " /go/src/example.com/txt/split/ \\\n")
|
||||||
|
fmt.Fprintf(out, " /go/src/example.com/txt/split/split.go\n")
|
||||||
|
fmt.Fprintf(out, "\n")
|
||||||
|
fmt.Fprintf(out, " Flags:\n")
|
||||||
|
|
||||||
|
pflag.PrintDefaults()
|
||||||
|
}
|
||||||
|
|
||||||
|
func debug(items ...interface{}) {
|
||||||
|
if *flDebug {
|
||||||
|
x := []interface{}{"DBG:"}
|
||||||
|
x = append(x, items...)
|
||||||
|
fmt.Println(x...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func visitPkg(importPath, absPath string) error {
|
||||||
|
debug("visit", importPath)
|
||||||
|
return saveImport(importPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
func prune(pkgName string) bool {
|
||||||
|
for _, pr := range *flPrune {
|
||||||
|
if pr == pkgName {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// cache keeps track of which packages we have already loaded.
|
||||||
|
var cache = map[string]*build.Package{}
|
||||||
|
|
||||||
|
func saveImport(pkgName string) error {
|
||||||
|
if cache[pkgName] != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if prune(pkgName) {
|
||||||
|
debug("prune", pkgName)
|
||||||
|
return ErrSkipPkg
|
||||||
|
}
|
||||||
|
pkg, err := loadPackage(pkgName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
debug("save", pkgName)
|
||||||
|
cache[pkgName] = pkg
|
||||||
|
|
||||||
|
debug("recurse", pkgName)
|
||||||
|
defer func() { debug("done ", pkgName) }()
|
||||||
|
if !pkg.Goroot && (len(pkg.GoFiles)+len(pkg.Imports) > 0) {
|
||||||
|
// Process deps of this package before the package itself.
|
||||||
|
for _, impName := range pkg.Imports {
|
||||||
|
if impName == "C" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
debug("depends on", impName)
|
||||||
|
saveImport(impName)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Emit a variable for each package.
|
||||||
|
var buf bytes.Buffer
|
||||||
|
buf.WriteString(pkgName)
|
||||||
|
buf.WriteString(" := ")
|
||||||
|
|
||||||
|
// Packages depend on their own directories, their own files, and
|
||||||
|
// transitive list of all deps' directories and files.
|
||||||
|
all := map[string]struct{}{}
|
||||||
|
all[pkg.Dir+"/"] = struct{}{}
|
||||||
|
filesForPkg(pkg, all)
|
||||||
|
for _, imp := range pkg.Imports {
|
||||||
|
pkg := cache[imp]
|
||||||
|
if pkg == nil || pkg.Goroot {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
all[pkg.Dir+"/"] = struct{}{}
|
||||||
|
filesForPkg(pkg, all)
|
||||||
|
}
|
||||||
|
// Sort and de-dup them.
|
||||||
|
files := flatten(all)
|
||||||
|
for _, f := range files {
|
||||||
|
buf.WriteString(" \\\n ")
|
||||||
|
buf.WriteString(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(buf.String())
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func filesForPkg(pkg *build.Package, all map[string]struct{}) {
|
||||||
|
for _, file := range pkg.GoFiles {
|
||||||
|
if pkg.Dir != "." {
|
||||||
|
file = pkg.Dir + "/" + file
|
||||||
|
}
|
||||||
|
all[file] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func flatten(all map[string]struct{}) []string {
|
||||||
|
list := make([]string, 0, len(all))
|
||||||
|
for k := range all {
|
||||||
|
list = append(list, k)
|
||||||
|
}
|
||||||
|
sort.Strings(list)
|
||||||
|
return list
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadPackage(pkgName string) (*build.Package, error) {
|
||||||
|
debug("load", pkgName)
|
||||||
|
pkg, err := build.Import(pkgName, getwd(), 0)
|
||||||
|
if err != nil {
|
||||||
|
// We can ignore NoGoError. Anything else is real.
|
||||||
|
if _, ok := err.(*build.NoGoError); !ok {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pkg, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getwd() string {
|
||||||
|
pwd, err := os.Getwd()
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Sprintf("can't get working directory: %v", err))
|
||||||
|
}
|
||||||
|
return pwd
|
||||||
|
}
|
117
hack/make-rules/helpers/go2make/pkgwalk.go
Normal file
117
hack/make-rules/helpers/go2make/pkgwalk.go
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2017 The Kubernetes Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"go/build"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
"sort"
|
||||||
|
)
|
||||||
|
|
||||||
|
// VisitFunc is a function called by WalkPkg to examine a single package.
|
||||||
|
type VisitFunc func(importPath string, absPath string) error
|
||||||
|
|
||||||
|
// ErrSkipPkg can be returned by a VisitFunc to indicate that the package in
|
||||||
|
// question should not be walked any further.
|
||||||
|
var ErrSkipPkg = fmt.Errorf("package skipped")
|
||||||
|
|
||||||
|
// WalkPkg recursively visits all packages under pkgName. This is similar
|
||||||
|
// to filepath.Walk, except that it follows symlinks. A package is always
|
||||||
|
// visited before the children of that package. If visit returns ErrSkipPkg,
|
||||||
|
// pkgName will not be walked.
|
||||||
|
func WalkPkg(pkgName string, visit VisitFunc) error {
|
||||||
|
// Visit the package itself.
|
||||||
|
pkg, err := findPackage(pkgName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := visit(pkg.ImportPath, pkg.Dir); err == ErrSkipPkg {
|
||||||
|
return nil
|
||||||
|
} else if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read all of the child dirents and find sub-packages.
|
||||||
|
infos, err := readDirInfos(pkg.Dir)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, info := range infos {
|
||||||
|
if !info.IsDir() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
name := info.Name()
|
||||||
|
if name[0] == '_' || (len(name) > 1 && name[0] == '.') || name == "testdata" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// Don't use path.Join() because it drops leading `./` via path.Clean().
|
||||||
|
err := WalkPkg(pkgName+"/"+name, visit)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// findPackage finds a Go package.
|
||||||
|
func findPackage(pkgName string) (*build.Package, error) {
|
||||||
|
debug("find", pkgName)
|
||||||
|
pkg, err := build.Import(pkgName, getwd(), build.FindOnly)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return pkg, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// readDirInfos returns a list of os.FileInfo structures for the dirents under
|
||||||
|
// dirPath. The result list is sorted by name. This is very similar to
|
||||||
|
// ioutil.ReadDir, except that it follows symlinks.
|
||||||
|
func readDirInfos(dirPath string) ([]os.FileInfo, error) {
|
||||||
|
names, err := readDirNames(dirPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
sort.Strings(names)
|
||||||
|
|
||||||
|
infos := make([]os.FileInfo, 0, len(names))
|
||||||
|
for _, n := range names {
|
||||||
|
info, err := os.Stat(path.Join(dirPath, n))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
infos = append(infos, info)
|
||||||
|
}
|
||||||
|
return infos, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// readDirNames returns a list of all dirents in dirPath. The result list is
|
||||||
|
// not sorted or filtered.
|
||||||
|
func readDirNames(dirPath string) ([]string, error) {
|
||||||
|
d, err := os.Open(dirPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer d.Close()
|
||||||
|
|
||||||
|
names, err := d.Readdirnames(-1)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return names, nil
|
||||||
|
}
|
222
hack/make-rules/helpers/go2make/pkgwalk_test.go
Normal file
222
hack/make-rules/helpers/go2make/pkgwalk_test.go
Normal file
@ -0,0 +1,222 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2017 The Kubernetes Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"path"
|
||||||
|
"reflect"
|
||||||
|
"sort"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_WalkPkg(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
pkg string
|
||||||
|
fail bool
|
||||||
|
expected []string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
pkg: "./testdata/nonexistent-dir",
|
||||||
|
fail: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pkg: "./testdata/dir-without-gofiles",
|
||||||
|
expected: []string{"./testdata/dir-without-gofiles"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pkg: "./testdata/dir-with-gofiles",
|
||||||
|
expected: []string{"./testdata/dir-with-gofiles", "./testdata/dir-with-gofiles/subdir"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, tc := range testCases {
|
||||||
|
visited := []string{}
|
||||||
|
err := WalkPkg(tc.pkg, func(imp, abs string) error {
|
||||||
|
if _, base := path.Split(imp); base == "skipme" {
|
||||||
|
return ErrSkipPkg
|
||||||
|
}
|
||||||
|
visited = append(visited, imp)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil && tc.fail {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("[%d] unexpected error: %v", i, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if tc.fail {
|
||||||
|
t.Errorf("[%d] expected error", i)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(visited, tc.expected) {
|
||||||
|
t.Errorf("[%d] unexpected results: %v", i, visited)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func Test_findPackage(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
pkg string
|
||||||
|
fail bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
pkg: "./testdata/nonexistent-dir",
|
||||||
|
fail: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pkg: "./testdata/dir-without-gofiles",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
pkg: "./testdata/dir-with-gofiles",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, tc := range testCases {
|
||||||
|
_, err := findPackage(tc.pkg)
|
||||||
|
if err != nil && tc.fail {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("[%d] unexpected error: %v", i, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if tc.fail {
|
||||||
|
t.Errorf("[%d] expected error", i)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_readDirInfos(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
dir string
|
||||||
|
fail bool
|
||||||
|
expected map[string]bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
dir: "./testdata/nonexistent-dir",
|
||||||
|
fail: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dir: "./testdata/dir-without-gofiles",
|
||||||
|
expected: map[string]bool{"README": true},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dir: "./testdata/dir-with-gofiles",
|
||||||
|
expected: map[string]bool{
|
||||||
|
"README": true,
|
||||||
|
"foo.go": true,
|
||||||
|
"bar.go": true,
|
||||||
|
"subdir": true,
|
||||||
|
"testdata": true,
|
||||||
|
"_underscore": true,
|
||||||
|
".dot": true,
|
||||||
|
"skipme": true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, tc := range testCases {
|
||||||
|
infos, err := readDirInfos(tc.dir)
|
||||||
|
if err != nil && tc.fail {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("[%d] unexpected error: %v", i, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if tc.fail {
|
||||||
|
t.Errorf("[%d] expected error", i)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
result := make([]string, len(infos))
|
||||||
|
sorted := make([]string, len(infos))
|
||||||
|
for i, inf := range infos {
|
||||||
|
result[i] = inf.Name()
|
||||||
|
sorted[i] = inf.Name()
|
||||||
|
}
|
||||||
|
sort.Strings(sorted)
|
||||||
|
if !reflect.DeepEqual(result, sorted) {
|
||||||
|
t.Errorf("[%d] result was not sorted: %v", i, result)
|
||||||
|
}
|
||||||
|
for _, r := range result {
|
||||||
|
if !tc.expected[r] {
|
||||||
|
t.Errorf("[%d] got unexpected result: %s", i, r)
|
||||||
|
} else {
|
||||||
|
delete(tc.expected, r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for r := range tc.expected {
|
||||||
|
t.Errorf("[%d] missing expected result: %s", i, r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_readDirNames(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
dir string
|
||||||
|
fail bool
|
||||||
|
expected map[string]bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
dir: "./testdata/nonexistent-dir",
|
||||||
|
fail: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dir: "./testdata/dir-without-gofiles",
|
||||||
|
expected: map[string]bool{"README": true},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dir: "./testdata/dir-with-gofiles",
|
||||||
|
expected: map[string]bool{
|
||||||
|
"README": true,
|
||||||
|
"foo.go": true,
|
||||||
|
"bar.go": true,
|
||||||
|
"subdir": true,
|
||||||
|
"testdata": true,
|
||||||
|
"_underscore": true,
|
||||||
|
".dot": true,
|
||||||
|
"skipme": true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, tc := range testCases {
|
||||||
|
result, err := readDirNames(tc.dir)
|
||||||
|
if err != nil && tc.fail {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("[%d] unexpected error: %v", i, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if tc.fail {
|
||||||
|
t.Errorf("[%d] expected error", i)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for _, r := range result {
|
||||||
|
if !tc.expected[r] {
|
||||||
|
t.Errorf("[%d] got unexpected result: %s", i, r)
|
||||||
|
} else {
|
||||||
|
delete(tc.expected, r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for r := range tc.expected {
|
||||||
|
t.Errorf("[%d] missing expected result: %s", i, r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
1
hack/make-rules/helpers/go2make/testdata/dir-with-gofiles/.dot/README
vendored
Normal file
1
hack/make-rules/helpers/go2make/testdata/dir-with-gofiles/.dot/README
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
README
|
1
hack/make-rules/helpers/go2make/testdata/dir-with-gofiles/.dot/subsubdir/README
vendored
Normal file
1
hack/make-rules/helpers/go2make/testdata/dir-with-gofiles/.dot/subsubdir/README
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
README
|
1
hack/make-rules/helpers/go2make/testdata/dir-with-gofiles/README
vendored
Normal file
1
hack/make-rules/helpers/go2make/testdata/dir-with-gofiles/README
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
README
|
1
hack/make-rules/helpers/go2make/testdata/dir-with-gofiles/_underscore/README
vendored
Normal file
1
hack/make-rules/helpers/go2make/testdata/dir-with-gofiles/_underscore/README
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
README
|
1
hack/make-rules/helpers/go2make/testdata/dir-with-gofiles/_underscore/subsubdir/README
vendored
Normal file
1
hack/make-rules/helpers/go2make/testdata/dir-with-gofiles/_underscore/subsubdir/README
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
README
|
20
hack/make-rules/helpers/go2make/testdata/dir-with-gofiles/bar.go
vendored
Normal file
20
hack/make-rules/helpers/go2make/testdata/dir-with-gofiles/bar.go
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2017 The Kubernetes Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package gofiles
|
||||||
|
|
||||||
|
func bar() {
|
||||||
|
}
|
20
hack/make-rules/helpers/go2make/testdata/dir-with-gofiles/foo.go
vendored
Normal file
20
hack/make-rules/helpers/go2make/testdata/dir-with-gofiles/foo.go
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2017 The Kubernetes Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package gofiles
|
||||||
|
|
||||||
|
func foo() {
|
||||||
|
}
|
1
hack/make-rules/helpers/go2make/testdata/dir-with-gofiles/skipme/README
vendored
Normal file
1
hack/make-rules/helpers/go2make/testdata/dir-with-gofiles/skipme/README
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
README
|
1
hack/make-rules/helpers/go2make/testdata/dir-with-gofiles/skipme/subsubdir/README
vendored
Normal file
1
hack/make-rules/helpers/go2make/testdata/dir-with-gofiles/skipme/subsubdir/README
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
README
|
1
hack/make-rules/helpers/go2make/testdata/dir-with-gofiles/subdir/README
vendored
Normal file
1
hack/make-rules/helpers/go2make/testdata/dir-with-gofiles/subdir/README
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
README
|
1
hack/make-rules/helpers/go2make/testdata/dir-with-gofiles/testdata/README
vendored
Normal file
1
hack/make-rules/helpers/go2make/testdata/dir-with-gofiles/testdata/README
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
README
|
1
hack/make-rules/helpers/go2make/testdata/dir-with-gofiles/testdata/subsubdir/README
vendored
Normal file
1
hack/make-rules/helpers/go2make/testdata/dir-with-gofiles/testdata/subsubdir/README
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
README
|
1
hack/make-rules/helpers/go2make/testdata/dir-without-gofiles/README
vendored
Normal file
1
hack/make-rules/helpers/go2make/testdata/dir-without-gofiles/README
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
README
|
303
hack/verify-generated-files-remake.sh
Normal file → Executable file
303
hack/verify-generated-files-remake.sh
Normal file → Executable file
@ -21,10 +21,303 @@ set -o pipefail
|
|||||||
KUBE_ROOT=$(dirname "${BASH_SOURCE}")/..
|
KUBE_ROOT=$(dirname "${BASH_SOURCE}")/..
|
||||||
source "${KUBE_ROOT}/hack/lib/init.sh"
|
source "${KUBE_ROOT}/hack/lib/init.sh"
|
||||||
|
|
||||||
make generated_files
|
# $1 = filename pattern as in "zz_generated.$1.go"
|
||||||
X=$(make generated_files DBG_CODEGEN=1)
|
function find_genfiles() {
|
||||||
if [[ -n "${X}" ]]; then
|
find . \
|
||||||
echo "Back-to-back 'make' runs are not clean for codegen"
|
\( \
|
||||||
echo "${X}"
|
-not \( \
|
||||||
|
\( \
|
||||||
|
-path ./_\* -o \
|
||||||
|
-path ./.\* \
|
||||||
|
\) -prune \
|
||||||
|
\) \
|
||||||
|
\) -name "zz_generated.$1.go"
|
||||||
|
}
|
||||||
|
|
||||||
|
# $1 = filename pattern as in "zz_generated.$1.go"
|
||||||
|
# $2 timestamp file
|
||||||
|
function newer() {
|
||||||
|
find_genfiles "$1" | while read F; do
|
||||||
|
if [[ "${F}" -nt "$2" ]]; then
|
||||||
|
echo "${F}"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# $1 = filename pattern as in "zz_generated.$1.go"
|
||||||
|
# $2 timestamp file
|
||||||
|
function older() {
|
||||||
|
find_genfiles "$1" | while read F; do
|
||||||
|
if [[ "$2" -nt "${F}" ]]; then
|
||||||
|
echo "${F}"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
function assert_clean() {
|
||||||
|
make generated_files >/dev/null
|
||||||
|
touch "${STAMP}"
|
||||||
|
make generated_files >/dev/null
|
||||||
|
X=($(newer deepcopy "${STAMP}"))
|
||||||
|
if [[ "${#X[*]}" != 0 ]]; then
|
||||||
|
echo "Generated files changed on back-to-back 'make' runs:"
|
||||||
|
echo " ${X[@]:-(none)}"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
STAMP=/tmp/stamp.$RANDOM
|
||||||
|
|
||||||
|
#
|
||||||
|
# Test when we touch a file in a package that needs codegen.
|
||||||
|
#
|
||||||
|
|
||||||
|
assert_clean
|
||||||
|
|
||||||
|
DIR=staging/src/k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1
|
||||||
|
touch "$DIR/types.go"
|
||||||
|
touch "${STAMP}"
|
||||||
|
make generated_files >/dev/null
|
||||||
|
X=($(newer deepcopy "${STAMP}"))
|
||||||
|
if [[ "${#X[*]}" != 1 || ! ( "${X[0]}" =~ "${DIR}/zz_generated.deepcopy.go" ) ]]; then
|
||||||
|
echo "Wrong generated deepcopy files changed after touching src file:"
|
||||||
|
echo " ${X[@]:-(none)}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
X=($(newer defaults "${STAMP}"))
|
||||||
|
if [[ "${#X[*]}" != 1 || ! ( "${X[0]}" =~ "${DIR}/zz_generated.defaults.go" ) ]]; then
|
||||||
|
echo "Wrong generated defaults files changed after touching src file:"
|
||||||
|
echo " ${X[@]:-(none)}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
X=($(newer conversion "${STAMP}"))
|
||||||
|
if [[ "${#X[*]}" != 1 || ! ( "${X[0]}" =~ "${DIR}/zz_generated.conversion.go" ) ]]; then
|
||||||
|
echo "Wrong generated conversion files changed after touching src file:"
|
||||||
|
echo " ${X[@]:-(none)}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
#
|
||||||
|
# Test when the codegen tool itself changes: deepcopy
|
||||||
|
#
|
||||||
|
|
||||||
|
assert_clean
|
||||||
|
|
||||||
|
touch staging/src/k8s.io/code-generator/cmd/deepcopy-gen/main.go
|
||||||
|
touch "${STAMP}"
|
||||||
|
make generated_files >/dev/null
|
||||||
|
X=($(older deepcopy "${STAMP}"))
|
||||||
|
if [[ "${#X[*]}" != 0 ]]; then
|
||||||
|
echo "Generated deepcopy files did not change after touching code-generator file:"
|
||||||
|
echo " ${X[@]:-(none)}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
assert_clean
|
||||||
|
|
||||||
|
touch staging/src/k8s.io/code-generator/cmd/deepcopy-gen/
|
||||||
|
touch "${STAMP}"
|
||||||
|
make generated_files >/dev/null
|
||||||
|
X=($(older deepcopy "${STAMP}"))
|
||||||
|
if [[ "${#X[*]}" != 0 ]]; then
|
||||||
|
echo "Generated deepcopy files did not change after touching code-generator dir:"
|
||||||
|
echo " ${X[@]:-(none)}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
assert_clean
|
||||||
|
|
||||||
|
touch vendor/k8s.io/gengo/examples/deepcopy-gen/generators/deepcopy.go
|
||||||
|
touch "${STAMP}"
|
||||||
|
make generated_files >/dev/null
|
||||||
|
X=($(older deepcopy "${STAMP}"))
|
||||||
|
if [[ "${#X[*]}" != 0 ]]; then
|
||||||
|
echo "Generated deepcopy files did not change after touching code-generator dep file:"
|
||||||
|
echo " ${X[@]:-(none)}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
assert_clean
|
||||||
|
|
||||||
|
touch vendor/k8s.io/gengo/examples/deepcopy-gen/generators/
|
||||||
|
touch "${STAMP}"
|
||||||
|
make generated_files >/dev/null
|
||||||
|
X=($(older deepcopy "${STAMP}"))
|
||||||
|
if [[ "${#X[*]}" != 0 ]]; then
|
||||||
|
echo "Generated deepcopy files did not change after touching code-generator dep dir:"
|
||||||
|
echo " ${X[@]:-(none)}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
#
|
||||||
|
# Test when the codegen tool itself changes: defaults
|
||||||
|
#
|
||||||
|
|
||||||
|
assert_clean
|
||||||
|
|
||||||
|
touch staging/src/k8s.io/code-generator/cmd/defaulter-gen/main.go
|
||||||
|
touch "${STAMP}"
|
||||||
|
make generated_files >/dev/null
|
||||||
|
X=($(older defaults "${STAMP}"))
|
||||||
|
if [[ "${#X[*]}" != 0 ]]; then
|
||||||
|
echo "Generated defaults files did not change after touching code-generator file:"
|
||||||
|
echo " ${X[@]:-(none)}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
assert_clean
|
||||||
|
|
||||||
|
touch staging/src/k8s.io/code-generator/cmd/defaulter-gen/
|
||||||
|
touch "${STAMP}"
|
||||||
|
make generated_files >/dev/null
|
||||||
|
X=($(older defaults "${STAMP}"))
|
||||||
|
if [[ "${#X[*]}" != 0 ]]; then
|
||||||
|
echo "Generated defaults files did not change after touching code-generator dir:"
|
||||||
|
echo " ${X[@]:-(none)}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
assert_clean
|
||||||
|
|
||||||
|
touch vendor/k8s.io/gengo/examples/defaulter-gen/generators/defaulter.go
|
||||||
|
touch "${STAMP}"
|
||||||
|
make generated_files >/dev/null
|
||||||
|
X=($(older defaults "${STAMP}"))
|
||||||
|
if [[ "${#X[*]}" != 0 ]]; then
|
||||||
|
echo "Generated defaults files did not change after touching code-generator dep file:"
|
||||||
|
echo " ${X[@]:-(none)}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
assert_clean
|
||||||
|
|
||||||
|
touch vendor/k8s.io/gengo/examples/defaulter-gen/generators/
|
||||||
|
touch "${STAMP}"
|
||||||
|
make generated_files >/dev/null
|
||||||
|
X=($(older defaults "${STAMP}"))
|
||||||
|
if [[ "${#X[*]}" != 0 ]]; then
|
||||||
|
echo "Generated defaults files did not change after touching code-generator dep dir:"
|
||||||
|
echo " ${X[@]:-(none)}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
#
|
||||||
|
# Test when the codegen tool itself changes: conversion
|
||||||
|
#
|
||||||
|
|
||||||
|
assert_clean
|
||||||
|
|
||||||
|
touch staging/src/k8s.io/code-generator/cmd/conversion-gen/main.go
|
||||||
|
touch "${STAMP}"
|
||||||
|
make generated_files >/dev/null
|
||||||
|
X=($(older conversion "${STAMP}"))
|
||||||
|
if [[ "${#X[*]}" != 0 ]]; then
|
||||||
|
echo "Generated conversion files did not change after touching code-generator file:"
|
||||||
|
echo " ${X[@]:-(none)}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
assert_clean
|
||||||
|
|
||||||
|
touch staging/src/k8s.io/code-generator/cmd/conversion-gen/
|
||||||
|
touch "${STAMP}"
|
||||||
|
make generated_files >/dev/null
|
||||||
|
X=($(older conversion "${STAMP}"))
|
||||||
|
if [[ "${#X[*]}" != 0 ]]; then
|
||||||
|
echo "Generated conversion files did not change after touching code-generator dir:"
|
||||||
|
echo " ${X[@]:-(none)}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
assert_clean
|
||||||
|
|
||||||
|
touch vendor/k8s.io/code-generator/cmd/conversion-gen/generators/conversion.go
|
||||||
|
touch "${STAMP}"
|
||||||
|
make generated_files >/dev/null
|
||||||
|
X=($(older conversion "${STAMP}"))
|
||||||
|
if [[ "${#X[*]}" != 0 ]]; then
|
||||||
|
echo "Generated conversion files did not change after touching code-generator dep file:"
|
||||||
|
echo " ${X[@]:-(none)}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
assert_clean
|
||||||
|
|
||||||
|
touch vendor/k8s.io/code-generator/cmd/conversion-gen/generators/
|
||||||
|
touch "${STAMP}"
|
||||||
|
make generated_files >/dev/null
|
||||||
|
X=($(older conversion "${STAMP}"))
|
||||||
|
if [[ "${#X[*]}" != 0 ]]; then
|
||||||
|
echo "Generated conversion files did not change after touching code-generator dep dir:"
|
||||||
|
echo " ${X[@]:-(none)}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
#
|
||||||
|
# Test when we touch a file in a package that needs codegen.
|
||||||
|
#
|
||||||
|
|
||||||
|
assert_clean
|
||||||
|
|
||||||
|
touch "staging/src/k8s.io/api/core/v1/types.go"
|
||||||
|
touch "${STAMP}"
|
||||||
|
make generated_files >/dev/null
|
||||||
|
X=($(newer openapi "${STAMP}"))
|
||||||
|
if [[ "${#X[*]}" != 1 || ! ( "${X[0]}" =~ "pkg/generated/openapi/zz_generated.openapi.go" ) ]]; then
|
||||||
|
echo "Wrong generated openapi files changed after touching src file:"
|
||||||
|
echo "${X[@]:-(none)}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
#
|
||||||
|
# Test when the codegen tool itself changes: openapi
|
||||||
|
#
|
||||||
|
|
||||||
|
assert_clean
|
||||||
|
|
||||||
|
touch staging/src/k8s.io/code-generator/cmd/openapi-gen/main.go
|
||||||
|
touch "${STAMP}"
|
||||||
|
make generated_files >/dev/null
|
||||||
|
X=($(older openapi "${STAMP}"))
|
||||||
|
if [[ "${#X[*]}" != 0 ]]; then
|
||||||
|
echo "Generated openapi files did not change after touching code-generator file:"
|
||||||
|
echo " ${X[@]:-(none)}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
assert_clean
|
||||||
|
|
||||||
|
touch staging/src/k8s.io/code-generator/cmd/openapi-gen/
|
||||||
|
touch "${STAMP}"
|
||||||
|
make generated_files >/dev/null
|
||||||
|
X=($(older openapi "${STAMP}"))
|
||||||
|
if [[ "${#X[*]}" != 0 ]]; then
|
||||||
|
echo "Generated openapi files did not change after touching code-generator dir:"
|
||||||
|
echo " ${X[@]:-(none)}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
assert_clean
|
||||||
|
|
||||||
|
touch vendor/k8s.io/kube-openapi/pkg/generators/openapi.go
|
||||||
|
touch "${STAMP}"
|
||||||
|
make generated_files >/dev/null
|
||||||
|
X=($(older openapi "${STAMP}"))
|
||||||
|
if [[ "${#X[*]}" != 0 ]]; then
|
||||||
|
echo "Generated openapi files did not change after touching code-generator dep file:"
|
||||||
|
echo " ${X[@]:-(none)}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
assert_clean
|
||||||
|
|
||||||
|
touch vendor/k8s.io/kube-openapi/pkg/generators
|
||||||
|
touch "${STAMP}"
|
||||||
|
make generated_files >/dev/null
|
||||||
|
X=($(older openapi "${STAMP}"))
|
||||||
|
if [[ "${#X[*]}" != 0 ]]; then
|
||||||
|
echo "Generated openapi files did not change after touching code-generator dep dir:"
|
||||||
|
echo " ${X[@]:-(none)}"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
Loading…
Reference in New Issue
Block a user