Skip to content

Instantly share code, notes, and snippets.

@akutz
Created September 25, 2015 20:30
Show Gist options
  • Save akutz/d5d4e9a85663e69806bf to your computer and use it in GitHub Desktop.
Save akutz/d5d4e9a85663e69806bf to your computer and use it in GitHub Desktop.
A makefile example
STAT_FILE_SIZE = stat --format '%s' $$FILE 2> /dev/null || stat -f '%z' $$FILE 2> /dev/null
CALC_FILE_SIZE := BYTES=$$($(STAT_FILE_SIZE)); SIZE=$$(($$BYTES / 1024 / 1024)); printf "$${SIZE}MB"
PRINT_FILE_SIZE := $(STAT_FILE_SIZE) $(CALC_FILE_SIZE)
MAX_PAD := 80
STATUS_DELIM := ....................................................................................................
START_STATUS = export FILE=$(1); export PAD_LEN=$$(($(MAX_PAD) - $${\#FILE})); printf "$$FILE"
PRINT_STATUS = export EC=$$?; cd $(_); if [ "$$EC" -eq "0" ]; then printf "%*.*s%s\n" 0 $$PAD_LEN "$(STATUS_DELIM)" "SUCCESS!"; else exit $$EC; fi
PARSE_RESULT = export EC=$$?; cd $(_); if [ "$$EC" -ne "0" ]; then exit $$EC; fi
GET_GOOS = $(shell echo $(1) | tr A-Z a-z)
GET_GOARCH = $(shell if [ "$(1)" = "x86_64" ]; then echo amd64; else echo 386; fi)
BINDIR := .bin
RPMDIR := .rpm
TSTDIR := .tst
NOT_PATH := -not -path './.*' -not -path './vendor/*'
PKG_PARS := { while read F; do F=$${F\#.}; F=$${F%/*}; if [ "$$F" != "" ]; then echo $$F; fi; done } | sort | uniq
IF_MAIN = { while read F; do grep '^package main' $$F > /dev/null; if [ "$$?" $(1) "0" ]; then echo $$F; fi; done; }
IF_MAIN_TRUE := $(call IF_MAIN,-eq)
IF_MAIN_FALSE := $(call IF_MAIN,-ne)
FIND_SRCS := find . -type f -name "*.go"
SRCS := $(shell $(FIND_SRCS) $(NOT_PATH) -not -path '*/*test.go' | tr '\n' ' ')
PKGS := $(shell $(FIND_SRCS) $(NOT_PATH) | $(IF_MAIN_FALSE) | $(PKG_PARS))
MAIN_PKG := .$(shell $(FIND_SRCS) $(NOT_PATH) | $(IF_MAIN_TRUE) | $(PKG_PARS))
MAIN_NAME := $(notdir $(MAIN_PKG))
FIND_TSTS := find . -type f -name "*test.go"
TEST_PKGS := $(shell $(FIND_TSTS) $(NOT_PATH) | $(IF_MAIN_FALSE) | $(PKG_PARS))
TEST_SRCS := $(shell $(FIND_TSTS) $(NOT_PATH) | tr '\n' ' ')
TESTS := $(shell for P in $(TEST_PKGS); do echo $(BUILD)/$$P$$(basename $$P).test; done)
ALL_SRCS := $(SRCS) $(TEST_SRCS)
VENDOR := vendor
$(VENDOR): glide.yaml
@$(call START_STATUS,"glide up")
$(GLIDE) -q up 2> /dev/null
$(PRINT_STATUS)
define OBJS_TARGET
OBJS_SRC_PKG_$1 := .$$(basename $$(subst $2,,$1))
ifeq ($$(OBJS_SRC_PKG_$1),.)
OBJS_SRC_PKG_$1 := ./
endif
ifeq ($$(origin OFFLINE), undefined)
OBJS_SRC_PKG_GOGET_$1 = $$(GO) get -d ./$$(dir $$(1))
else
OBJS_SRC_PKG_GOGET_$1 = echo "" > /dev/null
endif
$1: $$(wildcard $$(OBJS_SRC_PKG_$1)/*.go) | $$(VENDOR)
@$$(call START_STATUS,$3-$4/$$(BASEPKG)$$(subst $2,,$1))
$$(GO) fmt $$?
$$(GO) fix $$?
$$(call OBJS_SRC_PKG_GOGET_$1,$$<)
env GOOS=$3 GOARCH=$4 $$(GO) \
build \
-buildmode=archive \
-o $1 \
$$(GOFLAGS) $$(LDFLAGS) \
$$(OBJS_SRC_PKG_$1)
$$(PRINT_STATUS)
endef
define BUILD_PLATFORM_TARGET
BLD_$1 := $$(BINDIR)/$1
BIN_FILE_$1 := $$(MAIN_NAME)
BIN_$1 := $$(BLD_$1)/$$(BIN_FILE_$1)
TGZ_FILE_$1 := $$(BIN_FILE_$1)-$1.$$(V_SEMVER).tar.gz
TGZ_FILE_LATEST_$1 := $$(BIN_FILE_$1)-$1.tar.gz
TGZ_$1 := $$(BLD_$1)/$$(TGZ_FILE_$1)
TGZ_LATEST_$1 := $$(BLD_$1)/$$(TGZ_FILE_LATEST_$1)
RPM_FILE_$1 := $$(BIN_FILE_$1)-$$(V_RPM_SEMVER)-1.$$(V_ARCH).rpm
RPM_FILE_LATEST_$1 := $$(BIN_FILE_$1)-latest-$$(V_ARCH).rpm
RPM_$1 := $$(BLD_$1)/$$(RPM_FILE_$1)
RPM_LATEST_$1 := $$(BLD_$1)/$$(RPM_FILE_LATEST_$1)
DEB_FILE_$1 := $$(BIN_FILE_$1)_$$(V_RPM_SEMVER)-1_amd64.deb
DEB_FILE_LATEST_$1 := $$(BIN_FILE_$1)-latest-$$(V_ARCH).deb
DEB_$1 := $$(BLD_$1)/$$(DEB_FILE_$1)
DEB_LATEST_$1 := $$(BLD_$1)/$$(DEB_FILE_LATEST_$1)
V_OS_ARCH_$1 := $1
V_OS_$1 := $$(firstword $$(subst -, ,$$(V_OS_ARCH_$1)))
V_ARCH_$1 := $$(lastword $$(subst -, ,$$(V_OS_ARCH_$1)))
GOOS_$1 := linux
#$$(call GET_GOOS,$$(V_OS_$1))
GOARCH_$1 := amd64
#$$(call GET_GOARCH,$$(V_ARCH_$1))
PKG_DIR_$1 := .obj/$$(V_OS_ARCH_$1)
OBJS_PREFIX_$1 := $$(GOPATH)/pkg/$$(GOOS_$1)_$$(GOARCH_$1)/$$(BASEPKG)
OBJS_$1 := $$(OBJS_PREFIX_$1).a $$(addsuffix .a,$$(addprefix $$(OBJS_PREFIX_$1),$$(PKGS)))
$$(foreach o,$$(OBJS_$1),$$(eval $$(call OBJS_TARGET,$$(o),$$(OBJS_PREFIX_$1),$$(GOOS_$1),$$(GOARCH_$1))))
objs: $$(OBJS_$1)
build-$$(V_OS_ARCH_$1): $$(BIN_$1)
build-$$(GOOS_$1)-$$(GOARCH_$1): $$(BIN_$1)
$$(BIN_$1): $$(OBJS_$1) $$(wildcard $$(MAIN_PKG)/*.go) | $$(VENDOR)
@$$(call START_STATUS,$$(BIN_$1))
env GOOS=$$(GOOS_$1) GOARCH=$$(GOARCH_$1) $$(GO)
build \
-buildmode=exe \
-o $$(BIN_$1) \
$$(GOFLAGS) $$(LDFLAGS) \
$$(MAIN_PKG)
$$(PRINT_STATUS)
tgz-$$(V_OS_ARCH_$1): $$(TGZ_$1)
tgz-$$(GOOS_$1)-$$(GOARCH_$1): $$(TGZ_$1)
$$(TGZ_$1): $$(BIN_$1)
@$$(call START_STATUS,$$(TGZ_$1))
tar -C $$(BLD_$1) -czf $$(TGZ_$1) $$(BIN_FILE_$1)
$$(PRINT_STATUS)
tgz-latest-$$(V_OS_ARCH_$1): $$(TGZ_LATEST_$1)
tgz-latest-$$(GOOS_$1)-$$(GOARCH_$1): $$(TGZ_LATEST_$1)
$$(TGZ_LATEST_$1): $$(TGZ_$1)
@$$(call START_STATUS,$$(TGZ_LATEST_$1))
cd $$(BLD_$1)
cp -f $$(TGZ_FILE_$1) $$(TGZ_FILE_LATEST_$1)
$$(PRINT_STATUS)
rpm-$$(V_OS_ARCH_$1): $$(RPM_$1)
rpm-$$(GOOS_$1)-$$(GOARCH_$1): $$(RPM_$1)
$$(RPM_$1): $$(BIN_$1) $$(MAIN_NAME).spec
ifeq ($$(V_OS),Linux)
@$$(call START_STATUS,$$(RPM_$1))
rm -fr $$(RPMDIR)
mkdir -p \
$$(RPMDIR)/BUILD \
$$(RPMDIR)/RPMS \
$$(RPMDIR)/SRPMS \
$$(RPMDIR)/SOURCES \
$$(RPMDIR)/tmp
ln -s ../../$$(BLD_$1) $$(RPMDIR)/RPMS/$$(V_ARCH_$1)
ln -s .. $$(RPMDIR)/SPECS
cd $$(RPMDIR)
setarch $$(V_ARCH_$1) rpmbuild -ba --quiet \
-D "rpmbuild $$(_)/$$(RPMDIR)" \
-D "v_semver $$(V_RPM_SEMVER)" \
-D "v_arch $$(V_ARCH_$1)" \
-D "binfile $$(_)/$$(BIN_$1)" \
../$$(MAIN_NAME).spec
$$(PRINT_STATUS)
endif
rpm-latest-$$(V_OS_ARCH_$1): $$(RPM_LATEST_$1)
rpm-latest-$$(GOOS_$1)-$$(GOARCH_$1): $$(RPM_LATEST_$1)
$$(RPM_LATEST_$1): $$(RPM_$1)
ifeq ($$(V_OS),Linux)
@$$(call START_STATUS,$$(RPM_LATEST_$1))
cd $$(BLD_$1)
cp -f $$(RPM_FILE_$1) $$(RPM_FILE_LATEST_$1)
$$(PRINT_STATUS)
endif
deb-$$(V_OS_ARCH_$1): $$(DEB_$1)
deb-$$(GOOS_$1)-$$(GOARCH_$1): $$(DEB_$1)
$$(DEB_$1): $$(RPM_$1)
ifeq ($$(V_OS),Linux)
@$$(call START_STATUS,$$(DEB_$1))
cd $$(BLD_$1)
fakeroot alien -k -c --bump=0 $$(RPM_FILE_$1) > /dev/null
$$(PRINT_STATUS)
endif
deb-latest-$$(V_OS_ARCH_$1): $$(DEB_LATEST_$1)
deb-latest-$$(GOOS_$1)-$$(GOARCH_$1): $$(DEBLATEST_$1)
$$(DEB_LATEST_$1): $$(DEB_$1)
ifeq ($$(V_OS),Linux)
@$$(call START_STATUS,$$(DEB_LATEST_$1))
cd $$(BLD_$1)
cp -f $$(DEB_FILE_$1) $$(DEB_FILE_LATEST_$1)
$$(PRINT_STATUS)
endif
endef
$(foreach b,$(BUILD_PLATFORMS),$(eval $(call BUILD_PLATFORM_TARGET,$(b))))
build: build-$(V_OS_ARCH)
tgz: tgz-$(V_OS_ARCH)
rpm: rpm-$(V_OS_ARCH)
deb: deb-$(V_OS_ARCH)
tgz-latest: tgz-latest-$(V_OS_ARCH)
rpm-latest: rpm-latest-$(V_OS_ARCH)
deb-latest: deb-latest-$(V_OS_ARCH)
define TEST_TARGET
$1: $$(SRCS) $$(wildcard $$(dir $1)*test.go)
@printf "building $1..."
go test -c ./$$(@D) -o $$@
$$(PRINT_STATUS)
endef
$(foreach t,$(TESTS),$(eval $(call TEST_TARGET,$(t))))
test: $(TESTS)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment