#!/usr/bin/make -f

# The rules were derrived from this fedora project
# https://src.fedoraproject.org/rpms/rocm-compilersupport
# and is covered by this license.
#
# Copyright Fedora Project Authors.
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#

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

LLVM_VERSION           := 20
LLVM_VERSION_FULL      := 20.0.0
LLVM_VERSION_MINOR     := 0
LLVM_VERSION_SUFFIX    := rocm7.1.0
LLVM_VERSION_SNAPSHOT  := 0

amd_device_libs_prefix := lib/rocm/llvm/lib/clang/$(LLVM_VERSION)
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_triple            := x86_64-gnu-linux
targets_to_build       := "Native;AMDGPU"
projects_to_build      := "clang;clang-tools-extra;lld"
runtimes_to_build      := "compiler-rt"

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)

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 \
 -DLLVM_VERSION_SUFFIX=$(LLVM_VERSION_SUFFIX) \
 -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/${DEB_HOST_MULTIARCH}/cmake/AMDDeviceLibs

%:
	dh $@

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

# generate install files with the correct llvm versions
stamps/preconfig: dirs
	@echo "[SECTION START] generating install files"
	for f in debian/*.in; do \
		f2=$$(echo $$f | sed 's/\.in$$//' | sed -r 's/-?X\.Y/-rocm/' ); \
		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" \
			-e "s|@LLVM_VERSION_SUFFIX@|$(LLVM_VERSION_SUFFIX)|g" \
			-e "s|-\?X\.Y|-rocm|g" \
			$$f > $$f2; \
	done
	touch $@

stamps/config-llvm: stamps/preconfig
	@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 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 \
		-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
	sed -i -e 's@libLLVM.so.$(LLVM_VERSION).$(LLVM_VERSION_MINOR)$(LLVM_VERSION_SUFFIX)@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
	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
	rm -rf $(deb_inst)/usr/bin/hipvars.pm
	# this is a python module to be imported, not executed, and throws a
	# lintian warning otherwise
	chmod -x debian/tmp/usr/lib/rocm/llvm/share/opt-viewer/optpmap.py

override_dh_install:
	dh_install
	dh_missing --list-missing

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_dwz:
override_dh_ocaml:
override_dh_ocamlinit:
override_dh_ocamlclean:

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