datawire / build-aux

Common Makefile snippets
1 stars 0 forks source link

Add tests and CI #11

Closed LukeShu closed 5 years ago

LukeShu commented 5 years ago

This uses BATS to add tests for prelude.mk. Obviously, it would be good to add tests for more stuff as well, but it's a start.

Closes #3.

LukeShu commented 5 years ago

Added:

The memory corruption bug in Make is triggering on macOS 2/3 - 3/4 of the time. Variables set with lazyonce might get 2 extra bytes at the end, hence:

make: *** No rule to make target `/private/var/folders/yy/d215g62s727f4w2137t9jl2m0000gn/T/tmp.gvpSR9WD/build-aux/bin/flockck', needed by `all'.  Stop.

So 3/4 of the macOS CI jobs failed, but the Go 1.11 one passed.

One of the Ubuntu jobs is pending because it passed, but then I SSHed in to it to experiment with speeding up APT.

LukeShu commented 5 years ago

diff from what was reviewed:

diff --git a/.circleci/config.yml b/.circleci/config.yml
index b72feadc..d7926ec6 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -26,7 +26,12 @@ commands:
         type: string
     steps:
       - run:
-          command: sudo apt update && sudo apt install << parameters.packages >>
+          # CircleCI seems to be in EC2 us-east-1, so use an archive.ubuntu.com mirror there, so that "apt
+          # update" is consistently fast.
+          command: |
+            sudo sed -i 's,//archive\.ubuntu\.com,//us-east-1.ec2.archive.ubuntu.com,g' /etc/apt/sources.list &&
+            sudo apt update &&
+            sudo apt install << parameters.packages >>

   "brew-install":
     parameters:
@@ -53,7 +58,7 @@ commands:
       - run:
           name: "Install Go"
           command: |
-            curl https://dl.google.com/go/go1.12.$(uname -s | tr A-Z a-z)-amd64.tar.gz -o /tmp/go.tar.gz
+            curl https://dl.google.com/go/go<< parameters.version >>.$(uname -s | tr A-Z a-z)-amd64.tar.gz -o /tmp/go.tar.gz
             tar -C /tmp -xzf /tmp/go.tar.gz
             echo 'export PATH=/tmp/go/bin:$PATH' >> "$BASH_ENV"
             if [ -z "$(/tmp/go/bin/go env GOPROXY)" ]; then
@@ -104,8 +109,6 @@ jobs:

   "VM macOS 10-13":
     executor: vm-macos-10-13
-    environment:
-      build_aux_unsupported_go: true
     steps:
       - brew-install:
           packages: bats
diff --git a/CHANGELOG.md b/CHANGELOG.md
index cc745ab9..12162a27 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -58,7 +58,7 @@
  - 2019-05-01: `prelude.mk`: Add `$(call lazyonce,…)`.
  - 2019-05-01: `prelude.mk`: Introduce, steal code from `common.mk`.

- - 2019-02-15: `kubernaut-ui.mk`: Avoid warnings from `make` inside of `makeh shell`.
+ - 2019-02-15: `kubernaut-ui.mk`: Avoid warnings from `make` inside of `make shell`.

  - 2019-02-13: `_go-common.mk`: Bump golangci-lint version 1.13.1→1.15.0.

diff --git a/go-mod.mk b/go-mod.mk
index 19145aad..9bf67502 100644
--- a/go-mod.mk
+++ b/go-mod.mk
@@ -57,7 +57,6 @@ include $(dir $(_go-mod.mk))common.mk
 # Configure the `go` command

 go.goversion = $(_prelude.go.VERSION)
-go.goversion.HAVE= $(_prelude.go.VERSION.HAVE)
 go.lock = $(_prelude.go.lock)

 export GO111MODULE = on
@@ -85,9 +84,7 @@ $(eval $(call build-aux.bin-go.rule, go-mkopensource, github.com/datawire/build-

 NAME ?= $(notdir $(go.module))

-_go.module.error = $(error This Makefile requires Go '1.11.4' or newer; you $(if $(go.goversion),have '$(go.goversion)',do not seem to have Go))
-_go.module.value = $(shell GO111MODULE=on go mod edit -json | jq -r .Module.Path)
-go.module := $(_go.module.$(if $(call go.goversion.HAVE,1.11.4),value,error))
+go.module := $(_prelude.go.ensure)$(shell GO111MODULE=on go mod edit -json | jq -r .Module.Path)
 ifneq ($(words $(go.module)),1)
   $(error Could not extract $$(go.module) from ./go.mod)
 endif
diff --git a/prelude.mk b/prelude.mk
index 4055c187..b67cc39f 100644
--- a/prelude.mk
+++ b/prelude.mk
@@ -51,8 +51,8 @@
 #
 #  Internal use:
 #  - Variable: _prelude.go.VERSION      (exposed as go-mod.mk:go.goversion)
-#  - Function: _prelude.go.VERSION.HAVE (exposed as go-mod.mk:go.goversion.have)
 #  - Variable: _prelude.go.lock         (exposed as go-mod.mk:go.lock)
+#  - Variable: _prelude.go.ensure       (used by go-mod.mk)
 #
 ## common.mk targets ##
 #  - clobber
@@ -99,6 +99,25 @@ quote.shell = $(subst $(NL),'"$${NL}"','$(subst ','\'',$1)')
 # Caches the value of EXPR (in case it's expensive/slow) once it is
 # evaluated, but doesn't eager-evaluate it either.
 lazyonce = $(eval $(strip $1) := $2)$2
+_lazyonce.disabled = $(FALSE)
+
+ifeq ($(MAKE_VERSION),3.81)
+  define _lazyonce.print_warning
+    $(warning The 'lazyonce' function is known to trigger a memory corruption bug in GNU Make 3.81)
+    $(warning Disabling the 'lazyonce' function; upgrade your copy of GNU Make for faster builds)
+    $(eval _lazyonce.need_warning = $(FALSE))
+  endef
+  _lazyonce.need_warning = $(TRUE)
+  # The second $(if) is just so that the evaluated result output of
+  # _lazyonce.print_warning isn't part of the returned value.
+  lazyonce = $(if $(_lazyonce.need_warning),$(if $(_lazyonce.print_warning),))$2
+  _lazyonce.disabled = $(TRUE)
+
+  # These are use a lot, so go ahead and eager-evaluate them to speed
+  # things up.
+  _prelude.go.HAVE := $(_prelude.go.HAVE)
+  _prelude.go.VERSION := $(_prelude.go.VERSION)
+endif

 #
 # Variable constants
@@ -112,7 +131,7 @@ build-aux.bindir = $(abspath $(build-aux.dir)/bin)
 # Have this section toward the end, so that it can eagerly use stuff
 # defined above.

-FLOCK           ?= $(call lazyonce,FLOCK,$(or $(shell which flock 2>/dev/null),$(build-aux.bindir)/flock))
+FLOCK           ?= $(call lazyonce,FLOCK,$(or $(shell which flock 2>/dev/null),$(_prelude.go.ensure)$(build-aux.bindir)/flock))
 COPY_IFCHANGED  ?= $(build-aux.bindir)/copy-ifchanged
 MOVE_IFCHANGED  ?= $(build-aux.bindir)/move-ifchanged
 WRITE_IFCHANGED ?= $(build-aux.bindir)/write-ifchanged
diff --git a/prelude_go.mk b/prelude_go.mk
index 103b52f1..e52521ac 100644
--- a/prelude_go.mk
+++ b/prelude_go.mk
@@ -85,13 +85,16 @@ _prelude.go.VERSION.HAVE = $(if $(_prelude.go.HAVE),$(call _prelude.go.VERSION.g
 #
 # Building Go programs for use by build-aux

+_prelude.go.error_unsupported = $(error This Makefile requires Go '1.11.4' or newer; you $(if $(_prelude.go.HAVE),have '$(_prelude.go.VERSION)',do not seem to have Go))
+_prelude.go.ensure = $(if $(call _prelude.go.VERSION.HAVE,1.11.4),,$(_prelude.go.error_unsupported))
+
 # All of this funny business with locking can be ditched once we drop
 # support for Go 1.11.  (When removing it, be aware that go-mod.mk
 # uses `_prelude.go.*` variables).

-_prelude.go.lock.missing = $(error This Makefile requires Go '1.11.4' or newer; you do not seem to have Go)
-_prelude.go.lock.too_old = $(error This Makefile requires Go '1.11.4' or newer; you have '$(_prelude.go.VERSION)')
-_prelude.go.lock.1_11 = $(FLOCK)$(if $@, $(_prelude.go.GOPATH)/pkg/mod )
+_prelude.go.lock.unsupported = $(_prelude.go.error_unsupported)
+# The second $(if) is just to make sure that any output isn't part of what we return.
+_prelude.go.lock.1_11 = $(FLOCK)$(if $@, $(_prelude.go.GOPATH)/pkg/mod $(if $(shell mkdir -p $(_prelude.go.GOPATH)/pkg/mod),))
 _prelude.go.lock.current =

 # _prelude.go.lock is a slightly magical variable.  When evaluated as a dependency in a  
@@ -102,7 +105,6 @@ _prelude.go.lock.current =
 # When evaluated as part of a recipe, it evaluates as a command prefix
 # with arguments.
 _prelude.go.lock = $(_prelude.go.lock.$(strip \
-    $(if $(call not,$(_prelude.go.HAVE)),             missing,\
     $(if $(call _prelude.go.VERSION.HAVE, 1.12beta1), current,\
     $(if $(call _prelude.go.VERSION.HAVE, 1.11.4),    1_11,\
-                                                      too_old)))))
+                                                      unsupported))))
diff --git a/tests/go-mod.bats b/tests/go-mod.bats
index a1785053..fe166ea6 100644
--- a/tests/go-mod.bats
+++ b/tests/go-mod.bats
@@ -38,7 +38,7 @@ setup() {
    else
        [[ $(sed -n 1p actual) == 'outside: '* ]]
        [[ $(sed -n 2p actual) == 'inside: '* ]]
-       [[ $(wc -l actual) -eq 2 ]]
+       [[ $(wc -l <actual) -eq 2 ]]

        outside="$(sed -n 's/^outside: //p' actual)"
        [[ "$outside" != *' '* ]]
diff --git a/tests/prelude.bats b/tests/prelude.bats
index 9a3dbe7e..9224e4b7 100644
--- a/tests/prelude.bats
+++ b/tests/prelude.bats
@@ -32,6 +32,9 @@ load common
 }

 @test "prelude.mk: lazyonce" {
+   if [[ "$(make --version | head -n1)" == 'GNU Make 3.81' ]]; then
+       skip
+   fi
    cat >>Makefile <<-'__EOT__'
        include build-aux/prelude.mk
        var = $(call lazyonce,var,$(info eval-time)value)