diff --git a/GNUmakefile b/GNUmakefile index 033424553..2f54b4ef1 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -1,77 +1,209 @@ -PACKAGES = $(shell go list ./... | grep -v '/vendor/') -EXTERNAL_TOOLS=\ - github.com/kardianos/govendor \ - golang.org/x/tools/cmd/cover \ - github.com/axw/gocov/gocov \ - gopkg.in/matm/v1/gocov-html \ - github.com/ugorji/go/codec/codecgen +PROJECT_ROOT := $(patsubst %/,%,$(dir $(abspath $(lastword $(MAKEFILE_LIST))))) +THIS_OS := $(shell uname) -TEST_TOOLS=\ - github.com/hashicorp/vault +GIT_COMMIT := $(shell git rev-parse HEAD) +GIT_DIRTY := $(if $(shell git status --porcelain),+CHANGES) -all: test +GO_LDFLAGS := "-X main.GitCommit=$(GIT_COMMIT)$(GIT_DIRTY)" +GO_TAGS = -dev: format generate - @scripts/build-dev.sh +# Enable additional linters as the codebase evolves to pass them +CHECKS ?= --enable goimports -bin: generate - @sh -c "'$(PWD)/scripts/build.sh'" +default: help -release: generate - @sh -c "TARGETS=release '$(PWD)/scripts/build.sh'" +ifeq (,$(findstring $(THIS_OS),Darwin Linux)) +$(error Building Nomad is currently only supported on Darwin and Linux.) +endif -cov: - gocov test ./... | gocov-html > /tmp/coverage.html - open /tmp/coverage.html +# On Linux we build for Linux, Windows, and potentially Linux+LXC +ifeq (Linux,$(THIS_OS)) +HAS_LXC = $(shell pkg-config --exists lxc) +ALL_TARGETS += linux_386 \ + linux_amd64 \ + linux_arm \ + linux_arm64 \ + windows_386 \ + windows_amd64 -test: generate - @echo "--> Running go fmt" ; - @if [ -n "`go fmt ${PACKAGES}`" ]; then \ - echo "[ERR] go fmt updated formatting. Please commit formatted code first."; \ - exit 1; \ - fi - @sh -c "'$(PWD)/scripts/test.sh'" - @$(MAKE) vet +ifeq (,$(HAS_LAX)) +ALL_TARGETS += linux_amd64-lxc +endif +endif -cover: - go list ./... | xargs -n1 go test --cover +# On MacOS we only build for MacOS +ifeq (Darwin,$(THIS_OS)) +ALL_TARGETS += darwin_amd64 +endif -format: - @echo "--> Running go fmt" - @go fmt $(PACKAGES) +pkg/darwin_amd64/nomad: $(SOURCE_FILES) ## Build Nomad for darwin/amd64 + @echo "==> Building $@..." + @CGO_ENABLED=1 GOOS=darwin GOARCH=amd64 \ + go build \ + -ldflags $(GO_LDFLAGS) \ + -tags "$(GO_TAGS)" \ + -o "$@" -generate: - @echo "--> Running go generate" - @go generate $(PACKAGES) - @sed -i.old -e 's|github.com/hashicorp/nomad/vendor/github.com/ugorji/go/codec|github.com/ugorji/go/codec|' nomad/structs/structs.generated.go +pkg/linux_386/nomad: $(SOURCE_FILES) ## Build Nomad for linux/386 + @echo "==> Building $@..." + @CGO_ENABLED=1 GOOS=linux GOARCH=386 \ + go build \ + -ldflags $(GO_LDFLAGS) \ + -tags "$(GO_TAGS)" \ + -o "$@" -vet: - @echo "--> Running go vet $(VETARGS) ${PACKAGES}" - @go vet $(VETARGS) ${PACKAGES} ; if [ $$? -eq 1 ]; then \ - echo ""; \ - echo "[LINT] Vet found suspicious constructs. Please check the reported constructs"; \ - echo "and fix them if necessary before submitting the code for review."; \ - exit 1; \ - fi - @git grep -n `echo "log"".Print"` | grep -v 'vendor/' ; if [ $$? -eq 0 ]; then \ - echo "[LINT] Found "log"".Printf" calls. These should use Nomad's logger instead."; \ - fi +pkg/linux_amd64/nomad: $(SOURCE_FILES) ## Build Nomad for linux/amd64 + @echo "==> Building $@..." + @CGO_ENABLED=1 GOOS=linux GOARCH=amd64 \ + go build \ + -ldflags $(GO_LDFLAGS) \ + -tags "$(GO_TAGS)" \ + -o "$@" -# bootstrap the build by downloading additional tools -bootstrap: - @for tool in $(EXTERNAL_TOOLS) ; do \ - echo "Installing $$tool" ; \ - go get $$tool; \ - done - @for tool in $(TEST_TOOLS) ; do \ - echo "Installing $$tool (test dependency)" ; \ - go get $$tool; \ - done +pkg/linux_arm/nomad: $(SOURCE_FILES) ## Build Nomad for linux/arm + @echo "==> Building $@..." + @CGO_ENABLED=1 GOOS=linux GOARCH=arm CC=arm-linux-gnueabihf-gcc-5 \ + go build \ + -ldflags $(GO_LDFLAGS) \ + -tags "$(GO_TAGS)" \ + -o "$@" -install: bin/nomad - install -o root -g wheel -m 0755 ./bin/nomad /usr/local/bin/nomad +pkg/linux_arm64/nomad: $(SOURCE_FILES) ## Build Nomad for linux/arm64 + @echo "==> Building $@..." + @CGO_ENABLED=1 GOOS=linux GOARCH=arm64 CC=aarch64-linux-gnu-gcc-5 \ + go build \ + -ldflags $(GO_LDFLAGS) \ + -tags "$(GO_TAGS)" \ + -o "$@" -travis: - @sh -c "'$(PWD)/scripts/travis.sh'" +# If CGO support for Windows is ever required, set the following variables +# in the environment for `go build` for both the windows/amd64 and the +# windows/386 targets: +# CC=i686-w64-mingw32-gcc +# CXX=i686-w64-mingw32-g++ +pkg/windows_386/nomad: $(SOURCE_FILES) ## Build Nomad for windows/386 + @echo "==> Building $@..." + @CGO_ENABLED=1 GOOS=windows GOARCH=386 \ + go build \ + -ldflags $(GO_LDFLAGS) \ + -tags "$(GO_TAGS)" \ + -o "$@" -.PHONY: all bin cov integ test vet test-nodep +pkg/windows_amd64/nomad: $(SOURCE_FILES) ## Build Nomad for windows/amd64 + @echo "==> Building $@..." + @CGO_ENABLED=1 GOOS=windows GOARCH=386 \ + go build \ + -ldflags $(GO_LDFLAGS) \ + -tags "$(GO_TAGS)" \ + -o "$@" + +pkg/linux_amd64-lxc/nomad: $(SOURCE_FILES) ## Build Nomad+LXC for linux/amd64 + @echo "==> Building $@..." + @CGO_ENABLED=1 GOOS=linux GOARCH=amd64 \ + go build \ + -ldflags $(GO_LDFLAGS) \ + -tags "$(GO_TAGS) lxc" \ + -o "$@" + +# Define package targets for each of the build targets we actually have on this system +define makePackageTarget + +pkg/$(1).zip: pkg/$(1)/nomad + @echo "==> Packaging for $(1)..." + @zip pkg/$(1).zip pkg/$(1)/* + +endef + +# Reify the package targets +$(foreach t,$(ALL_TARGETS),$(eval $(call makePackageTarget,$(t)))) + +# Only for Travis CI compliance +.PHONY: bootstrap +bootstrap: deps + +.PHONY: deps +deps: ## Install build and development dependencies + @echo "==> Updating build dependencies..." + go get -u github.com/alecthomas/gometalinter + gometalinter --install + go get -u github.com/kardianos/govendor + go get -u golang.org/x/tools/cmd/cover + go get -u github.com/axw/gocov/gocov + go get -u gopkg.in/matm/v1/gocov-html + go get -u github.com/ugorji/go/codec/codecgen + go get -u github.com/hashicorp/vault + go get -u github.com/a8m/tree/cmd/tree + +.PHONY: check +check: ## Lint the source code + @echo "==> Linting source code..." + @gometalinter \ + --deadline 10m \ + --vendor \ + --exclude '.*\.generated\.go:\d+:' \ + --disable-all \ + --sort severity \ + $(CHECKS) \ + ./... + +generate: LOCAL_PACKAGES = $(shell go list ./... | grep -v '/vendor/') +generate: ## Update generated code for the current OS/arch + @echo "==> Generating code for $(GOOS)..." + @go generate $(LOCAL_PACKAGES) + +.PHONY: dev +dev: GOOS=$(shell go env GOOS) +dev: GOARCH=$(shell go env GOARCH) +dev: GOPATH=$(shell go env GOPATH) +dev: DEV_TARGET=pkg/$(GOOS)_$(GOARCH)$(if $(HAS_LXC),-lxc)/nomad +dev: check ## Build for the current development platform + @echo "==> Removing old development build..." + @rm -f $(PROJECT_ROOT)/$(DEV_TARGET) + @rm -f $(PROJECT_ROOT)/bin/nomad + @rm -f $(GOPATH)/bin/nomad + @$(MAKE) --no-print-directory \ + $(DEV_TARGET) \ + GO_TAGS=nomad_test + @mkdir -p $(PROJECT_ROOT)/bin + @mkdir -p $(GOPATH)/bin + @cp $(PROJECT_ROOT)/$(DEV_TARGET) $(PROJECT_ROOT)/bin/ + @cp $(PROJECT_ROOT)/$(DEV_TARGET) $(GOPATH)/bin + +.PHONY: release +release: clean check $(foreach t,$(ALL_TARGETS),pkg/$(t).zip) ## Build all release packages which can be built on this platform. + @echo "==> Results:" + @tree --dirsfirst $(PROJECT_ROOT)/pkg + +.PHONY: test +test: LOCAL_PACKAGES = $(shell go list ./... | grep -v '/vendor/') +test: dev ## Run Nomad test suites + @echo "==> Running Nomad test suites:" + @NOMAD_TEST_RKT=1 \ + go test \ + -cover \ + -timeout=900s \ + -tags="nomad_test $(if $(HAS_LXC),lxc)" \ + $(LOCAL_PACKAGES) + +.PHONY: clean +clean: GOPATH=$(shell go env GOPATH) +clean: ## Remove build artifacts + @echo "==> Cleaning build artifacts..." + @rm -rf "$(PROJECT_ROOT)/bin/" + @rm -rf "$(PROJECT_ROOT)/pkg/" + @rm -f "$(GOPATH)/bin/nomad" + +.PHONY: travis +travis: ## Run Nomad test suites with output to prevent timeouts under Travis CI + @sh -C "$(PROJECT_ROOT)/scripts/travis.sh" + +HELP_FORMAT=" \033[36m%-25s\033[0m %s\n" +.PHONY: help +help: ## Display this usage information + @echo "Valid targets:" + @grep -E '^[^ ]+:.*?## .*$$' $(MAKEFILE_LIST) | \ + sort | \ + awk 'BEGIN {FS = ":.*?## "}; \ + {printf $(HELP_FORMAT), $$1, $$2}' + @echo "\nThis host will build the following targets if 'make release' is invoked:" + @echo $(ALL_TARGETS) | sed 's/^/ /' diff --git a/scripts/build-dev.sh b/scripts/build-dev.sh deleted file mode 100755 index 9668a343d..000000000 --- a/scripts/build-dev.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env bash -set -e - -GIT_COMMIT="$(git rev-parse HEAD)" -GIT_DIRTY="$(test -n "`git status --porcelain`" && echo "+CHANGES" || true)" -LDFLAG="github.com/hashicorp/nomad/version.GitCommit=${GIT_COMMIT}${GIT_DIRTY}" - -TAGS="nomad_test" -if [[ $(uname) == "Linux" ]]; then - if pkg-config --exists lxc; then - TAGS="$TAGS lxc" - fi -fi - -echo "--> Installing with tags: $TAGS" -go install -ldflags "-X $LDFLAG" -tags "${TAGS}" - -echo "--> Ensuring bin directory exists..." -mkdir -p bin - -echo "--> Copying to bin" -cp $GOPATH/bin/nomad bin/nomad diff --git a/scripts/build.sh b/scripts/build.sh deleted file mode 100755 index afa0f3eb6..000000000 --- a/scripts/build.sh +++ /dev/null @@ -1,121 +0,0 @@ -#!/usr/bin/env bash -# -# This script builds the application from source for multiple platforms. -set -e - -# Get the parent directory of where this script is. -SOURCE="${BASH_SOURCE[0]}" -while [ -h "$SOURCE" ] ; do SOURCE="$(readlink "$SOURCE")"; done -DIR="$( cd -P "$( dirname "$SOURCE" )/.." && pwd )" - -# Change into that directory -cd "$DIR" - -# Get the git commit -GIT_COMMIT="$(git rev-parse HEAD)" -GIT_DIRTY="$(test -n "`git status --porcelain`" && echo "+CHANGES" || true)" -LDFLAG="main.GitCommit=${GIT_COMMIT}${GIT_DIRTY}" - -# Delete the old dir -echo "==> Removing old directory..." -rm -f bin/* -rm -rf pkg/* -mkdir -p bin/ - -targets="$(go env GOOS)_$(go env GOARCH)" -if [[ "$TARGETS" == "release" ]]; then - if [[ $(uname) == "Linux" ]]; then - targets="linux_386 linux_amd64 linux_amd64-lxc linux_arm linux_arm64 windows_386 windows_amd64" - elif [[ $(uname) == "Darwin" ]]; then - targets="darwin_amd64" - else - echo "Unable to build on $(uname). Use Linux or Darwin." - exit 1 - fi -elif [[ "$TARGETS" != "" ]]; then - targets="$TARGETS" -fi - -# Don't exit if a single target fails -set +e - -echo "TARGETS=\"$targets\"" -for target in $targets; do - case $target in - "linux_386") - echo "==> Building linux 386..." - CGO_ENABLED=1 GOARCH="386" GOOS="linux" go build -ldflags "-X $LDFLAG" -o "pkg/linux_386/nomad" - ;; - "linux_amd64") - echo "==> Building linux amd64..." - CGO_ENABLED=1 GOARCH="amd64" GOOS="linux" go build -ldflags "-X $LDFLAG" -o "pkg/linux_amd64/nomad" - ;; - "linux_amd64-lxc") - echo "==> Building linux amd64 with lxc..." - CGO_ENABLED=1 GOARCH="amd64" GOOS="linux" go build -ldflags "-X $LDFLAG" -o "pkg/linux_amd64-lxc/nomad" -tags "lxc" - ;; - "linux_arm") - echo "==> Building linux arm..." - CGO_ENABLED=1 CC="arm-linux-gnueabihf-gcc-5" GOOS=linux GOARCH="arm" go build -ldflags "-X $LDFLAG" -o "pkg/linux_arm/nomad" - ;; - "linux_arm64") - echo "==> Building linux arm64..." - CGO_ENABLED=1 CC="aarch64-linux-gnu-gcc-5" GOOS=linux GOARCH="arm64" go build -ldflags "-X $LDFLAG" -o "pkg/linux_arm64/nomad" - ;; - "windows_386") - echo "==> Building windows 386..." - CGO_ENABLED=0 GOARCH="386" GOOS="windows" go build -ldflags "-X $LDFLAG" -o "pkg/windows_386/nomad.exe" - # Use the following if CGO is required - #CGO_ENABLED=1 CXX=i686-w64-mingw32-g++ CC=i686-w64-mingw32-gcc GOARCH="386" GOOS="windows" go build -ldflags "-X $LDFLAG" -o "pkg/windows_386/nomad.exe" - ;; - "windows_amd64") - echo "==> Building windows amd64..." - CGO_ENABLED=0 GOARCH="amd64" GOOS="windows" go build -ldflags "-X $LDFLAG" -o "pkg/windows_amd64/nomad.exe" - # Use the following if CGO is required - #CGO_ENABLED=1 CXX=x86_64-w64-mingw32-g++ CC=x86_64-w64-mingw32-gcc GOARCH="amd64" GOOS="windows" go build -ldflags "-X $LDFLAG" -o "pkg/windows_amd64/nomad.exe" - ;; - "darwin_amd64") - echo "==> Building darwin amd64..." - CGO_ENABLED=1 GOARCH="amd64" GOOS="darwin" go build -ldflags "-X $LDFLAG" -o "pkg/darwin_amd64/nomad" - ;; - *) - echo "--> Invalid target: $target" - ;; - esac -done - -set -e - -# Move all the compiled things to $GOPATH/bin -GOPATH=${GOPATH:-$(go env GOPATH)} -case $(uname) in - CYGWIN*) - GOPATH="$(cygpath $GOPATH)" - ;; -esac -OLDIFS=$IFS -IFS=: MAIN_GOPATH=($GOPATH) -IFS=$OLDIFS - -# Copy our OS/Arch to the bin/ directory -DEV_PLATFORM="./pkg/$(go env GOOS)_$(go env GOARCH)" -for F in $(find ${DEV_PLATFORM} -mindepth 1 -maxdepth 1 -type f); do - cp ${F} bin/ - cp ${F} ${MAIN_GOPATH}/bin/ -done - -# Zip and copy to the dist dir -echo "==> Packaging..." -for PLATFORM in $(find ./pkg -mindepth 1 -maxdepth 1 -type d); do - OSARCH=$(basename ${PLATFORM}) - echo "--> ${OSARCH}" - - pushd $PLATFORM >/dev/null 2>&1 - zip ../${OSARCH}.zip ./* - popd >/dev/null 2>&1 -done - -# Done! -echo -echo "==> Results:" -tree pkg/ diff --git a/scripts/test.sh b/scripts/test.sh deleted file mode 100755 index 7a3803ded..000000000 --- a/scripts/test.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env bash -set -e - -GOTEST_TAGS="nomad_test" -if [[ $(uname) == "Linux" ]]; then - if pkg-config --exists lxc; then - GOTEST_TAGS="$GOTEST_TAGS lxc" - fi -fi - -# Create a temp dir and clean it up on exit -TEMPDIR=`mktemp -d -t nomad-test.XXX` -trap "rm -rf $TEMPDIR" EXIT HUP INT QUIT TERM - -# Build the Nomad binary for the API tests -echo "--> Building nomad" -echo go build -i -tags \"$GOTEST_TAGS\" -o $TEMPDIR/nomad -go build -i -tags "$GOTEST_TAGS" -o $TEMPDIR/nomad || exit 1 - -# Run the tests -echo "--> Running tests" -GOBIN="`which go`" -sudo -E PATH=$TEMPDIR:$PATH -E GOPATH=$GOPATH -E NOMAD_TEST_RKT=1 \ - $GOBIN test -tags "$GOTEST_TAGS" ${GOTEST_FLAGS:--cover -timeout=900s} $($GOBIN list ./... | grep -v /vendor/) -