Skip to content

Commit 0bd3773

Browse files
dioelliotmjackson
andauthored
Proposal: Improve Makefile (#735)
Signed-off-by: Dhi Aurrahman <[email protected]> Co-authored-by: Elliot Jackson <[email protected]>
1 parent 8ed4f9c commit 0bd3773

File tree

8 files changed

+242
-0
lines changed

8 files changed

+242
-0
lines changed

.github/workflows/commit.yaml

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
name: "build"
2+
3+
on:
4+
push: # We run tests on non-tagged pushes to main.
5+
branches:
6+
- main
7+
paths-ignore:
8+
- '**/*.md'
9+
10+
pull_request: # We also run tests on pull requests targeted at the main branch.
11+
branches:
12+
- main
13+
paths-ignore:
14+
- '**/*.md'
15+
16+
defaults:
17+
run: # use bash as the default shell.
18+
shell: bash
19+
20+
jobs:
21+
test:
22+
name: "Run tests"
23+
runs-on: ubuntu-20.04
24+
steps:
25+
- name: Cancel when duplicated
26+
uses: styfle/[email protected]
27+
with:
28+
access_token: ${{ secrets.GITHUB_TOKEN }}
29+
30+
- name: "Checkout"
31+
uses: actions/checkout@v3
32+
33+
- uses: actions/setup-go@v3
34+
with:
35+
go-version: "1.19.3"
36+
cache: true
37+
38+
- uses: actions/setup-python@v4
39+
with:
40+
python-version: "3.10"
41+
cache: "pip"
42+
43+
- name: Download cache for bazel
44+
uses: actions/cache@v3
45+
with:
46+
path: "~/.cache/bazel"
47+
key: test-${{ runner.os }}-bazel-cache
48+
49+
- name: "Install python requirements"
50+
run: "pip3 install -r requirements.txt --no-deps"
51+
52+
- name: "Generate *.pb.go and build the plugin binary"
53+
run: make -f Next.mk clean build # we do "clean build" here, hence validate.pb.go is regenerated.
54+
55+
- name: "Verify clean check-in"
56+
run: make -f Next.mk check # we do verification after validate.pb.go is regenerated.
57+
58+
- name: "Run tests"
59+
run: make -f Next.mk test
60+
61+
- name: "Run sanity checks"
62+
run: make -f Next.mk sanity

.gitignore

+13
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,16 @@ __pycache__/
4747
.settings
4848
.idea/
4949
.ijwb/
50+
51+
# Local cache directory.
52+
.cache
53+
54+
# Local build directory.
55+
/build
56+
57+
# Generated test cases Go files.
58+
/tests/harness/**/*.pb.go
59+
/tests/harness/**/*.pb.validate.go
60+
61+
# Harness test binary.
62+
/tests/harness/**/*-harness

BUILD renamed to BUILD.bazel

File renamed without changes.

Next.mk

+111
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
# Licensed under the Apache License, Version 2.0 (the "License")
2+
3+
# Plugin name.
4+
name := protoc-gen-validate
5+
6+
# Root dir returns absolute path of current directory. It has a trailing "/".
7+
root_dir := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
8+
9+
# Local cache directory.
10+
cache_dir := $(root_dir).cache
11+
12+
# Directory of Go tools.
13+
go_tools_dir := $(cache_dir)/tools/go
14+
15+
# Directory of prepackaged tools (e.g. protoc).
16+
prepackaged_tools_dir := $(cache_dir)/tools/prepackaged
17+
18+
# Currently we resolve Go using `which`. But more sophisticated approach is to use infer GOROOT.
19+
go := $(shell which go)
20+
goarch := $(shell $(go) env GOARCH)
21+
goexe := $(shell $(go) env GOEXE)
22+
goos := $(shell $(go) env GOOS)
23+
24+
# The current binary location for the current runtime (goos, goarch). We install our plugin here.
25+
current_binary_path := build/$(name)_$(goos)_$(goarch)
26+
current_binary := $(current_binary_path)/$(name)$(goexe)
27+
28+
# This makes sure protoc can access the installed plugins.
29+
export PATH := $(root_dir)$(current_binary_path):$(go_tools_dir)/bin:$(prepackaged_tools_dir)/bin:$(PATH)
30+
31+
# The main generated file.
32+
validate_pb_go := validate/validate.pb.go
33+
34+
# List of harness test cases.
35+
tests_harness_cases := \
36+
/harness \
37+
/harness/cases \
38+
/harness/cases/other_package \
39+
/harness/cases/yet_another_package
40+
41+
# Include versions of tools we build on-demand
42+
include Tools.mk
43+
# This provides the "help" target.
44+
include tools/build/Help.mk
45+
# This sets some required environment variables.
46+
include tools/build/Env.mk
47+
48+
# Path to the installed protocol buffer compiler.
49+
protoc := $(prepackaged_tools_dir)/bin/protoc
50+
51+
# Go based tools.
52+
bazel := $(go_tools_dir)/bin/bazelisk
53+
protoc-gen-go := $(go_tools_dir)/bin/protoc-gen-go
54+
55+
test: $(bazel) $(tests_harness_cases) ## Run tests
56+
@$(bazel) test //tests/... --test_output=errors
57+
58+
build: $(current_binary) ## Build the plugin
59+
60+
clean: ## Clean all build and test artifacts
61+
@rm -f $(validate_pb_go)
62+
@rm -f $(current_binary)
63+
64+
check: ## Verify contents of last commit
65+
@# Make sure the check-in is clean
66+
@if [ ! -z "`git status -s`" ]; then \
67+
echo "The following differences will fail CI until committed:"; \
68+
git diff --exit-code; \
69+
fi
70+
71+
# This provides shortcut to various bazel related targets.
72+
sanity: bazel-build bazel-build-tests-generation bazel-test-example-workspace
73+
74+
bazel-build: $(bazel) ## Build the plugin using bazel
75+
@$(bazel) build //:$(name)
76+
@mkdir -p $(current_binary_path)
77+
@cp -f bazel-bin/$(name)_/$(name)$(goexe) $(current_binary)
78+
79+
bazel-build-tests-generation: $(bazel) ## Build tests generation using bazel
80+
@$(bazel) build //tests/generation/...
81+
82+
bazel-test-example-workspace: $(bazel) ## Test example workspace using bazel
83+
@cd example-workspace && bazel test //... --test_output=errors
84+
85+
# Generate validate/validate.pb.go from validate/validate.proto.
86+
$(validate_pb_go): $(protoc) $(protoc-gen-go) validate/validate.proto
87+
@$(protoc) -I . --go_opt=paths=source_relative --go_out=. $(filter %.proto,$^)
88+
89+
# Build target for current binary.
90+
build/$(name)_%/$(name)$(goexe): $(validate_pb_go)
91+
@GOBIN=$(root_dir)$(current_binary_path) $(go) install .
92+
93+
# Generate all required files for harness tests in Go.
94+
$(tests_harness_cases): $(current_binary)
95+
$(call generate-test-cases-go,tests$@)
96+
97+
# Generates a test-case for Go.
98+
define generate-test-cases-go
99+
@cd $1 && \
100+
mkdir -p go && \
101+
$(protoc) \
102+
-I . \
103+
-I $(root_dir) \
104+
--go_opt=paths=source_relative \
105+
--go_out=go \
106+
--validate_opt=paths=source_relative \
107+
--validate_out=lang=go:go \
108+
*.proto
109+
endef
110+
111+
include tools/build/Installer.mk

Tools.mk

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Licensed under the Apache License, Version 2.0 (the "License")
2+
3+
bazelisk@v := github.com/bazelbuild/[email protected]
4+
protoc@v := github.com/protocolbuffers/[email protected]
5+
protoc-gen-go@v := google.golang.org/protobuf/cmd/[email protected]

tools/build/Env.mk

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Licensed under the Apache License, Version 2.0 (the "License")
2+
3+
# Disable cgo.
4+
export CGOENABLED := 0
5+
6+
# Reference: https://developers.google.com/protocol-buffers/docs/reference/go/faq#namespace-conflict.
7+
export GOLANG_PROTOBUF_REGISTRATION_CONFLICT := warn

tools/build/Help.mk

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Licensed under the Apache License, Version 2.0 (the "License")
2+
3+
# This is adopted from https://github.com/tetratelabs/func-e/blob/3df66c9593e827d67b330b7355d577f91cdcb722/Makefile#L60-L76.
4+
# ANSI escape codes. f_ means foreground, b_ background.
5+
# See https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters.
6+
f_black := $(shell printf "\33[30m")
7+
b_black := $(shell printf "\33[40m")
8+
f_white := $(shell printf "\33[97m")
9+
f_gray := $(shell printf "\33[37m")
10+
f_dark_gray := $(shell printf "\33[90m")
11+
f_bright_cyan := $(shell printf "\33[96m")
12+
b_bright_cyan := $(shell printf "\33[106m")
13+
ansi_reset := $(shell printf "\33[0m")
14+
ansi_$(name) := $(b_black)$(f_black)$(b_bright_cyan)$(name)$(ansi_reset)
15+
ansi_format_dark := $(f_gray)$(f_bright_cyan)%-10s$(ansi_reset) $(f_dark_gray)%s$(ansi_reset)\n
16+
ansi_format_bright := $(f_white)$(f_bright_cyan)%-10s$(ansi_reset) $(f_black)$(b_bright_cyan)%s$(ansi_reset)\n
17+
18+
# This formats help statements in ANSI colors. To hide a target from help, don't comment it with a trailing '##'.
19+
help: ## Describe how to use each target
20+
@printf "$(ansi_$(name))$(f_white)\n"
21+
@awk 'BEGIN {FS = ":.*?## "} /^[0-9a-zA-Z_-]+:.*?## / {sub("\\\\n",sprintf("\n%22c"," "), $$2);printf "$(ansi_format_dark)", $$1, $$2}' $(MAKEFILE_LIST)

tools/build/Installer.mk

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Licensed under the Apache License, Version 2.0 (the "License")
2+
3+
# Catch all rules for Go-based tools.
4+
$(go_tools_dir)/bin/%:
5+
@GOBIN=$(go_tools_dir)/bin $(go) install $($(notdir $@)@v)
6+
7+
# Install protoc from github.com/protocolbuffers/protobuf.
8+
protoc-os := $(if $(findstring $(goos),darwin),osx,$(goos))
9+
protoc-arch := $(if $(findstring $(goarch),arm64),aarch_64,x86_64)
10+
protoc-version = $(subst github.com/protocolbuffers/protobuf@v,$(empty),$($(notdir $1)@v))
11+
protoc-archive = protoc-$(call protoc-version,$1)-$(protoc-os)-$(protoc-arch).zip
12+
protoc-url = https://$(subst @,/releases/download/,$($(notdir $1)@v))/$(call protoc-archive,$1)
13+
protoc-zip = $(prepackaged_tools_dir)/$(call protoc-archive,$1)
14+
$(protoc):
15+
@mkdir -p $(prepackaged_tools_dir)
16+
ifeq ($(goos),linux)
17+
@curl -sSL $(call protoc-url,$@) -o $(call protoc-zip,$@)
18+
@unzip -oqq $(call protoc-zip,$@) -d $(prepackaged_tools_dir)
19+
@rm -f $(call protoc-zip,$@)
20+
else
21+
@curl -sSL $(call protoc-url,$@) | tar xf - -C $(prepackaged_tools_dir)
22+
@chmod +x $@
23+
endif

0 commit comments

Comments
 (0)