From ca6fc3a68ba5a39365d39ef96cf04843a6174ffd Mon Sep 17 00:00:00 2001 From: Clayton Coleman Date: Sat, 24 Sep 2016 17:25:21 -0400 Subject: [PATCH] Update makefile to generate defaulters --- Makefile.generated_files | 144 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 142 insertions(+), 2 deletions(-) diff --git a/Makefile.generated_files b/Makefile.generated_files index a09e428fbffb6..8861c1a2dc322 100644 --- a/Makefile.generated_files +++ b/Makefile.generated_files @@ -35,7 +35,7 @@ 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_conversion gen_openapi +generated_files: gen_deepcopy gen_defaulter gen_conversion gen_openapi # Code-generation logic. # @@ -286,6 +286,146 @@ $(DEEPCOPY_GEN): hack/make-rules/build.sh cmd/libs/go2idl/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 \ + | sort -u \ +) + +DEFAULTER_FILES := $(addsuffix /$(DEFAULTER_FILENAME), $(DEFAULTER_DIRS)) + +# 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_FILES) + if [[ -f $(META_DIR)/$(DEFAULTER_GEN).todo ]]; then \ + ./hack/run-in-gopath.sh $(DEFAULTER_GEN) \ + --v $(KUBE_VERBOSE) \ + --logtostderr \ + -i $$(cat $(META_DIR)/$(DEFAULTER_GEN).todo | paste -sd, -) \ + --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. +# +# 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), $(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 +# it up and trigger the batch from the 'generated_files' target. +$(DEFAULTER_FILES): $(DEFAULTER_GEN) + mkdir -p $$(dirname $(META_DIR)/$(DEFAULTER_GEN)) + 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): "; \ + DIRECT=$$(go list -f '{{.Dir}} {{.Dir}}/*.go' \ + ./cmd/libs/go2idl/defaulter-gen); \ + INDIRECT=$$(go list \ + -f '{{range .Deps}}{{.}}{{"\n"}}{{end}}' \ + ./cmd/libs/go2idl/defaulter-gen \ + | grep --color=never "^$(PRJ_SRC_PATH)" \ + | sed 's|^$(PRJ_SRC_PATH)|./|' \ + | xargs go list -f '{{.Dir}} {{.Dir}}/*.go'); \ + echo $$DIRECT $$INDIRECT \ + | sed 's/ / \\=,/g' \ + | tr '=,' '\n\t'; \ + ) | sed "s|$$(pwd -P)/||" > $@.tmp; \ + cmp -s $@.tmp $@ || cat $@.tmp > $@ && rm -f $@.tmp + +# 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 +# the $(DEFAULTER_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. +$(DEFAULTER_GEN): + hack/make-rules/build.sh cmd/libs/go2idl/defaulter-gen + touch $@ + # # Open-api generation # @@ -427,7 +567,7 @@ gen_conversion: $(CONVERSION_FILES) if [[ -f $(META_DIR)/$(CONVERSION_GEN).todo ]]; then \ ./hack/run-in-gopath.sh $(CONVERSION_GEN) \ --v $(KUBE_VERBOSE) \ - --logtostderr \ + --logtostderr \ -i $$(cat $(META_DIR)/$(CONVERSION_GEN).todo | paste -sd, -) \ -O $(CONVERSION_BASENAME); \ fi