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/"