#!/usr/bin/make -f
include /usr/share/dpkg/pkg-info.mk

export DH_VERBOSE = 1
export DEB_BUILD_MAINT_OPTIONS = hardening=+all optimize=-lto
export DEB_CXXFLAGS_MAINT_PREPEND = -gz

amd_device_libs_prefix = lib/rocm/llvm/lib/clang/$(llvm_maj_ver)
deb_inst               := $(CURDIR)/debian/tmp/
build_stage1           := $(CURDIR)/build-llvm/
build_stage2           := $(CURDIR)/build-llvm-2/
build_devicelibs       := $(CURDIR)/build-devicelibs/
_includedir            := /usr/include
build_type             := RelWithDebInfo
bundle_prefix          := /usr/lib/rocm/llvm
llvm_maj_ver           := 20
llvm_triple            := x86_64-gnu-linux
targets_to_build       := "X86;AMDGPU"
projects_to_build      := "clang;clang-tools-extra;lld"
runtimes_to_build      := "compiler-rt;libcxx;libcxxabi"

ifneq (,$(filter parallel=%,$(subst $(COMMA), ,$(DEB_BUILD_OPTIONS))))
  NCPUS := $(subst parallel=,,$(filter parallel=%,$(subst $(COMMA), ,$(DEB_BUILD_OPTIONS))))
else
  NCPUS := $(shell nproc)
endif


# no 32bit support
FLANG_ARCHS := amd64 arm64 ppc64el ppc64 sparc64 riscv64 loong64

# From src:llvm-toolchain-19's d/rules
# flang has some memory hogs, of up to 6.2gb per process. Limit the parallel jobs
# based on the available memory
ifneq (,$(filter $(DEB_HOST_ARCH), $(FLANG_ARCHS)))
  MEM_PER_CPU=6000
else
  MEM_PER_CPU=2100
endif
NJOBS := $(shell mt=`awk '/^(MemAvail|SwapFree)/ { mt += $$2 } END {print mt}' /proc/meminfo`; \
		awk -vn=$(NCPUS) -vmt=$$mt -vm=$(MEM_PER_CPU) \
		'END { mt/=1024; n2 = int(mt/m); print n==1 || n2<=1 ? 1 : n2<=n ? n2 : n }' < /dev/null)

CFLAGS := $(subst -fno-cf-protection,,$(CXXFLAGS))
CFLAGS_FOR_BUILD       :=
CPPFLAGS               :=
CPPFLAGS_FOR_BUILD     :=
CXXFLAGS := $(subst -fno-cf-protection,,$(CXXFLAGS))
CXXFLAGS_FOR_BUILD     :=
LDFLAGS                :=
LDFLAGS_FOR_BUILD      :=
NINJA_OPTIONS          := -j $(NJOBS)

LLVM_VERSION := 20
LLVM_VERSION_FULL := 20.0.0
LLVM_VERSION_MINOR := 0
LLVM_VERSION_SNAPSHOT := 0

ifneq ($(filter $(DEB_HOST_ARCH),armel mipsel powerpc),)
DEVICE_LIBS_CONFIG_FLAGS += -DCMAKE_CXX_STANDARD_LIBRARIES=-latomic
endif

define create_man =
help2man \
  --no-info \
  --source=debian \
  --help-option='-h' \
  --no-discard-stderr \
  --version-string=$(DEB_VERSION) \
  --name=$(2) \
  --section=$(3) \
  --output debian/hipcc/usr/share/man/man$(3)/$(2).$(3) \
  $(1)/$(2)
endef

%:
	dh $@
llvmrocm_cmake_config = \
 -DBUILD_SHARED_LIBS=OFF \
 -DBUILD_TESTING=OFF \
 -DCLANG_ENABLE_STATIC_ANALYZER=OFF \
 -DCLANG_ENABLE_ARCMT=OFF \
 -DCMAKE_BUILD_TYPE=$(build_type) \
 -DCMAKE_INSTALL_DO_STRIP=ON \
 -DCMAKE_INSTALL_PREFIX=$(bundle_prefix) \
 -DCOMPILER_RT_BUILD_BUILTINS=ON \
 -DCOMPILER_RT_BUILD_CTX_PROFILE=OFF \
 -DCOMPILER_RT_BUILD_GWP_ASAN=OFF \
 -DCOMPILER_RT_BUILD_LIBFUZZER=OFF \
 -DCOMPILER_RT_BUILD_MEMPROF=OFF \
 -DCOMPILER_RT_BUILD_ORC=OFF \
 -DCOMPILER_RT_BUILD_PROFILE=OFF \
 -DCOMPILER_RT_BUILD_SANITIZERS=OFF \
 -DCOMPILER_RT_BUILD_XRAY=OFF \
 -DENABLE_LINKER_BUILD_ID=ON \
 -DLIBCXX_INCLUDE_BENCHMARKS=OFF \
 -DLIBCXXABI_USE_LLVM_UNWINDER=OFF \
 -DLLVM_BINUTILS_INCDIR=$(_includedir) \
 -DLLVM_BUILD_LLVM_DYLIB=ON \
 -DLLVM_BUILD_RUNTIME=ON \
 -DLLVM_DEFAULT_TARGET_TRIPLE=$(llvm_triple) \
 -DLLVM_ENABLE_EH=ON \
 -DLLVM_ENABLE_FFI=ON \
 -DLLVM_ENABLE_OCAMLDOC=OFF \
 -DLLVM_ENABLE_RTTI=ON \
 -DLLVM_ENABLE_ZLIB=ON \
 -DLLVM_ENABLE_ZSTD=ON \
 -DLLVM_INCLUDE_BENCHMARKS=OFF \
 -DLLVM_INCLUDE_EXAMPLES=OFF \
 -DLLVM_INCLUDE_TESTS=OFF \
 -DLLVM_TARGETS_TO_BUILD=$(targets_to_build) \
 -DLLVM_TOOL_GOLD_BUILD=ON \
 -DLLVM_TOOL_LLVM_AS_FUZZER_BUILD=OFF \
 -DLLVM_TOOL_LLVM_DIS_FUZZER_BUILD=OFF \
 -DLLVM_TOOL_LLVM_DLANG_DEMANGLE_FUZZER_BUILD=OFF \
 -DLLVM_TOOL_LLVM_ISEL_FUZZER_BUILD=OFF \
 -DLLVM_TOOL_LLVM_ITANIUM_DEMANGLE_FUZZER_BUILD=OFF \
 -DLLVM_TOOL_LLVM_MC_ASSEMBLE_FUZZER_BUILD=OFF \
 -DLLVM_TOOL_LLVM_MC_DISASSEMBLE_FUZZER_BUILD=OFF \
 -DLLVM_TOOL_LLVM_MICROSOFT_DEMANGLE_FUZZER_BUILD=OFF \
 -DLLVM_TOOL_LLVM_OPT_FUZZER_BUILD=OFF \
 -DLLVM_TOOL_LLVM_RUST_DEMANGLE_FUZZER_BUILD=OFF \
 -DLLVM_TOOL_LLVM_SPECIAL_CASE_LIST_FUZZER_BUILD=OFF \
 -DLLVM_TOOL_LLVM_YAML_NUMERIC_PARSER_FUZZER_BUILD=OFF \
 -DLLVM_TOOL_LLVM_YAML_PARSER_FUZZER_BUILD=OFF \
 -DLLVM_TOOL_VFABI_DEMANGLE_FUZZER_BUILD=OFF \
 -DMLIR_INSTALL_AGGREGATE_OBJECTS=OFF \
 -DLLVM_LINK_LLVM_DYLIB=ON \
 -DLLVM_BUILD_TOOLS=ON \
 -DLLVM_BUILD_UTILS=ON \
 -DMLIR_BUILD_MLIR_C_DYLIB=ON

llvmrocm_stage1_config = \
 -DCMAKE_AR=$(build_stage1)/bin/llvm-ar \
 -DCMAKE_C_COMPILER=$(build_stage1)/bin/clang \
 -DCMAKE_CXX_COMPILER=$(build_stage1)/bin/clang++ \
 -DCMAKE_LINKER=$(build_stage1)/bin/ld.lld \
 -DCMAKE_RANLIB=$(build_stage1)/bin/llvm-ranlib \
 -DLLVM_DIR=$(build_stage1)/lib/cmake/llvm \
 -DClang_DIR=$(build_stage1)/lib/cmake/clang \
 -DLLD_DIR=$(build_stage1)/lib/cmake/lld

llvmrocm_tools_config = \
 -DCMAKE_AR=$(build_stage2)/bin/llvm-ar \
 -DCMAKE_C_COMPILER=$(build_stage2)/bin/clang \
 -DCMAKE_CXX_COMPILER=$(build_stage2)/bin/clang++ \
 -DCMAKE_LINKER=$(build_stage2)/bin/ld.lld \
 -DCMAKE_RANLIB=$(build_stage2)/bin/llvm-ranlib \
 -DLLVM_ROOT=$(build_stage2) \
 -DClang_DIR=$(build_stage2)/lib/cmake/clang \
 -DLLD_DIR=$(build_stage2)/lib/cmake/lld

llvmrocm_devicelibs_config = \
 -DAMDDeviceLibs_DIR=$(build_devicelibs)/lib/cmake/AMDDeviceLibs

dirs:
	- mkdir stamps
	- mkdir build-llvm
	- mkdir build-llvm-2
	- mkdir build-devicelibs
	- mkdir build-comgr
	- mkdir build-hipcc

# generate install files with the correct llvm versions
stamps/preconfig:
	@echo "Memory:"
	@if [ -e /proc/meminfo ]; then \
		cat /proc/meminfo | grep -E '(Mem|Swap)Free|Cached'; \
	else \
		echo "  No memory info available"; \
	fi
	@echo "Processors: $$(cat /proc/cpuinfo | grep --count '^processor')"
	@echo "Used Processors: $(NJOBS) (out of $(NCPUS)), $(MEM_PER_CPU)kb/processor"

	@echo "[SECTION START] generating install files"
	for f in debian/*.in; do \
		f2=$$(echo $$f | sed 's/\.in$$//'); \
		echo "$$f => $$f2"; \
		sed -e "s|@LLVM_EPOCH@|$(LLVM_EPOCH)|g" \
			-e "s|@LLVM_VERSION_FULL@|$(LLVM_VERSION_FULL)|g" \
			-e "s|@LLVM_VERSION_MINOR@|$(LLVM_VERSION_MINOR)|g" \
			-e "s|@LLVM_VERSION@|$(LLVM_VERSION)|g" \
			$$f > $$f2; \
	done

stamps/config-llvm: dirs
	@echo "[SECTION START] config-llvm"
	cmake -G Ninja -S llvm -B build-llvm \
		$(llvmrocm_cmake_config) \
	       -DCMAKE_INSTALL_PREFIX=$(bundle_prefix) \
	       -DCMAKE_INSTALL_LIBDIR=lib \
	       -DLLVM_ENABLE_PROJECTS=$(projects_to_build)
	touch $@

stamps/build-llvm: stamps/config-llvm
	ninja -C build-llvm $(NINJA_OPTIONS)
	touch $@

stamps/config-llvm-2: stamps/build-llvm
	@echo "[SECTION START] config-llvm-2"
	cmake -G Ninja -S llvm -B build-llvm-2 \
		$(llvmrocm_cmake_config) \
		$(llvmrocm_stage1_config) \
		-DCMAKE_INSTALL_PREFIX=$(bundle_prefix) \
		-DCMAKE_INSTALL_RPATH=$(bundle_prefix)/lib \
		-DCMAKE_INSTALL_LIBDIR=lib \
		-DCMAKE_SKIP_INSTALL_RPATH=OFF \
		-DCLANG_DEFAULT_LINKER=lld \
		-DLLVM_ENABLE_LLD=ON \
		-DLLVM_TOOL_COMPILER_RT_BUILD=ON \
		-DLLVM_TOOL_LIBCXXABI_BUILD=OFF \
		-DLLVM_TOOL_LIBCXX_BUILD=OFF \
		-DLLVM_ENABLE_PROJECTS=$(projects_to_build) \
		-DLLVM_ENABLE_RUNTIMES=$(runtimes_to_build) 
	touch $@

stamps/build-llvm-2: stamps/config-llvm-2
	ninja -C build-llvm-2 $(NINJA_OPTIONS)
	touch $@

stamps/install-llvm-2: stamps/build-llvm-2
	DESTDIR=$(deb_inst) \
	ninja -C build-llvm-2 $(NINJA_OPTIONS) install
	touch $@

stamps/config-devicelibs: stamps/install-llvm-2
	cmake -G Ninja -S amd/device-libs -B build-devicelibs \
		$(llvmrocm_cmake_config) \
		$(llvmrocm_tools_config) \
	       -DCMAKE_INSTALL_PREFIX=/usr \
	       -DCMAKE_INSTALL_LIBDIR=lib \
	       -DROCM_DEVICE_LIBS_BITCODE_INSTALL_LOC_NEW="$(amd_device_libs_prefix)/amdgcn" \
	       -DROCM_DEVICE_LIBS_BITCODE_INSTALL_LOC_OLD=""
	touch $@

stamps/build-devicelibs: stamps/config-devicelibs
	ninja -C build-devicelibs $(NINJA_OPTIONS)
	touch $@

stamps/install-devicelibs: stamps/build-devicelibs
	DESTDIR=$(deb_inst) \
	ninja -C build-devicelibs $(NINJA_OPTIONS) install
	touch $@

# comgr needs to link against the static versions libLLVM.
# This only works well if the llvm-2 stage is only static
# which is possible but makes the build artifacts huge.
# Use some scetchy sed-foo to replace the dynamic linking
# with static linking. The original use of the libLLVM.so
# also needs a couple of other libraries added to the link.
stamps/config-comgr: stamps/install-devicelibs
	cmake -G Ninja -S amd/comgr -B build-comgr \
		$(llvmrocm_cmake_config) \
		$(llvmrocm_tools_config) \
		$(llvmrocm_devicelibs_config) \
		-DCMAKE_INSTALL_RPATH=$(bundle_prefix)/lib \
		-DBUILD_SHARED_LIBS=ON \
		-DCMAKE_INSTALL_PREFIX=/usr \
		-DCMAKE_INSTALL_LIBDIR=lib
	sed -i -e 's@libLLVM.so.20.0git@libLLVMCore.a@' build-comgr/build.ninja
	sed -i -e 's@-lrt  -lm@-lLLVMCoverage -lLLVMFrontendDriver -lLLVMFrontendHLSL -lLLVMLTO -lLLVMOption -lLLVMSymbolize -lLLVMWindowsDriver -lrt  -lm@' build-comgr/build.ninja

	touch $@

stamps/build-comgr: stamps/config-comgr
	ninja -C build-comgr $(NINJA_OPTIONS)
	touch $@

stamps/install-comgr: stamps/build-comgr
	DESTDIR=$(deb_inst) \
	ninja -C build-comgr $(NINJA_OPTIONS) install
	touch $@

stamps/config-hipcc: stamps/install-comgr
	cmake -G Ninja -S amd/hipcc -B build-hipcc \
		$(llvmrocm_cmake_config) \
		$(llvmrocm_tools_config) \
		$(llvmrocm_devicelibs_config) \
		-DCMAKE_INSTALL_RPATH=$(bundle_prefix)/lib \
		-DCMAKE_INSTALL_PREFIX=/usr \
		-DCMAKE_INSTALL_LIBDIR=lib
	touch $@

stamps/build-hipcc: stamps/config-hipcc
	ninja -C build-hipcc $(NINJA_OPTIONS)
	touch $@

stamps/install-hipcc: stamps/build-hipcc
	DESTDIR=$(deb_inst) \
	ninja -C build-hipcc $(NINJA_OPTIONS) install
	touch $@

override_dh_auto_configure: stamps/preconfig stamps/config-hipcc

override_dh_auto_build: stamps/build-hipcc

override_dh_auto_install: stamps/install-hipcc
	rm -f $(deb_inst)/usr/lib/rocm/llvm/share/clang/clang-format-bbedit.applescript
	rm $(deb_inst)usr/lib/rocm/llvm/bin/flang
	rm -rf $(deb_inst)/usr/lib/rocm/llvm/share/clang-doc
	rm -rf $(deb_inst)/usr/lib/ocaml
	rm -rf $(deb_inst)/usr/hip
	rm -rf $(deb_inst)/usr/share/doc/ROCm-Device-Libs/LICENSE.TXT
# don't want to package include, cmake or static libs for lld
	rm -rf $(deb_inst)$(bundle_prefix)/include/lld
	rm -rf $(deb_inst)$(bundle_prefix)/lib/cmake/lld
	rm -rf $(deb_inst)$(bundle_prefix)/lib/liblld*

override_dh_install: 
	dh_install
	dh_missing --list-missing

# No docs
override_dh_installdocs:

# Too many DIE's
override_dh_dwz:

clean:
	- rm -rf build-*
	- rm -rf stamps
	- rm -rf $(deb_inst)
	- rm -rf debian/.debhelper
	- rm -rf debian/rocm-llvm
	- rm -rf libcxx/utils/libcxx/__pycache__
	- rm *.install

override_dh_auto_clean: clean

override_dh_ocamlinit:
override_dh_ocamlclean:
override_dh_ocaml:
# dwz doesn't fully support DWARF-5 yet, see #1016936
override_dh_dwz:
	:

override_dh_installman:
	mkdir -p debian/hipcc/usr/share/man/man1
	# this isn't working, disabling it for now
	#$(call create_man,debian/hipcc/usr/bin,hipcc,1)
	#$(call create_man,debian/hipcc/usr/bin,hipconfig,1)
	dh_installman

override_dh_shlibdeps:
	dh_shlibdeps --dpkg-shlibdeps-params=-l$(deb_inst)$(bundle_prefix)/lib/

