#!/usr/bin/make -f
# -*- makefile -*-
#
# These rules should work for any debian-ish distro that uses systemd
# as init.  That does _not_ include Ubuntu 14.04 ("trusty"); look for
# its own special rule file.
#
# Please keep the diff between that and this relatively small, even if
# it means having suboptimal code; these need to be kept in sync by
# sentient bags of meat.

#export DH_VERBOSE=1
export DH_OPTIONS
export DH_GOPKG := github.com/snapcore/snapd
#export DEB_BUILD_OPTIONS=nocheck
export DH_GOLANG_EXCLUDES=tests
export DH_GOLANG_BUILDPKG = $(strip $(addprefix $(DH_GOPKG)/, \
    cmd/snap \
    cmd/snap-exec \
    cmd/snap-seccomp \
    cmd/snap-update-ns \
    cmd/snapctl \
    cmd/snapd \
    cmd/snapd-apparmor \
    ))
# skip Go generate, all source code should have been committed
export DH_GOLANG_GO_GENERATE=0

export PATH:=${PATH}:${CURDIR}
# GOCACHE is needed by go-1.13+
export GOCACHE:=/tmp/go-build

# this is overridden in the ubuntu/14.04 release branch
SYSTEMD_UNITS_DESTDIR="$(shell pkg-config --variable=systemdsystemunitdir systemd)"

# The go tool does not fully support vendoring with gccgo, but we can
# work around that by constructing the appropriate -I flag by hand.
GCCGO := $(shell go tool dist env > /dev/null 2>&1 && echo no || echo yes)

# Disable -buildmode=pie mode on i386 as can panics in spectacular
# ways (LP: #1711052).
# See also https://forum.snapcraft.io/t/artful-i386-panics/
# Note while the panic is only on artful, that's because artful
# detects it; the issue potentially there on older things.
BUILDFLAGS:=-pkgdir=$(CURDIR)/_build/std
ifneq ($(shell dpkg-architecture -qDEB_HOST_ARCH),i386)
BUILDFLAGS+= -buildmode=pie
endif

GCCGOFLAGS=
ifeq ($(GCCGO),yes)
GOARCH := $(shell go env GOARCH)
GOOS := $(shell go env GOOS)
BUILDFLAGS:=
GCCGOFLAGS=-gccgoflags="-I $(CURDIR)/_build/pkg/gccgo_$(GOOS)_$(GOARCH)/$(DH_GOPKG)/vendor"
export DH_GOLANG_GO_GENERATE=0
# workaround for https://github.com/golang/go/issues/23721
export GOMAXPROCS=2
endif

# check if we need to include the testkeys in the binary
# TAGS are the go build tags for all binaries, SNAP_TAGS are for snap
# build only.
TAGS=nosecboot
SNAP_TAGS=nosecboot nomanagers
ifneq (,$(filter testkeys,$(DEB_BUILD_OPTIONS)))
	TAGS+= withtestkeys
	SNAP_TAGS+= withtestkeys
endif

DEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH)

# /usr/lib/snapd/snap-{update-ns,gdbserver-shim} are always linked
# statically against glibc. Use libc-dev-bin to avoid having to handle the
# different soname (e.g. libc6 vs libc6.1)
BUILT_USING_PACKAGES=libc-dev-bin

# export DEB_BUILD_MAINT_OPTIONS = hardening=+all
# DPKG_EXPORT_BUILDFLAGS = 1
# include /usr/share/dpkg/buildflags.mk

VENDOR_ARGS=--enable-nvidia-multiarch
BUILT_USING_PACKAGES+=libcap-dev
BUILT_USING=$(shell dpkg-query -f '$${source:Package} (= $${source:Version}), ' -W $(BUILT_USING_PACKAGES))

%:
	dh $@ --buildsystem=golang --with=golang --builddirectory=_build

override_dh_fixperms:
	dh_fixperms -Xusr/lib/snapd/snap-confine


# The .real profile is a workaround for a bug in dpkg LP: #1673247 that causes
# ubiquity to crash. It allows us to "move" the snap-confine profile from
# snap-confine into snapd in a way that works with old dpkg that is in the live
# CD image.
#
# Because both the usual and the .real profile describe the same binary the
# .real profile takes priority (as it is loaded later).
override_dh_installdeb:
	dh_apparmor --profile-name=usr.lib.snapd.snap-confine.real -psnapd
	dh_installdeb

override_dh_clean:
	dh_clean
	$(MAKE) -C data clean
	# XXX: hacky
	$(MAKE) -C cmd distclean || true
	rm -f snapd.defines.mk

version_from_changelog := $(shell dpkg-parsechangelog --show-field Version)
$(info version_from_changelog is $(version_from_changelog))

# Generate version files
define snapdtool__version_generated.go
package snapdtool
func init() {
	Version = "$(version_from_changelog)"
}
endef

define cmd__VERSION
$(version_from_changelog)
endef

define data__info
VERSION=$(version_from_changelog)
SNAPD_APPARMOR_REEXEC=0
SNAPD_ASSERTS_FORMATS='{"account-key":1,"snap-declaration":6,"system-user":2}'
endef

# Generate snapd.defines.mk for use by snapd.mk makefile targets.
# This file contains variable definitions that match Debian's FHS conventions.
define snapd_defines_mk_content
# This file is generated by Debian's snapd.rules
# Directory variables
prefix = /usr
bindir = /usr/bin
sbindir = /usr/sbin
libexecdir = /usr/lib/snapd
mandir = /usr/share/man
datadir = /usr/share
localstatedir = /var
sharedstatedir = /var/lib
unitdir = $(shell pkg-config --variable=systemdsystemunitdir systemd)
# Build configuration
builddir=$(CURDIR)/_build/bin
with_core_bits = 0
with_alt_snap_mount_dir = 0
with_apparmor = 1
with_testkeys = $(if $(findstring testkeys,$(DEB_BUILD_OPTIONS)),1,0)
with_static_pie = 0
with_vendor = 0
endef

snapd.defines.mk:
	$(file >$@,$(snapd_defines_mk_content))

override_dh_auto_build: snapd.defines.mk
	# We used to call mkversion.sh, but since it builds and executes go code
	# from this package it is significantly easier to do by hand.
	$(file >_build/src/$(DH_GOPKG)/snapdtool/version_generated.go,$(snapdtool__version_generated.go))
	$(file >cmd/VERSION,$(cmd__VERSION))
	$(file >data/info,$(data__info))
	# Build golang bits
	cp -a bootloader/assets/data _build/src/$(DH_GOPKG)/bootloader/assets

	# Prepare the build tree by removing code not used for Debian builds
	$(MAKE) -f packaging/snapd.mk prepare-debian-build-tree sourcedir=_build/src/$(DH_GOPKG) SNAPD_DEFINES_DIR=$(CURDIR)

	# and build, we cannot use modules as packaging on Debian requires us to use
	# dependencies from the distro, and this would require further updates to the
	# go.mod file
	GO111MODULE=off dh_auto_build -- $(BUILDFLAGS) -tags "$(TAGS)" $(GCCGOFLAGS)

	GO111MODULE=off $(MAKE) -f packaging/snapd.mk $(CURDIR)/_build/bin/snap SNAPD_DEFINES_DIR=$(CURDIR)

	# (static linking on powerpc with cgo is broken)
ifneq ($(shell dpkg-architecture -qDEB_HOST_ARCH),powerpc)
	# Generate static snap-exec, snapctl and snap-update-ns - it somehow includes CGO so
	# we must force a static build here. We need a static snap-{exec,update-ns}
	# inside the core snap because not all bases will have a libc
	(cd _build/bin && GO111MODULE=off GOPATH=$$(pwd)/.. CGO_ENABLED=0 go build -tags "$(TAGS)" $(GCCGOFLAGS) -pkgdir=$$(pwd)/std $(DH_GOPKG)/cmd/snap-exec)
	(cd _build/bin && GO111MODULE=off GOPATH=$$(pwd)/.. CGO_ENABLED=0 go build -tags "$(TAGS)" $(GCCGOFLAGS) -pkgdir=$$(pwd)/std $(DH_GOPKG)/cmd/snapctl)
	(cd _build/bin && GO111MODULE=off GOPATH=$$(pwd)/.. go build -tags "$(TAGS)" --ldflags '-extldflags "-static"' $(GCCGOFLAGS) -pkgdir=$$(pwd)/std $(DH_GOPKG)/cmd/snap-update-ns)

	# ensure we generated a static build
	$(MAKE) -f packaging/snapd.mk check-static-binaries SNAPD_DEFINES_DIR=$(CURDIR)
endif

	# ensure snap-seccomp is build with a static libseccomp on Ubuntu
ifeq ($(shell dpkg-vendor --query Vendor),Ubuntu)
	# (static linking on powerpc with cgo is broken)
 ifneq ($(shell dpkg-architecture -qDEB_HOST_ARCH),powerpc)
	sed -i "s|#cgo LDFLAGS:|#cgo LDFLAGS: /usr/lib/$(shell dpkg-architecture -qDEB_TARGET_MULTIARCH)/libseccomp.a|" _build/src/$(DH_GOPKG)/cmd/snap-seccomp/main.go
	(cd _build/bin && GOPATH=$$(pwd)/.. CGO_LDFLAGS_ALLOW="/.*/libseccomp.a" go build -tags "$(TAGS)" $(GCCGOFLAGS) $(DH_GOPKG)/cmd/snap-seccomp)
	# ensure that libseccomp is not dynamically linked
	ldd _build/bin/snap-seccomp
	test "$$(ldd _build/bin/snap-seccomp | grep libseccomp)" = ""
	# revert again so that the subsequent tests work
	sed -i "s|#cgo LDFLAGS: /usr/lib/$(shell dpkg-architecture -qDEB_TARGET_MULTIARCH)/libseccomp.a|#cgo LDFLAGS:|" _build/src/$(DH_GOPKG)/cmd/snap-seccomp/main.go
 endif
endif

	# Build C bits, sadly manually
	cd cmd && ( autoreconf -i -f )
	cd cmd && ( ./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var --libexecdir=/usr/lib/snapd $(VENDOR_ARGS))
	$(MAKE) -C cmd all

	# Generate the real systemd/dbus/env config files
	$(MAKE) -C data all

override_dh_auto_test:
	LANG=C.utf-8 LC_ALL=C.utf-8 SNAPD_SKIP_SLOW_TESTS=true GO111MODULE=off dh_auto_test -- $(BUILDFLAGS) -tags "$(TAGS)" $(GCCGOFLAGS) $(DH_GOPKG)/...
# a tested default (production) build should have no test keys
ifeq (,$(filter nocheck,$(DEB_BUILD_OPTIONS)))
	# check that only the main trusted account-keys are included
	$(MAKE) -f packaging/snapd.mk check-trusted-account-keys SNAPD_DEFINES_DIR=$(CURDIR)
	# run the snap-confine tests
	$(MAKE) -C cmd check
endif

override_dh_install-indep:
	# we do not need this in the package, its just needed during build
	rm -rf ${CURDIR}/debian/tmp/usr/bin/xgettext-go
	# toolbelt is not shippable
	rm -f ${CURDIR}/debian/tmp/usr/bin/toolbelt
	# we do not like /usr/bin/snappy anymore
	rm -f ${CURDIR}/debian/tmp/usr/bin/snappy
	# chrorder generator
	rm -f ${CURDIR}/debian/tmp/usr/bin/chrorder
	# bootloader assets generator
	rm -f ${CURDIR}/debian/tmp/usr/bin/genasset
	# asserts/info
	rm -f ${CURDIR}/debian/tmp/usr/bin/info
	# docs generator
	rm -f ${CURDIR}/debian/tmp/usr/bin/docs

	dh_install

override_dh_install-arch:
	# we do not need this in the package, its just needed during build
	rm -rf ${CURDIR}/debian/tmp/usr/bin/xgettext-go
	# toolbelt is not shippable
	rm -f ${CURDIR}/debian/tmp/usr/bin/toolbelt
	# we do not like /usr/bin/snappy anymore
	rm -f ${CURDIR}/debian/tmp/usr/bin/snappy
	# i18n stuff
	mkdir -p debian/snapd/usr/share
	if [ -d share/locale ]; then \
		cp -R share/locale debian/snapd/usr/share; \
	fi
	# chrorder generator
	rm -f ${CURDIR}/debian/tmp/usr/bin/chrorder
	# bootloader assets generator
	rm -f ${CURDIR}/debian/tmp/usr/bin/genasset
	# asserts/info
	rm -f ${CURDIR}/debian/tmp/usr/bin/info
	# docs generator
	rm -f ${CURDIR}/debian/tmp/usr/bin/docs

	# Install snapd's systemd units / upstart jobs, done
	# here instead of debian/snapd.install because the
	# ubuntu/14.04 release branch adds/changes bits here
	$(MAKE) -C data install DESTDIR=$(CURDIR)/debian/snapd/ \
		SYSTEMDSYSTEMUNITDIR=$(SYSTEMD_UNITS_DESTDIR)
	# We called this apps-bin-path.sh instead of snapd.sh, and
	# it's a conf file so we're stuck with it
	mv debian/snapd/etc/profile.d/snapd.sh debian/snapd/etc/profile.d/apps-bin-path.sh

	$(MAKE) -C cmd install DESTDIR=$(CURDIR)/debian/tmp
	# This breaks autopkgtest. The desired permission 111 is re-applied in postinst.
	chmod 755 $(CURDIR)/debian/tmp/var/lib/snapd/void

	# Rename the apparmor profile, see dh_apparmor call above for an explanation.
	mv $(CURDIR)/debian/tmp/etc/apparmor.d/usr.lib.snapd.snap-confine $(CURDIR)/debian/tmp/etc/apparmor.d/usr.lib.snapd.snap-confine.real

	# Outside of Ubuntu Core we don't need to install the following files:
	rm $(CURDIR)/debian/snapd/$(SYSTEMD_UNITS_DESTDIR)/snapd.autoimport.service
	rm $(CURDIR)/debian/snapd/$(SYSTEMD_UNITS_DESTDIR)/snapd.core-fixup.service
	rm $(CURDIR)/debian/snapd/$(SYSTEMD_UNITS_DESTDIR)/snapd.failure.service
	rm $(CURDIR)/debian/snapd/$(SYSTEMD_UNITS_DESTDIR)/snapd.snap-repair.service
	rm $(CURDIR)/debian/snapd/$(SYSTEMD_UNITS_DESTDIR)/snapd.snap-repair.timer
	rm $(CURDIR)/debian/snapd/$(SYSTEMD_UNITS_DESTDIR)/snapd.system-shutdown.service
	rm $(CURDIR)/debian/snapd/$(SYSTEMD_UNITS_DESTDIR)/snapd.recovery-chooser-trigger.service
	rm $(CURDIR)/debian/snapd/usr/lib/snapd/snapd.run-from-snap
	# New gpio-chardev interface only support on ubuntu for now, we don't need
	# to install the ordering target
	rm $(CURDIR)/debian/snapd/$(SYSTEMD_UNITS_DESTDIR)/snapd.gpio-chardev-setup.target

	dh_install

override_dh_auto_install: snap.8
	dh_auto_install -O--buildsystem=golang

snap.8:
	# fix reproducible builds as reported by:
	#   https://tests.reproducible-builds.org/debian/rb-pkg/unstable/amd64/snapd.html
	# once golang-go-flags is fixed we can remove the "sed" expression
	$(CURDIR)/_build/bin/snap help --man | sed '1 s/^.*/.TH snap 8 "$(shell date --reference=debian/changelog +"%d %B %Y")"/' > $@

override_dh_auto_clean:
	dh_auto_clean -O--buildsystem=golang
	rm -vf snap.8

override_dh_gencontrol:
	dh_gencontrol -- -VBuilt-Using="$(BUILT_USING)"
