include $(TOPDIR)/rules.mk

PROJECT_DIR:=$(CURDIR)
PKG_NAME:=sing-box-rr
PKG_VERSION:=$(shell cat $(CURDIR)/../VERSION 2>/dev/null || echo 0.0.0-unknown)
PKG_RELEASE:=6
PKG_SOURCE_DATE_EPOCH:=$(shell cat $(CURDIR)/../SOURCE_DATE_EPOCH 2>/dev/null || date +%s)

PKG_LICENSE:=GPL-3.0-or-later
PKG_LICENSE_FILES:=LICENSE
PKG_MAINTAINER:=RR Edition

PKG_BUILD_PARALLEL:=1
PKG_BUILD_FLAGS:=no-mips16

GO_BIN?=/usr/local/go/bin/go
SINGBOX_RR_LD_LLD_BIN?=
SINGBOX_RR_BUILT_BINARY=$(PKG_BUILD_DIR)/sing-box
SINGBOX_RR_GOCACHE?=$(TMP_DIR)/sing-box-rr-go-build
SINGBOX_RR_GOMODCACHE?=$(DL_DIR)/sing-box-rr-go-mod
SINGBOX_RR_TAGS:=$(shell tr -d '\n' < $(PROJECT_DIR)/release/DEFAULT_BUILD_TAGS_OTHERS 2>/dev/null)
SINGBOX_RR_BASE_LDFLAGS:=$(shell tr -d '\n' < $(PROJECT_DIR)/release/LDFLAGS 2>/dev/null)
SINGBOX_RR_LDFLAGS:=$(strip $(SINGBOX_RR_BASE_LDFLAGS) -X github.com/sagernet/sing-box/constant.Version=$(PKG_VERSION) -s -w)

ifeq ($(ARCH),aarch64)
  SINGBOX_RR_GOARCH:=arm64
endif

ifeq ($(ARCH),x86_64)
  SINGBOX_RR_GOARCH:=amd64
  SINGBOX_RR_GOENV_EXTRA:=GOAMD64=v1
endif

include $(INCLUDE_DIR)/package.mk

define Package/sing-box-rr
  TITLE:=Sing-box RR edition
  SECTION:=net
  CATEGORY:=Network
  URL:=https://git.my-handbook.ru/fresa/sing-box-rr-edition
  DEPENDS:=@(aarch64||x86_64) +ca-bundle +kmod-inet-diag +kmod-tun
  PROVIDES:=sing-box sing-box-tiny
  CONFLICTS:=sing-box
  USERID:=sing-box=5566:sing-box=5566
endef

define Package/sing-box-rr/description
  Trimmed OpenWrt build of the sing-box RR Edition fork.
  Keeps the network-oriented runtime and preserves XHTTP and mKCP.
endef

define Build/Prepare
	rm -rf $(PKG_BUILD_DIR)
	mkdir -p $(PKG_BUILD_DIR)
	( \
		cd "$(PROJECT_DIR)" && \
		tar \
			--exclude=.git \
			--exclude=.codex \
			--exclude=BUILD.md \
			--exclude=Makefile \
			--exclude=Makefile.sing-box \
			-cf - . \
	) | (cd "$(PKG_BUILD_DIR)" && tar -xf -)
endef

define Build/Compile
	[ -x "$(GO_BIN)" ] || { echo "external Go not found at $(GO_BIN)"; exit 1; }
	[ -n "$(SINGBOX_RR_GOARCH)" ] || { echo "unsupported OpenWrt ARCH: $(ARCH)"; exit 1; }
	mkdir -p "$(SINGBOX_RR_GOCACHE)" "$(SINGBOX_RR_GOMODCACHE)"
	( \
		set -e; \
		use_cgo=0; \
		cc_env=; \
		cxx_env=; \
		if printf '%s' "$(SINGBOX_RR_TAGS)" | tr ',' '\n' | grep -qx 'with_musl'; then \
			use_cgo=1; \
			if [ -n "$(SINGBOX_RR_LD_LLD_BIN)" ]; then \
				ld_bin="$(SINGBOX_RR_LD_LLD_BIN)"; \
			else \
				if printf '%s' "$(SINGBOX_RR_TAGS)" | tr ',' '\n' | grep -qx 'with_naive_outbound'; then \
					ld_bin=$$$$(find "$(TOPDIR)/staging_dir/host" -maxdepth 3 -name ld.lld | head -n1); \
					[ -n "$$$$ld_bin" ] || ld_bin=$$$$(find "$(TOPDIR)/staging_dir/host" -maxdepth 3 -type f -name lld | head -n1); \
					if [ -z "$$$$ld_bin" ]; then \
						ld_bin=$$$$(command -v $(TARGET_CROSS)ld.bfd); \
						[ -n "$$$$ld_bin" ] || ld_bin=$$$$(command -v $(TARGET_CROSS)ld); \
					fi; \
				else \
					ld_bin=$$$$(command -v $(TARGET_CROSS)ld.bfd); \
					[ -n "$$$$ld_bin" ] || ld_bin=$$$$(command -v $(TARGET_CROSS)ld); \
					if [ -z "$$$$ld_bin" ]; then \
						ld_bin=$$$$(find "$(TOPDIR)/staging_dir/host" -maxdepth 3 -name ld.lld | head -n1); \
						[ -n "$$$$ld_bin" ] || ld_bin=$$$$(find "$(TOPDIR)/staging_dir/host" -maxdepth 3 -type f -name lld | head -n1); \
					fi; \
				fi; \
			fi; \
			[ -x "$$$$ld_bin" ] || { echo "no suitable linker found for $(TARGET_CC)"; exit 1; }; \
			wrapper_dir="$(PKG_BUILD_DIR)/.toolchain"; \
			rm -rf "$$$$wrapper_dir"; \
			mkdir -p "$$$$wrapper_dir"; \
			printf '%s\n' '#!/bin/sh' > "$$$$wrapper_dir/ld"; \
			printf '%s' "exec $$$$ld_bin \"" >> "$$$$wrapper_dir/ld"; \
			printf '\044@' >> "$$$$wrapper_dir/ld"; \
			printf '%s\n' '"' >> "$$$$wrapper_dir/ld"; \
			printf '%s\n' '#!/bin/sh' > "$$$$wrapper_dir/cc"; \
			printf '%s\n' "export STAGING_DIR='$(TOPDIR)/staging_dir'" >> "$$$$wrapper_dir/cc"; \
			printf '%s' "exec $(TARGET_CC) -B'$$$$wrapper_dir' \"" >> "$$$$wrapper_dir/cc"; \
			printf '\044@' >> "$$$$wrapper_dir/cc"; \
			printf '%s\n' '"' >> "$$$$wrapper_dir/cc"; \
			printf '%s\n' '#!/bin/sh' > "$$$$wrapper_dir/cxx"; \
			printf '%s\n' "export STAGING_DIR='$(TOPDIR)/staging_dir'" >> "$$$$wrapper_dir/cxx"; \
			printf '%s' "exec $(TARGET_CXX) -B'$$$$wrapper_dir' \"" >> "$$$$wrapper_dir/cxx"; \
			printf '\044@' >> "$$$$wrapper_dir/cxx"; \
			printf '%s\n' '"' >> "$$$$wrapper_dir/cxx"; \
			chmod +x "$$$$wrapper_dir/ld" "$$$$wrapper_dir/cc" "$$$$wrapper_dir/cxx"; \
			cc_env="CC=$$$$wrapper_dir/cc"; \
			cxx_env="CXX=$$$$wrapper_dir/cxx"; \
		fi; \
		cd "$(PKG_BUILD_DIR)" && \
		env \
		$$$$cc_env \
		$$$$cxx_env \
		PATH="$(dir $(GO_BIN)):$$$$PATH" \
		GOTOOLCHAIN=local \
		GOCACHE="$(SINGBOX_RR_GOCACHE)" \
		GOMODCACHE="$(SINGBOX_RR_GOMODCACHE)" \
		CGO_ENABLED="$$$$use_cgo" \
		GOOS=linux \
		GOARCH="$(SINGBOX_RR_GOARCH)" \
		$(SINGBOX_RR_GOENV_EXTRA) \
		"$(GO_BIN)" build \
			-buildvcs=false \
			-trimpath \
			-tags "$(SINGBOX_RR_TAGS)" \
			-ldflags "$(SINGBOX_RR_LDFLAGS)" \
			-o "$(SINGBOX_RR_BUILT_BINARY)" \
			./cmd/sing-box \
	)
endef

define Package/sing-box-rr/conffiles
/etc/config/sing-box
/etc/sing-box/config.json
endef

define Package/sing-box-rr/install
	$(INSTALL_DIR) $(1)/usr/bin
	$(INSTALL_BIN) $(SINGBOX_RR_BUILT_BINARY) $(1)/usr/bin/sing-box

	$(INSTALL_DIR) $(1)/etc/sing-box
	$(INSTALL_DATA) $(PKG_BUILD_DIR)/release/config/config.json $(1)/etc/sing-box/config.json

	$(INSTALL_DIR) $(1)/etc/config
	$(INSTALL_CONF) $(PKG_BUILD_DIR)/release/config/openwrt.conf $(1)/etc/config/sing-box

	$(INSTALL_DIR) $(1)/etc/init.d
	$(INSTALL_BIN) $(PKG_BUILD_DIR)/release/config/openwrt.init $(1)/etc/init.d/sing-box

	$(INSTALL_DIR) $(1)/lib/upgrade/keep.d
	$(INSTALL_DATA) $(PKG_BUILD_DIR)/release/config/openwrt.keep $(1)/lib/upgrade/keep.d/sing-box
endef

define Package/sing-box-rr/prerm
#!/bin/sh
[ -n "$${IPKG_INSTROOT}" ] && exit 0
[ "$$PKG_UPGRADE" = "1" ] && exit 0
/etc/init.d/sing-box stop 2>/dev/null || true
exit 0
endef

$(eval $(call BuildPackage,sing-box-rr))
