# rustdroid build orchestration.
#
# Three outputs assembled under out/:
#   - api-impl.jar             (dex of the vendored Android API Java sources)
#   - framework-res.apk        (prebuilt Android framework resources)
#   - libtranslation_layer_main.so + libandroid.so + rustdroid   (Rust native layer + launcher)
#
# Runtime deps come from Debian packages installed in /usr/lib: the bionic shims,
# libm (libm_bio) and libOpenSLES from bionic-translation / libopensles-standalone,
# and the ART runtime from art-standalone (via pkg-config). The shim linker's cfg
# (shipped by bionic-translation) maps libc.so/libm.so/libOpenSLES.so to those.
#
# Run:  LD_LIBRARY_PATH=out out/rustdroid path/to/app.apk -l activity/Class

JAVAC        ?= javac
DX           ?= dx
JAR          ?= jar
CARGO        ?= cargo
PKG_CONFIG   ?= pkg-config
CARGO_TARGET ?=

ART_LIBDIR   := $(shell $(PKG_CONFIG) --variable=libdir art-standalone)
KXML2_JAR    ?= /usr/share/java/kxml2.jar
ICU4J_JAR    ?= /usr/share/java/icu4j.jar
JARJAR_JAR   ?= /usr/share/java/jarjar.jar
BCPROV_JAR   ?= /usr/share/java/bcprov.jar
JAVA         ?= java

OUT          := out
CLASSES      := $(OUT)/classes
# Exactly the sources ATL compiles (its meson srcs list); several .java files in
# the tree are intentionally excluded stubs that do not compile.
SOURCES_LIST := java/sources.list
JAVA_SRCS    := $(shell cat $(SOURCES_LIST))

CARGO_PROFILE ?= release
ifeq ($(CARGO_PROFILE),release)
	CARGO_FLAGS := --release
	PROFILE_DIR := release
else
	CARGO_FLAGS :=
	PROFILE_DIR := debug
endif
ifneq ($(CARGO_TARGET),)
	CARGO_FLAGS += --target $(CARGO_TARGET)
	TARGET_DIR  := target/$(CARGO_TARGET)/$(PROFILE_DIR)
else
	TARGET_DIR  := target/$(PROFILE_DIR)
endif

ARM64_OUT    ?= out-arm64

.PHONY: all java native assemble arm64 clean

all: assemble

# Cross build into its own tree; needs the arm64 -dev packages, libgstreamer1.0-dev:arm64 among them.
arm64:
	$(MAKE) assemble CARGO_TARGET=aarch64-unknown-linux-gnu PKG_CONFIG=aarch64-linux-gnu-pkg-config OUT=$(ARM64_OUT)

# --- Java -> dex -----------------------------------------------------------
# android.icu is ICU4J repackaged, as AOSP builds it; ART brings its own, other JVMs load this one.
$(OUT)/android-icu4j.jar: $(ICU4J_JAR)
	@mkdir -p $(OUT)
	printf 'rule com.ibm.icu.** android.icu.@1\n' > $(OUT)/icu4j.rules
	$(JAVA) -jar $(JARJAR_JAR) process $(OUT)/icu4j.rules $(ICU4J_JAR) $@

# Likewise com.android.org.bouncycastle, the platform's BC provider.
$(OUT)/android-bouncycastle.jar: $(BCPROV_JAR)
	@mkdir -p $(OUT)
	printf 'rule org.bouncycastle.** com.android.org.bouncycastle.@1\n' > $(OUT)/bouncycastle.rules
	$(JAVA) -jar $(JARJAR_JAR) process $(OUT)/bouncycastle.rules $(BCPROV_JAR) $@

$(OUT)/api-impl.jar: $(SOURCES_LIST) $(JAVA_SRCS) $(OUT)/android-icu4j.jar
	@mkdir -p $(CLASSES)
	$(JAVAC) --release 8 -cp "$(KXML2_JAR):$(OUT)/android-icu4j.jar" \
		-encoding UTF-8 -Xlint:-deprecation,-options -sourcepath java \
		-d $(CLASSES) @$(SOURCES_LIST)
	$(JAR) cf $(OUT)/api-impl-classes.jar -C $(CLASSES) . -C java META-INF
	$(DX) --dex --incremental --output=$(OUT)/api-impl.jar $(OUT)/api-impl-classes.jar

java: $(OUT)/api-impl.jar $(OUT)/android-bouncycastle.jar

# --- Rust native layer + launcher -----------------------------------------
native:
	$(CARGO) build $(CARGO_FLAGS)

# --- Assemble the runnable layout under out/ -------------------------------
assemble: java native
	@mkdir -p $(OUT)
	cp $(TARGET_DIR)/rustdroid $(OUT)/rustdroid
	cp $(TARGET_DIR)/libtranslation_layer_main.so $(OUT)/libtranslation_layer_main.so
	cp res/framework-res/framework-res.apk $(OUT)/framework-res.apk
	cp $(TARGET_DIR)/libandroid.so $(OUT)/libandroid.so.0
	ln -sf libandroid.so.0 $(OUT)/libandroid.so
	ln -sf libandroid.so.0 $(OUT)/libjnigraphics.so
	@echo "Built out/. Run: LD_LIBRARY_PATH=$(OUT) $(OUT)/rustdroid path/to/app.apk -l activity"

clean:
	rm -rf $(OUT) $(ARM64_OUT)
	$(CARGO) clean

distclean: clean
	dh_clean
