1# Copyright 2018 The Prometheus Authors 2# Licensed under the Apache License, Version 2.0 (the "License"); 3# you may not use this file except in compliance with the License. 4# You may obtain a copy of the License at 5# 6# http://www.apache.org/licenses/LICENSE-2.0 7# 8# Unless required by applicable law or agreed to in writing, software 9# distributed under the License is distributed on an "AS IS" BASIS, 10# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11# See the License for the specific language governing permissions and 12# limitations under the License. 13 14 15# A common Makefile that includes rules to be reused in different prometheus projects. 16# !!! Open PRs only against the prometheus/prometheus/Makefile.common repository! 17 18# Example usage : 19# Create the main Makefile in the root project directory. 20# include Makefile.common 21# customTarget: 22# @echo ">> Running customTarget" 23# 24 25# Ensure GOBIN is not set during build so that promu is installed to the correct path 26unexport GOBIN 27 28GO ?= go 29GOFMT ?= $(GO)fmt 30FIRST_GOPATH := $(firstword $(subst :, ,$(shell $(GO) env GOPATH))) 31GOOPTS ?= 32GOHOSTOS ?= $(shell $(GO) env GOHOSTOS) 33GOHOSTARCH ?= $(shell $(GO) env GOHOSTARCH) 34 35GO_VERSION ?= $(shell $(GO) version) 36GO_VERSION_NUMBER ?= $(word 3, $(GO_VERSION)) 37PRE_GO_111 ?= $(shell echo $(GO_VERSION_NUMBER) | grep -E 'go1\.(10|[0-9])\.') 38 39GOVENDOR := 40GO111MODULE := 41ifeq (, $(PRE_GO_111)) 42 ifneq (,$(wildcard go.mod)) 43 # Enforce Go modules support just in case the directory is inside GOPATH (and for Travis CI). 44 GO111MODULE := on 45 46 ifneq (,$(wildcard vendor)) 47 # Always use the local vendor/ directory to satisfy the dependencies. 48 GOOPTS := $(GOOPTS) -mod=vendor 49 endif 50 endif 51else 52 ifneq (,$(wildcard go.mod)) 53 ifneq (,$(wildcard vendor)) 54$(warning This repository requires Go >= 1.11 because of Go modules) 55$(warning Some recipes may not work as expected as the current Go runtime is '$(GO_VERSION_NUMBER)') 56 endif 57 else 58 # This repository isn't using Go modules (yet). 59 GOVENDOR := $(FIRST_GOPATH)/bin/govendor 60 endif 61endif 62PROMU := $(FIRST_GOPATH)/bin/promu 63pkgs = ./... 64 65ifeq (arm, $(GOHOSTARCH)) 66 GOHOSTARM ?= $(shell GOARM= $(GO) env GOARM) 67 GO_BUILD_PLATFORM ?= $(GOHOSTOS)-$(GOHOSTARCH)v$(GOHOSTARM) 68else 69 GO_BUILD_PLATFORM ?= $(GOHOSTOS)-$(GOHOSTARCH) 70endif 71 72PROMU_VERSION ?= 0.3.0 73PROMU_URL := https://github.com/prometheus/promu/releases/download/v$(PROMU_VERSION)/promu-$(PROMU_VERSION).$(GO_BUILD_PLATFORM).tar.gz 74 75STATICCHECK := 76# staticcheck only supports linux, freebsd, darwin and windows platforms on i386/amd64 77# windows isn't included here because of the path separator being different. 78ifeq ($(GOHOSTOS),$(filter $(GOHOSTOS),linux freebsd darwin)) 79 ifeq ($(GOHOSTARCH),$(filter $(GOHOSTARCH),amd64 i386)) 80 STATICCHECK := $(FIRST_GOPATH)/bin/staticcheck 81 STATICCHECK_VERSION ?= 2019.1 82 STATICCHECK_URL := https://github.com/dominikh/go-tools/releases/download/$(STATICCHECK_VERSION)/staticcheck_$(GOHOSTOS)_$(GOHOSTARCH) 83 endif 84endif 85 86PREFIX ?= $(shell pwd) 87BIN_DIR ?= $(shell pwd) 88DOCKER_IMAGE_TAG ?= $(subst /,-,$(shell git rev-parse --abbrev-ref HEAD)) 89DOCKER_REPO ?= prom 90 91DOCKER_ARCHS ?= amd64 92 93BUILD_DOCKER_ARCHS = $(addprefix common-docker-,$(DOCKER_ARCHS)) 94PUBLISH_DOCKER_ARCHS = $(addprefix common-docker-publish-,$(DOCKER_ARCHS)) 95TAG_DOCKER_ARCHS = $(addprefix common-docker-tag-latest-,$(DOCKER_ARCHS)) 96 97ifeq ($(GOHOSTARCH),amd64) 98 ifeq ($(GOHOSTOS),$(filter $(GOHOSTOS),linux freebsd darwin windows)) 99 # Only supported on amd64 100 test-flags := -race 101 endif 102endif 103 104# This rule is used to forward a target like "build" to "common-build". This 105# allows a new "build" target to be defined in a Makefile which includes this 106# one and override "common-build" without override warnings. 107%: common-% ; 108 109.PHONY: common-all 110common-all: precheck style check_license staticcheck unused build test 111 112.PHONY: common-style 113common-style: 114 @echo ">> checking code style" 115 @fmtRes=$$($(GOFMT) -d $$(find . -path ./vendor -prune -o -name '*.go' -print)); \ 116 if [ -n "$${fmtRes}" ]; then \ 117 echo "gofmt checking failed!"; echo "$${fmtRes}"; echo; \ 118 echo "Please ensure you are using $$($(GO) version) for formatting code."; \ 119 exit 1; \ 120 fi 121 122.PHONY: common-check_license 123common-check_license: 124 @echo ">> checking license header" 125 @licRes=$$(for file in $$(find . -type f -iname '*.go' ! -path './vendor/*') ; do \ 126 awk 'NR<=3' $$file | grep -Eq "(Copyright|generated|GENERATED)" || echo $$file; \ 127 done); \ 128 if [ -n "$${licRes}" ]; then \ 129 echo "license header checking failed:"; echo "$${licRes}"; \ 130 exit 1; \ 131 fi 132 133.PHONY: common-deps 134common-deps: 135 @echo ">> getting dependencies" 136ifdef GO111MODULE 137 GO111MODULE=$(GO111MODULE) $(GO) mod download 138else 139 $(GO) get $(GOOPTS) -t ./... 140endif 141 142.PHONY: common-test-short 143common-test-short: 144 @echo ">> running short tests" 145 GO111MODULE=$(GO111MODULE) $(GO) test -short $(GOOPTS) $(pkgs) 146 147.PHONY: common-test 148common-test: 149 @echo ">> running all tests" 150 GO111MODULE=$(GO111MODULE) $(GO) test $(test-flags) $(GOOPTS) $(pkgs) 151 152.PHONY: common-format 153common-format: 154 @echo ">> formatting code" 155 GO111MODULE=$(GO111MODULE) $(GO) fmt $(pkgs) 156 157.PHONY: common-vet 158common-vet: 159 @echo ">> vetting code" 160 GO111MODULE=$(GO111MODULE) $(GO) vet $(GOOPTS) $(pkgs) 161 162.PHONY: common-staticcheck 163common-staticcheck: $(STATICCHECK) 164ifdef STATICCHECK 165 @echo ">> running staticcheck" 166 chmod +x $(STATICCHECK) 167ifdef GO111MODULE 168# 'go list' needs to be executed before staticcheck to prepopulate the modules cache. 169# Otherwise staticcheck might fail randomly for some reason not yet explained. 170 GO111MODULE=$(GO111MODULE) $(GO) list -e -compiled -test=true -export=false -deps=true -find=false -tags= -- ./... > /dev/null 171 GO111MODULE=$(GO111MODULE) $(STATICCHECK) -ignore "$(STATICCHECK_IGNORE)" $(pkgs) 172else 173 $(STATICCHECK) -ignore "$(STATICCHECK_IGNORE)" $(pkgs) 174endif 175endif 176 177.PHONY: common-unused 178common-unused: $(GOVENDOR) 179ifdef GOVENDOR 180 @echo ">> running check for unused packages" 181 @$(GOVENDOR) list +unused | grep . && exit 1 || echo 'No unused packages' 182else 183ifdef GO111MODULE 184 @echo ">> running check for unused/missing packages in go.mod" 185 GO111MODULE=$(GO111MODULE) $(GO) mod tidy 186ifeq (,$(wildcard vendor)) 187 @git diff --exit-code -- go.sum go.mod 188else 189 @echo ">> running check for unused packages in vendor/" 190 GO111MODULE=$(GO111MODULE) $(GO) mod vendor 191 @git diff --exit-code -- go.sum go.mod vendor/ 192endif 193endif 194endif 195 196.PHONY: common-build 197common-build: promu 198 @echo ">> building binaries" 199 GO111MODULE=$(GO111MODULE) $(PROMU) build --prefix $(PREFIX) 200 201.PHONY: common-tarball 202common-tarball: promu 203 @echo ">> building release tarball" 204 $(PROMU) tarball --prefix $(PREFIX) $(BIN_DIR) 205 206.PHONY: common-docker $(BUILD_DOCKER_ARCHS) 207common-docker: $(BUILD_DOCKER_ARCHS) 208$(BUILD_DOCKER_ARCHS): common-docker-%: 209 docker build -t "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(DOCKER_IMAGE_TAG)" \ 210 --build-arg ARCH="$*" \ 211 --build-arg OS="linux" \ 212 . 213 214.PHONY: common-docker-publish $(PUBLISH_DOCKER_ARCHS) 215common-docker-publish: $(PUBLISH_DOCKER_ARCHS) 216$(PUBLISH_DOCKER_ARCHS): common-docker-publish-%: 217 docker push "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(DOCKER_IMAGE_TAG)" 218 219.PHONY: common-docker-tag-latest $(TAG_DOCKER_ARCHS) 220common-docker-tag-latest: $(TAG_DOCKER_ARCHS) 221$(TAG_DOCKER_ARCHS): common-docker-tag-latest-%: 222 docker tag "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(DOCKER_IMAGE_TAG)" "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:latest" 223 224.PHONY: common-docker-manifest 225common-docker-manifest: 226 DOCKER_CLI_EXPERIMENTAL=enabled docker manifest create -a "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):$(DOCKER_IMAGE_TAG)" $(foreach ARCH,$(DOCKER_ARCHS),$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$(ARCH):$(DOCKER_IMAGE_TAG)) 227 DOCKER_CLI_EXPERIMENTAL=enabled docker manifest push "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):$(DOCKER_IMAGE_TAG)" 228 229.PHONY: promu 230promu: $(PROMU) 231 232$(PROMU): 233 $(eval PROMU_TMP := $(shell mktemp -d)) 234 curl -s -L $(PROMU_URL) | tar -xvzf - -C $(PROMU_TMP) 235 mkdir -p $(FIRST_GOPATH)/bin 236 cp $(PROMU_TMP)/promu-$(PROMU_VERSION).$(GO_BUILD_PLATFORM)/promu $(FIRST_GOPATH)/bin/promu 237 rm -r $(PROMU_TMP) 238 239.PHONY: proto 240proto: 241 @echo ">> generating code from proto files" 242 @./scripts/genproto.sh 243 244ifdef STATICCHECK 245$(STATICCHECK): 246 mkdir -p $(FIRST_GOPATH)/bin 247 curl -s -L $(STATICCHECK_URL) > $(STATICCHECK) 248endif 249 250ifdef GOVENDOR 251.PHONY: $(GOVENDOR) 252$(GOVENDOR): 253 GOOS= GOARCH= $(GO) get -u github.com/kardianos/govendor 254endif 255 256.PHONY: precheck 257precheck:: 258 259define PRECHECK_COMMAND_template = 260precheck:: $(1)_precheck 261 262PRECHECK_COMMAND_$(1) ?= $(1) $$(strip $$(PRECHECK_OPTIONS_$(1))) 263.PHONY: $(1)_precheck 264$(1)_precheck: 265 @if ! $$(PRECHECK_COMMAND_$(1)) 1>/dev/null 2>&1; then \ 266 echo "Execution of '$$(PRECHECK_COMMAND_$(1))' command failed. Is $(1) installed?"; \ 267 exit 1; \ 268 fi 269endef 270