current_dir := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
rust-installed-targets := $(shell rustup target list --installed)
IOS_TARGETS := \
	aarch64-apple-ios \
	aarch64-apple-ios-sim \
	x86_64-apple-ios
MACOS_TARGETS := \
	aarch64-apple-darwin \
	x86_64-apple-darwin
FILENAME := libonionmasq_apple.a

all: release
release: ios macos
debug: ios-debug macos-debug

ios: ios-release

ios-debug: lipo-ios-debug ios-debug-aarch64-apple-ios
ios-verbose: ios-verbose-aarch64-apple-ios-sim ios-verbose-x86_64-apple-ios ios-verbose-aarch64-apple-ios
ios-release: ios-release-aarch64-apple-ios #Simulator is never released, so don't build these targets.

macos: macos-release

macos-debug: lipo-macos-debug
macos-verbose: macos-verbose-aarch64-apple-darwin macos-verbose-x86_64-apple-darwin
macos-release: lipo-macos-release

onionmasq_apple.h:
	cbindgen --crate onionmasq-apple --config cbindgen.toml --output onionmasq_apple.h

# Args:
# $1: OS name
# $2: Rust target name
# $3: Release mode
define apple-build-rules

$(1)-$(3)-$(2): $(1)-install-deps onionmasq_apple.h
ifeq ($(3), release)
	cargo build --package onionmasq-apple --target $(2) --release
else ifeq ($(3), verbose)
	cargo build --package onionmasq-apple --target $(2) --features verbose
else
	cargo build --package onionmasq-apple --target $(2)
endif

.PHONY: $(1)-$(3)-$(2)
endef

$(foreach target, $(IOS_TARGETS), $(eval $(call apple-build-rules,ios,$(target),debug)))
$(foreach target, $(IOS_TARGETS), $(eval $(call apple-build-rules,ios,$(target),verbose)))
$(foreach target, $(IOS_TARGETS), $(eval $(call apple-build-rules,ios,$(target),release)))
$(foreach target, $(MACOS_TARGETS), $(eval $(call apple-build-rules,macos,$(target),debug)))
$(foreach target, $(MACOS_TARGETS), $(eval $(call apple-build-rules,macos,$(target),verbose)))
$(foreach target, $(MACOS_TARGETS), $(eval $(call apple-build-rules,macos,$(target),release)))

clean:
	cargo clean
	rm onionmasq_apple.h

clean-all: clean

ios-install-deps: ios-targets cbindgen

macos-install-deps: macos-targets cbindgen

cbindgen:
ifeq ($(shell command -v cbindgen),)
	cargo install cbindgen
endif

# Args:
# $1: Rust target name
# $2: OS name
define target-rules

$(2)-target-$(1):
ifeq ($$(filter $(1), $$(rust-installed-targets)),)
	rustup target install $(1)
endif
.PHONY: $(2)-target-$(1)
$(2)-targets: $(2)-target-$(1)

endef

ios-targets:
$(foreach target, $(IOS_TARGETS), $(eval $(call target-rules,$(target),ios)))

macos-targets:
$(foreach target, $(MACOS_TARGETS), $(eval $(call target-rules,$(target),macos)))

# Args:
# $1: OS name
# $2: Release mode
# $3: Rust target name 1
# $4: Rust target name 2
define lipo-rules

lipo-$(1)-$(2): $(1)-$(2)-$(3) $(1)-$(2)-$(4)
ifeq (,$(wildcard target/universal-$(1)/$(2)/$(FILENAME)))
	mkdir -p target/universal-$(1)/$(2)
	lipo target/$(3)/$(2)/$(FILENAME) target/$(4)/$(2)/$(FILENAME) -create -output target/universal-$(1)/$(2)/$(FILENAME)
endif

.PHONY: lipo-$(1)-$(2)

endef

$(eval $(call lipo-rules,macos,debug,$(word 1,$(MACOS_TARGETS)),$(word 2,$(MACOS_TARGETS))))
$(eval $(call lipo-rules,macos,release,$(word 1,$(MACOS_TARGETS)),$(word 2,$(MACOS_TARGETS))))
$(eval $(call lipo-rules,ios,debug,$(word 2,$(IOS_TARGETS)),$(word 3,$(IOS_TARGETS))))

.PHONY: ios-install-deps cbindgen ios-debug ios-release ios ios-targets
.PHONY: macos-install-deps macos-debug macos-release macos macos-targets
.PHONY: all
