IOS_OUT := ./ios

.PHONY: all linux android windows macos clean ios dist vendor


DEFAULT_GOAL: linux

all: linux android windows

ARCH := $(shell uname -m)
ARM_X_CC := aarch64-linux-gnu-gcc

# determine if the x64 cross arm64 compiler is available so we can add that target
LINUX_X_ARM=
ifneq (,$(strip $(shell which $(ARM_X_CC) 2> /dev/null)))
	LINUX_X_ARM = libCwtch.x.so
endif

VERSION ?= $(shell git describe --tags)
DEBVERSION := $(shell echo $(VERSION) | tr -d 'v')
DATE ?= $(shell git log -1 --format=%cd --date=format:%G-%m-%d-%H-%M)

linux: EXPERIMENTS ?= "serverExperiment"
linux: libCwtch.so $(LINUX_X_ARM) deb

macos: EXPERIMENTS ?= "serverExperiment"
macos: libCwtch.x64.dylib libCwtch.arm64.dylib

android: EXPERIMENTS ?= ""
android: cwtch.aar

windows: EXPERIMENTS ?= "serverExperiment"
windows: libCwtch.dll


dist: build/libCwtch-sources-$(VERSION).tar.xz
build/libCwtch-sources-$(VERSION).tar.xz: vendor
	go mod vendor ;
	tar --exclude="build" --exclude-vcs --exclude-vcs-ignores -cJf $@ *
	rm -r vendor

lib.go: generate/generate_bindings.go spec templates/lib_template.go
	go run generate/generate_bindings.go --experiments "$(EXPERIMENTS)"

libCwtch.so: lib.go
	./switch-ffi.sh
	go build -trimpath -ldflags "-buildid=autobindings-$(VERSION) -X main.buildVer=autobindings-$(VERSION) -X main.buildDate=$(DATE)" -buildmode c-shared -o libCwtch.so
	mkdir -p build/linux
	mkdir -p build/linux/amd64
	mkdir -p build/linux/arm64
ifeq ($(ARCH),x86_64)
	mv libCwtch.so build/linux/amd64/libCwtch.so
else ifeq ($(ARCH),aarch64)
	mv libCwtch.so build/linux/arm64/libCwtch.so
endif
	mv libCwtch.h build/linux/libCwtch.h

libCwtch.x.so: lib.go
	./switch-ffi.sh
	mkdir -p build/linux/amd64
	mkdir -p build/linux/arm64
ifeq ($(ARCH),x86_64)
	env CGO_ENABLED=1 CC=$(ARM_X_CC)  GOARCH=arm64 go build -trimpath -ldflags "-buildid=autobindings-$(VERSION) -X main.buildVer=autobindings-$(VERSION) -X main.buildDate=$(DATE)" -buildmode c-shared -o libCwtch.x.so
	mv libCwtch.x.so build/linux/arm64/libCwtch.so
	mv libCwtch.x.h build/linux/libCwtch.h
endif

deb: libCwtch.so $(LINUX_X_ARM)
ifeq ($(ARCH),x86_64)
	mkdir -p build/linux/deb/amd64/libCwtch/DEBIAN
	mkdir -p build/linux/deb/amd64/libCwtch/usr/lib
	sed "s|VERSION|$(DEBVERSION)|g" deb/control  > build/linux/deb/amd64/libCwtch/DEBIAN/control
	cp build/linux/amd64/libCwtch.so build/linux/deb/amd64/libCwtch/usr/lib
	dpkg-deb --build build/linux/deb/amd64/libCwtch
	mv build/linux/deb/amd64/libCwtch.deb build/linux/amd64/libCwtch-$(VERSION)-amd64.deb
endif
ifneq ($(LINUX_X_ARM),)
	mkdir -p build/linux/deb/arm64/libCwtch/DEBIAN
	mkdir -p build/linux/deb/arm64/libCwtch/usr/lib
	sed "s|VERSION|$(DEBVERSION)|g" deb/control  > build/linux/deb/arm64/libCwtch/DEBIAN/control
	cp build/linux/arm64/libCwtch.so build/linux/deb/arm64/libCwtch/usr/lib
	dpkg-deb --build build/linux/deb/arm64/libCwtch
	mv build/linux/deb/arm64/libCwtch.deb build/linux/arm64/libCwtch-$(VERSION)-arm64.deb
endif

libCwtch.x64.dylib: lib.go
	./switch-ffi.sh
	env CGO_CFLAGS="-mmacosx-version-min=10.12" CGO_LDFLAGS="-mmacosx-version-min=10.12" GOARCH=amd64 GOOS=darwin CGO_ENABLED=1 go build -trimpath -ldflags "-buildid=autobindings-$(VERSION) -X main.buildVer=autobindings-$(VERSION) -X main.buildDate=$(DATE)" -buildmode c-shared -o libCwtch.x64.dylib
	mkdir -p build/macos
	mv libCwtch.x64.dylib build/macos/

libCwtch.arm64.dylib: lib.go
	./switch-ffi.sh
	env CGO_CFLAGS="-mmacosx-version-min=10.12" CGO_LDFLAGS="-mmacosx-version-min=10.12" GOARCH=arm64 GOOS=darwin CGO_ENABLED=1 go build -trimpath -ldflags "-buildid=$(VERSION)  -X main.buildVer=$(VERSION) -X main.buildDate=$(DATE)" -buildmode c-shared -o libCwtch.arm64.dylib
	mkdir -p build/macos
	mv libCwtch.arm64.dylib build/macos/

# 16kb page size alignment from https://github.com/ProtonMail/gopenpgp/issues/300#issuecomment-2503591095
# https://developer.android.com/guide/practices/page-sizes#compile-16-kb-alignment
cwtch.aar: lib.go
	./switch-gomobile.sh
	env CGO_LDFLAGS="-O2 -s -w -Wl,-z,max-page-size=16384" gomobile bind -androidapi 21 -target android/arm,android/arm64,android/amd64 -ldflags="-buildid=$(VERSION) -X cwtch.buildVer=$(VERSION) -X cwtch.buildDate=$(DATE)" -tags safegostring -trimpath
	mkdir -p build/android
	mv cwtch.aar build/android/
	mv cwtch-sources.jar build/android/

libCwtch.dll: lib.go
	./switch-ffi.sh
	# '-Xlinker --no-insert-timestamp` sets the output dll PE timestamp header to all zeros, instead of the actual time
	# this is necessary for reproducible builds (see: https://wiki.debian.org/ReproducibleBuilds/TimestampsInPEBinaries for additional information)
	# note: the above documentation also references an ability to set an optional timestamp - this behaviour seems to no longer be supported in more recent versions of mingw32-gcc (the help docs no longer reference that functionality)
	# these flags have to be passed through to the underlying gcc process using the -extldflags option in the underlying go linker, note that the whole flag is quoted...this is necessary.
	GOOS=windows GOARCH=amd64 CGO_ENABLED=1 CC=x86_64-w64-mingw32-gcc-win32 go build -trimpath -ldflags "-buildid=$(VERSION)  -X main.buildVer=$(VERSION) -X main.buildDate=$(DATE) '-extldflags=-Xlinker --no-insert-timestamp'" -buildmode c-shared -o libCwtch.dll
	mkdir -p build/windows
	mv libCwtch.dll build/windows/
	mv libCwtch.h build/windows/

clean-autobindings:
	rm -f lib.go

clean: 
	rm -fr lib.go cwtch.aar cwtch_go.apk libCwtch.*.h libCwtch.*.so cwtch-sources.jar libCwtch.dll libCwtch.*.dylib build vendor

# iOS - for testing purposes only for now, not officially supported

ios-arm64:
	CGO_ENABLED=1 \
	GOOS=darwin \
	GOARCH=arm64 \
	SDK=iphoneos \
	CGO_CFLAGS="-fembed-bitcode" \
	CC=$(PWD)/clangwrap.sh \
	go build -buildmode=c-archive -tags ios -o $(IOS_OUT)/arm64.a .

ios-x86_64:
	CGO_ENABLED=1 \
	GOOS=darwin \
	GOARCH=amd64 \
	SDK=iphonesimulator \
	CC=$(PWD)/clangwrap.sh \
	go build -buildmode=c-archive -tags ios -o $(IOS_OUT)/x86_64.a .

ios: ios-arm64 ios-x86_64
	lipo $(IOS_OUT)/x86_64.a $(IOS_OUT)/arm64.a -create -output $(IOS_OUT)/cwtch.a
	cp $(IOS_OUT)/arm64.h $(IOS_OUT)/cwtch.h
