#!/usr/bin/make -f
include /usr/share/dpkg/architecture.mk
include /usr/share/dpkg/buildflags.mk
include /usr/share/rustc/architecture.mk
export CFLAGS CXXFLAGS CPPFLAGS LDFLAGS
export DEB_HOST_RUST_TYPE DEB_HOST_GNU_TYPE
export CARGO_PROFILE_RELEASE_DEBUG=true
export LIBSTDBUF_DIR = /usr/libexec/rust-coreutils

# Use lld whenever it is available: it links the big multicall binary much
# faster than GNU ld. Fall back to the default linker on arches where lld is
# not installed. Always ask the linker to print its version banner (-Wl,-v)
# so the build log records which linker actually ran.
LLD := $(shell command -v ld.lld 2>/dev/null)
ifneq ($(LLD),)
export RUSTFLAGS = -C link-arg=-fuse-ld=lld -C link-arg=-Wl,-v \
                   -C link-arg=-L/usr/lib/$(DEB_HOST_MULTIARCH)
else
export RUSTFLAGS = -C link-arg=-Wl,-v
endif

# Fat LTO + 1 codegen unit + full debuginfo of the giant multicall crate is
# fatal on some arches: s390x hits the 150min buildd timeout, 32-bit arches OOM
# on the ~3GB address space ("rustc-LLVM ERROR: out of memory"). Set the cargo
# profile env overrides so they apply to every cargo invocation (build, test,
# install), unlike a Cargo.toml sed that only wraps one step.
ifeq ($(DEB_HOST_ARCH),s390x)
export CARGO_PROFILE_RELEASE_LTO = false
export CARGO_PROFILE_RELEASE_CODEGEN_UNITS = 16
export CARGO_PROFILE_RELEASE_DEBUG = 1
endif
ifeq ($(DEB_HOST_ARCH_BITS),32)
export CARGO_PROFILE_RELEASE_LTO = thin
export CARGO_PROFILE_RELEASE_CODEGEN_UNITS = 16
export CARGO_PROFILE_RELEASE_DEBUG = 1
endif
VERSION := $(shell dpkg-parsechangelog -S Version|sed -e "s|.*~\(.*\)-.*|\1|g")
UPSTREAM_VERSION := $(shell dpkg-parsechangelog -S Version|cut -d- -f1)

# Build a multicall binary instead of multiple binaries
# to reduce the storage footprint
export MULTICALL = y

# Vendoring setup
# FIXME: The upstream Makefile we use doesn't work with the cargo wrapper,
# as it assumes no cross-compilation and hence files appearing in target/release
# rather than the architecture-specific target directory.
#export CARGO = /usr/share/cargo/bin/cargo
export CARGO_VENDOR_DIR = debian/rust-vendor
export CARGO_HOME = $(CURDIR)/debian/cargo_home

# Configure dh_quilt_patch for applying vendor patches
# This allows the debian/rust-vendor/ to be patched without dpkg-source issues
export QUILT_PATCH_DIR=debian/patches/rust-vendor
export QUILT_PC=debian/rust-vendor/.pc

# LP: #2152801
export CARGOFLAGS += --features feat_systemd_logind

%:
	dh $@ --buildsystem cargo

override_dh_auto_configure:
	if [ ! -d l10n/ ]; then \
		echo "Error: l10n translations not found! Run uscan -dd to download the l10n tarball." >&2; \
        exit 1; \
    fi
	CARGO_HOME=$(CURDIR)/debian/cargo_home DEB_CARGO_CRATE=coreutils_$(VERSION) /usr/share/cargo/bin/cargo prepare-debian $(CARGO_VENDOR_DIR)
	/usr/share/cargo/bin/dh-cargo-vendored-sources
	dh_quilt_patch
	dh_auto_configure

.PHONY: vendor

vendor:
	rm -rf $(CARGO_VENDOR_DIR)
	# Deliberately don't use the wrapper, as it expects the configure step
	# to have occurred already.
	# If you have to modify the path here, don't forget to change the README.source doc
	# as well.
	env -i cargo-vendor-filterer --all-features  --tier 2  --platform '*-*-linux-gnu' --platform '*-*-linux-gnueabi' $(CARGO_VENDOR_DIR)
	# Remove the checksum files to allow us to patch the crates
	@for crate in $(CARGO_VENDOR_DIR)/*; do \
		sed -i 's/^{"files":.*"package":"\([a-z0-9]\+\)"}$$/{"files":{},"package":"\1"}/' "$$crate/.cargo-checksum.json"; \
	done
	# Cleanup temp files
	rm -rf $(CARGO_HOME)
	# Update include-binaries
	rm -f Cargo.lock
	rm -f debian/source/include-binaries
	dpkg-source --include-binaries -b .
	# Update XS-Vendored-Sources-Rust field
	VENDORED_SOURCES=$$(/usr/share/cargo/bin/dh-cargo-vendored-sources 2>&1 | grep "^XS-Vendored-Sources-Rust:") \
	  && sed -i "s/^XS-Vendored-Sources-Rust:.*/$${VENDORED_SOURCES}/" debian/control || true
	# Commit changes
	git add -f $(CARGO_VENDOR_DIR)
	git commit -m "Update vendored rust crates" || true
	git add debian/source/
	git commit -m "Update debian/source/include-binaries" || true
	git add debian/control
	git commit debian/control -m "Update XS-Vendored-Sources-Rust field" || true


override_dh_auto_test:
ifeq ($(DEB_HOST_ARCH),s390x)
	# The release test build (every util + every test) is what actually hits
	# the buildd inactivity timeout on s390x. Tests are non-gating here (||true)
	# anyway, so skip them and rely on the other arches for coverage.
	@echo "Skipping the test suite on s390x to stay under the buildd timeout"
else
	# for now, don't fail the build if tests are failing
	CARGO_HOME=$(CURDIR)/debian/cargo_home make PROFILE=release MULTICALL=$(MULTICALL) \
				TEST_NO_FAIL_FAST="-- --skip test_dd::test_stdin_stdout_skip_w_multiplier \
				--skip test_env::test_env_arg_ignore_signal_valid_signals \
				--skip test_env::test_env_french \
				--skip test_env::test_simulation_of_terminal_for_stdin_only \
				--skip test_env::test_simulation_of_terminal_for_stdout_only \
				--skip test_env::test_simulation_of_terminal_size_information \
				--skip test_env::test_simulation_of_terminal_true \
				--skip test_chmod::test_chmod_colored_output \
				--skip test_nohup::test_nohup_stderr_to_stdout \
				--skip test_nohup::test_nohup_with_pseudo_terminal_emulation_on_stdin_stdout_stderr_get_replaced \
				--skip test_tail::test_following_with_pid \
				--skip test_tail::test_follow_when_files_are_pointing_to_same_relative_file_and_file_stays_same_size stdout \
				--skip test_touch::test_touch_changes_time_of_file_in_stdout \
				--skip test_error_messages_french_translation \
				--skip test_french_colored_error_messages \
				--skip test_help_messages_french_translation \
				--skip util_invalid_name_invalid_command" \
				test||true
endif

override_dh_auto_install:
# LTO/debuginfo/codegen are handled globally via CARGO_PROFILE_RELEASE_* env
# overrides at the top of this file, so no Cargo.toml editing is needed here.
	CARGO_HOME=$(CURDIR)/debian/cargo_home DESTDIR=$(CURDIR)/debian/tmp/ make SELINUX_ENABLED=1 PROFILE=release MULTICALL=$(MULTICALL) install
# Create the symlink early to be able to generate the manpages
	cd debian/tmp/usr/share/zsh/site-functions && mkdir rust-coreutils && chmod -x _* && mv _* rust-coreutils
	cd debian/tmp/usr/share/bash-completion/completions/ && chmod -x rust-*
	cd debian/tmp/usr/share/fish/vendor_completions.d/ && chmod -x *.fish
	cd debian/tmp/usr/bin && mv rust-coreutils coreutils && rm rust-*
#	cd debian/tmp/usr/share/fish/vendor_completions.d && for f in *fish; do mv $$f rust-$$f; done
#

execute_after_dh_install:
	install -d debian/rust-coreutils/usr/lib/cargo/bin/coreutils
	cat debian/rust-coreutils.hardlinks | while read a b; do \
		env -C debian/rust-coreutils/ ln $$a $$b; \
	done

override_dh_missing:
	dh_missing --fail-missing

override_dh_dwz:
	# Don't do anything. fails because of the
	# https://github.com/rust-lang/rust/issues/66118

override_dh_fixperms:
	dh_fixperms
	chmod 0644 debian/rust-coreutils/usr/libexec/rust-coreutils/libstdbuf.so

execute_after_dh_auto_configure:
	# Log the toolchain and linker up front, on every arch, so the build log
	# always records which linker was used - even if a later step times out
	# before any link runs. The leading '-' keeps the build going on the rare
	# arch where ld.lld is absent (we fall back to the default linker there).
	rustc --version --verbose
	-ld.lld --version
	-ld --version | head -n1

override_dh_clean:
	rm -f Cargo.toml.orig Cargo.lock
	dh_clean --exclude=Cargo.toml.orig --exclude=config.guess

override_dh_update_autotools_config:
	# don't do anything - impact vendoring otherwise
