github.com/grumpyhome/grumpy@v0.3.1-0.20201208125205-7b775405bdf1/grumpy-runtime-src/Makefile (about) 1 # Copyright 2016 Google Inc. All Rights Reserved. 2 # 3 # Licensed under the Apache License, Version 2.0 (the "License"); 4 # you may not use this file except in compliance with the License. 5 # You may obtain a copy of the License at 6 # 7 # http://www.apache.org/licenses/LICENSE-2.0 8 # 9 # Unless required by applicable law or agreed to in writing, software 10 # distributed under the License is distributed on an "AS IS" BASIS, 11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 # See the License for the specific language governing permissions and 13 # limitations under the License. 14 15 # ------------------------------------------------------------------------------ 16 # General setup 17 # ------------------------------------------------------------------------------ 18 19 GO_ENV := $(shell go env GOOS GOARCH) 20 GOOS ?= $(word 1,$(GO_ENV)) 21 GOARCH ?= $(word 2,$(GO_ENV)) 22 ROOT_DIR := $(realpath .) 23 PKG_DIR := build/pkg/$(GOOS)_$(GOARCH) 24 25 # Try python2 and then python if PYTHON has not been set 26 ifeq ($(PYTHON),) 27 ifneq ($(shell which python2),) 28 PYTHON = python2 29 else 30 PYTHON = python 31 endif 32 endif 33 PYTHON_BIN := $(shell which $(PYTHON)) 34 PYTHON_VER := $(word 2,$(shell $(PYTHON) -V 2>&1)) 35 GO_REQ_MAJ := 1 36 GO_REQ_MIN := 9 37 GO_MAJ_MIN := $(subst go,, $(word 3,$(shell go version 2>&1)) ) 38 GO_MAJ := $(word 1,$(subst ., ,$(GO_MAJ_MIN) )) 39 GO_MIN := $(word 2,$(subst ., ,$(GO_MAJ_MIN) )) 40 41 ifeq ($(filter 2.7.%,$(PYTHON_VER)),) 42 $(error unsupported Python version $(PYTHON_VER), Grumpy only supports 2.7.x. To use a different python binary such as python2, run: 'make PYTHON=python2 ...') 43 endif 44 45 ifneq ($(shell test $(GO_MAJ) -ge $(GO_REQ_MAJ) -a $(GO_MIN) -ge $(GO_REQ_MIN) && echo ok),ok) 46 $(error unsupported Go version $(GO_VER), Grumpy requires at least $(GO_REQ_MAJ).$(GO_REQ_MIN). Please update Go) 47 endif 48 49 PY_DIR := build/lib/python2.7/site-packages 50 PY_INSTALL_DIR := $(shell $(PYTHON) -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())") 51 52 export GOPATH := $(ROOT_DIR)/build 53 export PATH := $(ROOT_DIR)/build/bin:$(PATH) 54 ifndef PYTHONPATH 55 export PYTHONPATH := $(ROOT_DIR)/$(PY_DIR) 56 else 57 export PYTHONPATH := $(PYTHONPATH):$(ROOT_DIR)/$(PY_DIR) 58 endif 59 60 GOPATH_PY_ROOT := $(GOPATH)/src/__python__ 61 62 PYTHONPARSER_SRCS := $(patsubst third_party/%,$(PY_DIR)/grumpy/%,$(wildcard third_party/pythonparser/*.py)) 63 64 COMPILER_BIN := build/bin/grumpc 65 COMPILER_SRCS := $(PY_DIR)/grumpy/__init__.py 66 COMPILER_TESTS := $(patsubst %.py,grumpy/%,$(filter-out compiler/expr_visitor_test.py compiler/stmt_test.py,$(wildcard compiler/*_test.py))) 67 COMPILER_TEST_SRCS := $(patsubst %,$(PY_DIR)/%.py,$(COMPILER_TESTS)) 68 COMPILER_SHARDED_TEST_SRCS := $(patsubst %,$(PY_DIR)/grumpy/compiler/%,expr_visitor_test.py stmt_test.py) 69 COMPILER_PASS_FILES := $(patsubst %,$(PY_DIR)/%.pass,$(COMPILER_TESTS)) 70 COMPILER_EXPR_VISITOR_PASS_FILES := $(patsubst %,$(PY_DIR)/grumpy/compiler/expr_visitor_test.%of32.pass,$(shell seq 32)) 71 COMPILER_STMT_PASS_FILES := $(patsubst %,$(PY_DIR)/grumpy/compiler/stmt_test.%of16.pass,$(shell seq 16)) 72 COMPILER_D_FILES := $(patsubst %,$(PY_DIR)/%.d,$(COMPILER_TESTS)) 73 COMPILER := $(COMPILER_BIN) $(COMPILER_SRCS) $(PYTHONPARSER_SRCS) 74 75 PKGC_BIN := build/bin/pkgc 76 77 RUNNER_BIN := build/bin/grumprun 78 RUNTIME_SRCS := $(addprefix build/src/grumpy/,$(notdir $(wildcard runtime/*.go))) 79 RUNTIME := $(PKG_DIR)/grumpy.a 80 RUNTIME_PASS_FILE := build/runtime.pass 81 RUNTIME_COVER_FILE := $(PKG_DIR)/grumpy.cover 82 RUNNER = $(RUNNER_BIN) $(COMPILER) $(RUNTIME) $(STDLIB) 83 84 LIB_SRCS := $(patsubst lib/%,$(GOPATH_PY_ROOT)/%,$(shell find lib -name '*.py')) 85 THIRD_PARTY_STDLIB_SRCS := $(patsubst third_party/stdlib/%,$(GOPATH_PY_ROOT)/%,$(shell find third_party/stdlib -name '*.py')) 86 THIRD_PARTY_PYPY_SRCS := $(patsubst third_party/pypy/%,$(GOPATH_PY_ROOT)/%,$(shell find third_party/pypy -name '*.py')) 87 THIRD_PARTY_OUROBOROS_SRCS := $(patsubst third_party/ouroboros/%,$(GOPATH_PY_ROOT)/%,$(shell find third_party/ouroboros -name '*.py')) 88 STDLIB_SRCS := $(LIB_SRCS) $(THIRD_PARTY_STDLIB_SRCS) $(THIRD_PARTY_PYPY_SRCS) $(THIRD_PARTY_OUROBOROS_SRCS) 89 90 STDLIB_PACKAGES := $(patsubst $(GOPATH_PY_ROOT)/%.py,%,$(patsubst $(GOPATH_PY_ROOT)/%/__init__.py,%,$(STDLIB_SRCS))) 91 STDLIB := $(patsubst %,$(PKG_DIR)/__python__/%.a,$(STDLIB_PACKAGES)) 92 STDLIB_TESTS := \ 93 itertools_test \ 94 math_test \ 95 os/path_test \ 96 os_test \ 97 random_test \ 98 re_tests \ 99 sys_test \ 100 tempfile_test \ 101 test/test_bisect \ 102 test/test_colorsys \ 103 test/test_datetime \ 104 test/test_dict \ 105 test/test_dircache \ 106 test/test_dummy_thread \ 107 test/test_fpformat \ 108 test/test_genericpath \ 109 test/test_list \ 110 test/test_md5 \ 111 test/test_mimetools \ 112 test/test_mutex \ 113 test/test_operator \ 114 test/test_quopri \ 115 test/test_queue \ 116 test/test_rfc822 \ 117 test/test_sched \ 118 test/test_select \ 119 test/test_slice \ 120 test/test_stat \ 121 test/test_string \ 122 test/test_threading \ 123 test/test_tuple \ 124 test/test_uu \ 125 time_test \ 126 types_test \ 127 weetest_test 128 STDLIB_PASS_FILES := $(patsubst %,build/testing/%.pass,$(notdir $(STDLIB_TESTS))) 129 130 ACCEPT_TESTS := $(patsubst %.py,%,$(wildcard testing/*.py)) 131 ACCEPT_PASS_FILES := $(patsubst %,build/%.pass,$(ACCEPT_TESTS)) 132 ACCEPT_PY_PASS_FILES := $(patsubst %,build/%_py.pass,$(filter-out %/native_test,$(ACCEPT_TESTS))) 133 134 BENCHMARKS := $(patsubst %.py,%,$(wildcard benchmarks/*.py)) 135 BENCHMARK_BINS := $(patsubst %,build/%_benchmark,$(BENCHMARKS)) 136 137 TOOL_BINS = $(patsubst %,build/bin/%,benchcmp coverparse diffrange genmake pydeps) 138 139 GOLINT_BIN = build/bin/golint 140 PYLINT_BIN = build/bin/pylint 141 142 all: $(COMPILER) $(RUNNER) $(RUNTIME) $(TOOL_BINS) 143 144 benchmarks: $(BENCHMARK_BINS) 145 146 clean: 147 @rm -rf build 148 149 clean-pycache: 150 find . -name '__pycache__' -exec rm -fr {} + 151 152 # Convenient wrapper around grumprun that avoids having to set up PATH, etc. 153 run: $(RUNNER) 154 @$(RUNNER_BIN) 155 156 test: $(ACCEPT_PASS_FILES) $(ACCEPT_PY_PASS_FILES) $(RUNTIME_PASS_FILE) $(STDLIB_PASS_FILES) 157 158 precommit: cover gofmt lint test 159 160 .PHONY: all benchmarks clean cover gofmt golint install lint precommit pylint run test 161 162 # ------------------------------------------------------------------------------ 163 # grumpc compiler 164 # ------------------------------------------------------------------------------ 165 166 $(COMPILER_BIN) $(RUNNER_BIN) $(TOOL_BINS): build/bin/%: tools/% 167 @mkdir -p build/bin 168 @cp -f $< $@ 169 @sed -i.bak -e '1s@/usr/bin/env python@$(PYTHON_BIN)@' $@ 170 @rm -f $@.bak 171 172 $(COMPILER_SRCS) $(COMPILER_TEST_SRCS) $(COMPILER_SHARDED_TEST_SRCS): $(PY_DIR)/grumpy/%.py: %.py 173 @mkdir -p $(PY_DIR)/grumpy/compiler 174 @cp -f $< $@ 175 176 $(COMPILER_PASS_FILES): %.pass: %.py $(COMPILER) $(COMPILER_TEST_SRCS) 177 @$(PYTHON) $< -q 178 @touch $@ 179 @echo compiler/`basename $*` PASS 180 181 # NOTE: In the regex below we use (\.|$) instead of \> because the latter is 182 # not available in the awk available on OS X. 183 $(COMPILER_D_FILES): $(PY_DIR)/%.d: $(PY_DIR)/%.py $(COMPILER_SRCS) $(PYTHONPARSER_SRCS) 184 @$(PYTHON) -m modulefinder $< | awk '{if (match($$2, /^grumpy(\.|$$)/)) { print "$(PY_DIR)/$*.pass: " substr($$3, length("$(ROOT_DIR)/") + 1) }}' > $@ 185 186 -include $(COMPILER_D_FILES) 187 188 # Does not depend on stdlibs since it makes minimal use of them. 189 $(COMPILER_EXPR_VISITOR_PASS_FILES): $(PY_DIR)/grumpy/compiler/expr_visitor_test.%.pass: $(PY_DIR)/grumpy/compiler/expr_visitor_test.py $(RUNNER_BIN) $(COMPILER) $(RUNTIME) $(PKG_DIR)/__python__/traceback.a 190 @$(PYTHON) $< --shard=$* 191 @touch $@ 192 @echo 'compiler/expr_visitor_test $* PASS' 193 194 COMPILER_STMT_PASS_FILE_DEPS := \ 195 $(PKG_DIR)/__python__/__go__/grumpy.a \ 196 $(PKG_DIR)/__python__/__go__/os.a \ 197 $(PKG_DIR)/__python__/__go__/runtime.a \ 198 $(PKG_DIR)/__python__/__go__/time.a \ 199 $(PKG_DIR)/__python__/__go__/unicode.a \ 200 $(PKG_DIR)/__python__/sys.a \ 201 $(PKG_DIR)/__python__/traceback.a 202 203 # Does not depend on stdlibs since it makes minimal use of them. 204 $(COMPILER_STMT_PASS_FILES): $(PY_DIR)/grumpy/compiler/stmt_test.%.pass: $(PY_DIR)/grumpy/compiler/stmt_test.py $(RUNNER_BIN) $(COMPILER) $(RUNTIME) $(COMPILER_STMT_PASS_FILE_DEPS) 205 @$(PYTHON) $< --shard=$* 206 @touch $@ 207 @echo 'compiler/stmt_test $* PASS' 208 209 $(PKGC_BIN): tools/pkgc.go 210 @mkdir -p $(@D) 211 @go build -o $@ $< 212 213 # ------------------------------------------------------------------------------ 214 # Grumpy runtime 215 # ------------------------------------------------------------------------------ 216 217 $(RUNTIME_SRCS): build/src/grumpy/%.go: runtime/%.go 218 @mkdir -p build/src/grumpy 219 @cp -f $< $@ 220 221 $(RUNTIME): $(filter-out %_test.go,$(RUNTIME_SRCS)) 222 @mkdir -p $(PKG_DIR) 223 @go tool compile -o $@ -p grumpy -complete -I $(PKG_DIR) -pack $^ 224 225 $(RUNTIME_PASS_FILE): $(RUNTIME) $(filter %_test.go,$(RUNTIME_SRCS)) 226 @go test grumpy 227 @touch $@ 228 @echo 'runtime/grumpy PASS' 229 230 $(RUNTIME_COVER_FILE): $(RUNTIME) $(filter %_test.go,$(RUNTIME_SRCS)) 231 @go test -coverprofile=$@ grumpy 232 233 cover: $(RUNTIME_COVER_FILE) $(TOOL_BINS) 234 @bash -c 'comm -12 <(coverparse $< | sed "s/^grumpy/runtime/" | sort) <(git diff --dst-prefix= $(DIFF_COMMIT) | diffrange | sort)' | sort -t':' -k1,1 -k2n,2 | sed 's/$$/: missing coverage/' | tee errors.err 235 @test ! -s errors.err 236 237 build/gofmt.diff: $(wildcard runtime/*.go) 238 @gofmt -d $^ > $@ 239 240 gofmt: build/gofmt.diff 241 @if [ -s $< ]; then echo 'gofmt found errors, run: gofmt -w $(ROOT_DIR)/runtime/*.go'; cat build/gofmt.diff; false; fi 242 243 $(GOLINT_BIN): 244 @go get -u golang.org/x/lint/golint 245 246 golint: $(GOLINT_BIN) 247 @$(GOLINT_BIN) -set_exit_status runtime 248 249 # Don't use system pip for this since behavior varies a lot between versions. 250 # Instead build pylint from source. Dependencies will be fetched by distutils. 251 $(PYLINT_BIN): 252 @mkdir -p build/third_party 253 @cd build/third_party && curl -sL https://pypi.io/packages/source/p/pylint/pylint-1.6.4.tar.gz | tar -zx 254 @cd build/third_party/pylint-1.6.4 && $(PYTHON) setup.py install --prefix $(ROOT_DIR)/build 255 256 pylint: $(PYLINT_BIN) $(COMPILER_SRCS) $(PYTHONPARSER_SRCS) $(TOOL_BINS) 257 @$(PYTHON) $(PYLINT_BIN) $(COMPILER_SRCS) $(filter-out %pydeps,$(TOOL_BINS)) 258 259 lint: golint pylint 260 261 # ------------------------------------------------------------------------------ 262 # Native modules 263 # ------------------------------------------------------------------------------ 264 265 $(PKG_DIR)/__python__/__go__/%.a: build/src/__python__/__go__/%/module.go $(RUNTIME) 266 @mkdir -p $(@D) 267 @go install __python__/__go__/$* 268 269 build/src/__python__/__go__/%/module.go: $(PKGC_BIN) $(RUNTIME) 270 @mkdir -p $(@D) 271 @$(PKGC_BIN) $* > $@ 272 273 $(PKG_DIR)/__python__/__go__/grumpy.a: $(RUNTIME) 274 275 .PRECIOUS: build/src/__python__/__go__/%/module.go $(PKG_DIR)/__python__/__go__/%.a 276 277 # ------------------------------------------------------------------------------ 278 # Standard library 279 # ------------------------------------------------------------------------------ 280 281 $(LIB_SRCS): $(GOPATH_PY_ROOT)/%: lib/% 282 @mkdir -p $(@D) 283 @cp -f $< $@ 284 285 $(THIRD_PARTY_STDLIB_SRCS): $(GOPATH_PY_ROOT)/%: third_party/stdlib/% 286 @mkdir -p $(@D) 287 @cp -f $< $@ 288 289 $(THIRD_PARTY_PYPY_SRCS): $(GOPATH_PY_ROOT)/%: third_party/pypy/% 290 @mkdir -p $(@D) 291 @cp -f $< $@ 292 293 294 $(THIRD_PARTY_OUROBOROS_SRCS): $(GOPATH_PY_ROOT)/%: third_party/ouroboros/% 295 @mkdir -p $(@D) 296 @cp -f $< $@ 297 298 build/stdlib.mk: build/bin/genmake | $(STDLIB_SRCS) 299 @genmake build > $@ 300 301 -include build/stdlib.mk 302 303 $(patsubst %,build/src/__python__/%/module.go,$(STDLIB_PACKAGES)): $(COMPILER) 304 $(patsubst %,build/src/__python__/%/module.d,$(STDLIB_PACKAGES)): build/bin/pydeps $(PYTHONPARSER_SRCS) $(COMPILER) 305 $(patsubst %,$(PKG_DIR)/__python__/%.a,$(STDLIB_PACKAGES)): $(RUNTIME) 306 307 define GRUMPY_STDLIB_TEST 308 build/testing/$(notdir $(1)).pass: $(RUNTIME) $(PKG_DIR)/__python__/$(1).a $(RUNNER_BIN) $(PKG_DIR)/__python__/traceback.a 309 @mkdir -p $$(@D) 310 @$(RUNNER_BIN) -m $(subst /,.,$(1)) 311 @touch $$@ 312 @echo 'lib/$(1) PASS' 313 314 endef 315 316 $(eval $(foreach x,$(STDLIB_TESTS),$(call GRUMPY_STDLIB_TEST,$(x)))) 317 318 # ------------------------------------------------------------------------------ 319 # Acceptance tests & benchmarks 320 # ------------------------------------------------------------------------------ 321 322 $(PY_DIR)/weetest.py: lib/weetest.py 323 @cp -f $< $@ 324 325 $(PYTHONPARSER_SRCS): $(PY_DIR)/grumpy/%: third_party/% 326 @mkdir -p $(@D) 327 @cp -f $< $@ 328 329 $(ACCEPT_PASS_FILES): build/%_test.pass: %_test.py $(RUNTIME) $(STDLIB) $(RUNNER_BIN) 330 @mkdir -p $(@D) 331 @$(RUNNER_BIN) < $< 332 @touch $@ 333 @echo '$*_test PASS' 334 335 NATIVE_TEST_DEPS := \ 336 $(PKG_DIR)/__python__/__go__/encoding/csv.a \ 337 $(PKG_DIR)/__python__/__go__/image.a \ 338 $(PKG_DIR)/__python__/__go__/math.a \ 339 $(PKG_DIR)/__python__/__go__/strings.a 340 341 build/testing/native_test.pass: $(NATIVE_TEST_DEPS) 342 343 $(ACCEPT_PY_PASS_FILES): build/%_py.pass: %.py $(PY_DIR)/weetest.py 344 @mkdir -p $(@D) 345 @$(PYTHON) $< 346 @touch $@ 347 @echo '$*_py PASS' 348 349 $(patsubst %,build/%.go,$(BENCHMARKS)): build/%.go: %.py $(COMPILER) 350 @mkdir -p $(@D) 351 @$(COMPILER_BIN) $< > $@ 352 353 $(BENCHMARK_BINS): build/benchmarks/%_benchmark: build/benchmarks/%.go $(RUNTIME) $(STDLIB) 354 @mkdir -p $(@D) 355 @go build -o $@ $< 356 357 # ------------------------------------------------------------------------------ 358 # Installation 359 # ------------------------------------------------------------------------------ 360 361 install: $(RUNNER_BIN) $(COMPILER) $(RUNTIME) $(STDLIB) 362 # Binary executables 363 install -d "$(DESTDIR)/usr/bin" 364 install -m755 build/bin/grumpc "$(DESTDIR)/usr/bin/grumpc" 365 install -m755 build/bin/grumprun "$(DESTDIR)/usr/bin/grumprun" 366 # Python module 367 install -d "$(DESTDIR)"{/usr/lib/go,"$(PY_INSTALL_DIR)"} 368 cp -rv "$(PY_DIR)/grumpy" "$(DESTDIR)$(PY_INSTALL_DIR)" 369 # Go package and sources 370 install -d "$(DESTDIR)/usr/lib/go/" 371 cp -rv build/pkg build/src "$(DESTDIR)/usr/lib/go/"