#
# Makefile for WDSP library
# Builds static, shared and (optionally) Java JNI libraries.
#

UNAME_S := $(shell uname -s)

PREFIX ?= /usr/local
LIBDIR ?= $(PREFIX)/lib
INCLUDEDIR ?= $(PREFIX)/include

CC ?= gcc
AR ?= ar
RANLIB ?= ranlib

CFLAGS ?= -pthread -O3 -D_GNU_SOURCE -Wno-parentheses
CPPFLAGS ?=
LDFLAGS ?=
JNI_CFLAGS ?= -std=gnu89 -Wno-implicit-function-declaration -Wno-int-conversion -Wno-incompatible-pointer-types -Wno-incompatible-pointer-types-discards-qualifiers

FFTWINCLUDE := $(shell pkg-config --cflags fftw3 2>/dev/null)
FFTWLIBS := $(shell pkg-config --libs fftw3 2>/dev/null)
FFTWLIBS_F := $(shell pkg-config --libs fftw3f 2>/dev/null)

ifeq ($(strip $(FFTWLIBS)),)
  FFTWLIBS := -lfftw3
endif
ifeq ($(strip $(FFTWLIBS_F)),)
  FFTWLIBS_F := -lfftw3f
endif

ifeq ($(UNAME_S),Darwin)
  SHARED_EXT := dylib
  SHARED_LDFLAGS := -dynamiclib
  PIC_CFLAGS :=
  NOEXECSTACK :=
  JAVA_OS_INCLUDE := darwin
else
  SHARED_EXT := so
  SHARED_LDFLAGS := -shared
  PIC_CFLAGS := -fPIC
  NOEXECSTACK := -Wl,-z,noexecstack
  JAVA_OS_INCLUDE := linux
endif

OBJDIR := obj
OUTDIR := lib

STATIC_LIB_FILE := libwdsp.a
SHARED_LIB_FILE := libwdsp.$(SHARED_EXT)
JAVA_LIB_FILE   := libwdspj.$(SHARED_EXT)

STATIC_LIB := $(OUTDIR)/$(STATIC_LIB_FILE)
SHARED_LIB := $(OUTDIR)/$(SHARED_LIB_FILE)
JAVA_LIB   := $(OUTDIR)/$(JAVA_LIB_FILE)

ifeq ($(UNAME_S),Darwin)
  SHARED_LDFLAGS += -install_name $(LIBDIR)/$(SHARED_LIB_FILE)
  JAVA_SHARED_LDFLAGS := -dynamiclib -install_name $(LIBDIR)/$(JAVA_LIB_FILE)
else
  JAVA_SHARED_LDFLAGS := $(SHARED_LDFLAGS)
endif

JAVA_HOME ?= $(shell /usr/libexec/java_home 2>/dev/null || sh -c 'J=$$(command -v javac 2>/dev/null); if [ -n "$$J" ]; then dirname "$$(dirname "$$(readlink -f "$$J")")"; fi')
JAVA_INCLUDE := -I$(JAVA_HOME)/include -I$(JAVA_HOME)/include/$(JAVA_OS_INCLUDE)

ifneq ($(NR34LIB),ON)
  CPPFLAGS += -I third_party/rnnoise/include -I third_party/libspecbleach/include
  NR34_DEPS := third_party/rnnoise/librnnoise.a third_party/libspecbleach/libspecbleach.a
  NR34_LIBS := $(NR34_DEPS) $(FFTWLIBS_F)
else
  NR34_DEPS :=
  NR34_LIBS :=
endif

COMMON_LIBS := $(FFTWLIBS) -lpthread -lm

COMPILE = $(CC) $(CPPFLAGS) $(CFLAGS) $(PIC_CFLAGS) $(FFTWINCLUDE)

SOURCES = amd.c \
ammod.c \
amsq.c \
analyzer.c \
anf.c \
anr.c \
apfshadow.c \
bandpass.c \
calcc.c \
calculus.c \
cblock.c \
cfcomp.c \
cfir.c \
channel.c \
cmath.c \
compress.c \
delay.c \
dexp.c \
div.c \
doublepole.c \
eer.c \
emnr.c \
emph.c \
eq.c \
fcurve.c \
FDnoiseIQ.c \
fir.c \
firmin.c \
fmd.c \
fmmod.c \
fmsq.c \
gain.c \
gaussian.c \
gen.c \
icfir.c \
iir.c \
impulse_cache.c \
iobuffs.c \
iqc.c \
linux_port.c \
lmath.c \
main.c \
matchedCW.c \
meter.c \
meterlog10.c \
nbp.c \
nob.c \
nobII.c \
osctrl.c \
patchpanel.c \
resample.c \
rmatch.c \
rnnr.c \
RXA.c \
sbnr.c \
sender.c \
shift.c \
siphon.c \
slew.c \
snb.c \
ssql.c \
syncbuffs.c \
TXA.c \
utilities.c \
varsamp.c \
version.c \
wcpAGC.c \
wisdom.c \
zetaHat.c

OBJS      = $(addprefix $(OBJDIR)/, $(SOURCES:.c=.o))

JAVA_SOURCES = org_openhpsdr_dsp_Wdsp.c
JAVA_OBJS    = $(addprefix $(OBJDIR)/, $(JAVA_SOURCES:.c=.o))
JAVA_CLASS   = java/org/openhpsdr/dsp/Wdsp.java
JAVA_BUILD_DIR = java/build

.PHONY: all static shared java java-classes android install install_java install-dirs clean release

all: static shared java

static: $(STATIC_LIB)

shared: $(SHARED_LIB)

java:
ifeq ($(strip $(JAVA_HOME)),)
	@echo "Skipping Java build: JAVA_HOME is not set and javac was not found in PATH"
else
	@$(MAKE) $(JAVA_LIB) java-classes
endif

android:
	$(MAKE) -f Makefile.android all

$(OUTDIR) $(OBJDIR):
	mkdir -p $@

$(STATIC_LIB): $(OBJS) | $(OUTDIR)
	$(AR) rv $@ $(OBJS)
	$(RANLIB) $@

$(SHARED_LIB): $(OBJS) $(NR34_DEPS) | $(OUTDIR)
	$(CC) $(SHARED_LDFLAGS) $(NOEXECSTACK) $(LDFLAGS) -o $@ $(OBJS) $(NR34_LIBS) $(COMMON_LIBS)

$(JAVA_LIB): $(JAVA_OBJS) $(SHARED_LIB) | $(OUTDIR)
	$(CC) $(JAVA_SHARED_LDFLAGS) $(NOEXECSTACK) $(LDFLAGS) -o $@ $(JAVA_OBJS) -L$(OUTDIR) -lwdsp

java-classes: $(JAVA_CLASS)
	@mkdir -p $(JAVA_BUILD_DIR)
	javac -d $(JAVA_BUILD_DIR) $(JAVA_CLASS)

third_party/rnnoise/librnnoise.a:
	$(MAKE) -C third_party/rnnoise CFLAGS="$(CFLAGS) $(PIC_CFLAGS) -Iinclude -Isrc"

third_party/libspecbleach/libspecbleach.a:
	$(MAKE) -C third_party/libspecbleach CFLAGS="$(CFLAGS) $(PIC_CFLAGS) $(shell pkg-config --cflags fftw3f 2>/dev/null)"

$(OBJDIR)/%.o: %.c | $(OBJDIR)
	$(COMPILE) -c -o $@ $<

$(OBJDIR)/org_openhpsdr_dsp_Wdsp.o: org_openhpsdr_dsp_Wdsp.c org_openhpsdr_dsp_Wdsp.h | $(OBJDIR)
	@test -n "$(JAVA_HOME)" || (echo "JAVA_HOME is required to build JNI object org_openhpsdr_dsp_Wdsp.o"; exit 2)
	$(CC) $(CPPFLAGS) $(CFLAGS) $(JNI_CFLAGS) $(PIC_CFLAGS) $(FFTWINCLUDE) $(JAVA_INCLUDE) -c -o $@ $<

install-dirs:
	mkdir -p $(LIBDIR) $(INCLUDEDIR)

install: $(STATIC_LIB) $(SHARED_LIB) install-dirs
	cp wdsp.h $(INCLUDEDIR)
	cp $(STATIC_LIB) $(LIBDIR)
	cp $(SHARED_LIB) $(LIBDIR)
ifeq ($(UNAME_S),Darwin)
	/usr/bin/install_name_tool -id $(LIBDIR)/$(SHARED_LIB_FILE) $(LIBDIR)/$(SHARED_LIB_FILE)
else
	ldconfig || :
endif

install_java: $(JAVA_LIB) install-dirs
	cp $(JAVA_LIB) $(LIBDIR)

release: $(SHARED_LIB)
	cp $(SHARED_LIB) ../pihpsdr/release/pihpsdr

clean:
	-rm -rf $(OBJDIR) $(OUTDIR)
	-rm -rf $(JAVA_BUILD_DIR)
	-$(MAKE) -C third_party/rnnoise clean
	-$(MAKE) -C third_party/libspecbleach clean
