Remove hardcoded /home/vladimir and /opt paths. NDK is now resolved via ANDROID_NDK_HOME, ANDROID_SDK_ROOT/ANDROID_HOME, or the default SDK location for Linux/macOS (latest version picked automatically). javac is resolved via JAVA_HOME, system PATH, or Android Studio JBR on Linux/macOS. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
350 lines
12 KiB
Makefile
350 lines
12 KiB
Makefile
# Android cross-build for WDSP and JNI bridge
|
|
# Usage:
|
|
# make android
|
|
# make -f Makefile.android all
|
|
# Optional overrides:
|
|
# ANDROID_NDK=/path/to/ndk ANDROID_API=24 ANDROID_ABIS="arm64-v8a x86_64"
|
|
#
|
|
# FFTW source is downloaded and extracted automatically.
|
|
# Override FFTW_SRC to use an existing directory.
|
|
|
|
# Auto-detect NDK path (can always be overridden by setting ANDROID_NDK explicitly):
|
|
# 1. ANDROID_NDK_HOME environment variable
|
|
# 2. Latest NDK under ANDROID_SDK_ROOT or ANDROID_HOME
|
|
# 3. Default SDK locations: ~/Android/Sdk (Linux) or ~/Library/Android/sdk (macOS)
|
|
ifeq ($(origin ANDROID_NDK),undefined)
|
|
ifdef ANDROID_NDK_HOME
|
|
ANDROID_NDK := $(ANDROID_NDK_HOME)
|
|
else
|
|
_SDK_ROOT := $(or $(ANDROID_SDK_ROOT),$(ANDROID_HOME),\
|
|
$(wildcard $(HOME)/Android/Sdk),\
|
|
$(wildcard $(HOME)/Library/Android/sdk))
|
|
ifdef _SDK_ROOT
|
|
ANDROID_NDK := $(lastword $(sort $(wildcard $(_SDK_ROOT)/ndk/*)))
|
|
endif
|
|
endif
|
|
endif
|
|
ifndef ANDROID_NDK
|
|
$(error Cannot find Android NDK. Set ANDROID_NDK, ANDROID_NDK_HOME, ANDROID_SDK_ROOT, or ANDROID_HOME)
|
|
endif
|
|
ANDROID_API ?= 24
|
|
ANDROID_ABIS ?= arm64-v8a armeabi-v7a x86_64
|
|
ANDROID_HOST_TAG ?= $(shell uname -s | tr '[:upper:]' '[:lower:]' | sed 's/darwin/darwin/;s/linux/linux/')-$(shell uname -m | sed 's/aarch64/arm64/;s/x86_64/x86_64/')
|
|
|
|
# Auto-detect javac: JAVA_HOME > system PATH > Android Studio JBR (Linux/macOS)
|
|
_JAVAC_CANDIDATES := \
|
|
$(if $(JAVA_HOME),$(wildcard $(JAVA_HOME)/bin/javac)) \
|
|
$(shell command -v javac 2>/dev/null) \
|
|
$(wildcard /opt/android-studio/jbr/bin/javac) \
|
|
$(wildcard /Applications/Android\ Studio.app/Contents/jbr/Contents/Home/bin/javac)
|
|
JAVAC ?= $(firstword $(_JAVAC_CANDIDATES))
|
|
|
|
TOOLCHAIN := $(ANDROID_NDK)/toolchains/llvm/prebuilt/$(ANDROID_HOST_TAG)
|
|
|
|
COMMON_CFLAGS ?= -O3 -D_GNU_SOURCE -Wno-parentheses -fPIC
|
|
COMMON_CPPFLAGS ?= -I. -I third_party/rnnoise/include -I third_party/libspecbleach/include
|
|
ANDROID_JNI_CFLAGS ?= -std=gnu89 -Wno-implicit-function-declaration -Wno-int-conversion \
|
|
-Wno-incompatible-pointer-types -Wno-incompatible-pointer-types-discards-qualifiers
|
|
|
|
FFTW_VERSION := 3.3.11
|
|
FFTW_TAR := fftw-$(FFTW_VERSION).tar.gz
|
|
FFTW_URL := https://fftw.org/pub/fftw/$(FFTW_TAR)
|
|
FFTW_SRC ?= third_party/fftw-$(FFTW_VERSION)
|
|
FFTW_MAKEJOBS ?= $(shell nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null || echo 4)
|
|
|
|
WDSP_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
|
|
|
|
RNNOISE_SOURCES = \
|
|
third_party/rnnoise/src/denoise.c \
|
|
third_party/rnnoise/src/celt_lpc.c \
|
|
third_party/rnnoise/src/kiss_fft.c \
|
|
third_party/rnnoise/src/nnet.c \
|
|
third_party/rnnoise/src/nnet_default.c \
|
|
third_party/rnnoise/src/parse_lpcnet_weights.c \
|
|
third_party/rnnoise/src/pitch.c \
|
|
third_party/rnnoise/src/rnn.c \
|
|
third_party/rnnoise/src/rnnoise_data.c \
|
|
third_party/rnnoise/src/rnnoise_data_1.c \
|
|
third_party/rnnoise/src/rnnoise_data_2.c \
|
|
third_party/rnnoise/src/rnnoise_data_3.c \
|
|
third_party/rnnoise/src/rnnoise_data_4.c \
|
|
third_party/rnnoise/src/rnnoise_data_5.c \
|
|
third_party/rnnoise/src/rnnoise_data_6.c \
|
|
third_party/rnnoise/src/rnnoise_tables.c
|
|
|
|
SPECBLEACH_SOURCES = \
|
|
third_party/libspecbleach/src/processors/specbleach_adenoiser.c \
|
|
third_party/libspecbleach/src/processors/specbleach_denoiser.c \
|
|
third_party/libspecbleach/src/processors/adaptivedenoiser/adaptive_denoiser.c \
|
|
third_party/libspecbleach/src/shared/gain_estimation/gain_estimators.c \
|
|
third_party/libspecbleach/src/shared/noise_estimation/adaptive_noise_estimator.c \
|
|
third_party/libspecbleach/src/shared/pre_estimation/absolute_hearing_thresholds.c \
|
|
third_party/libspecbleach/src/shared/pre_estimation/critical_bands.c \
|
|
third_party/libspecbleach/src/shared/pre_estimation/masking_estimator.c \
|
|
third_party/libspecbleach/src/shared/pre_estimation/noise_scaling_criterias.c \
|
|
third_party/libspecbleach/src/shared/pre_estimation/spectral_smoother.c \
|
|
third_party/libspecbleach/src/shared/pre_estimation/transient_detector.c \
|
|
third_party/libspecbleach/src/shared/post_estimation/noise_floor_manager.c \
|
|
third_party/libspecbleach/src/shared/post_estimation/postfilter.c \
|
|
third_party/libspecbleach/src/shared/post_estimation/spectral_whitening.c \
|
|
third_party/libspecbleach/src/shared/utils/denoise_mixer.c \
|
|
third_party/libspecbleach/src/shared/utils/general_utils.c \
|
|
third_party/libspecbleach/src/shared/utils/spectral_features.c \
|
|
third_party/libspecbleach/src/shared/utils/spectral_utils.c \
|
|
third_party/libspecbleach/src/shared/stft/stft_processor.c \
|
|
third_party/libspecbleach/src/shared/stft/fft_transform.c \
|
|
third_party/libspecbleach/src/shared/stft/stft_buffer.c \
|
|
third_party/libspecbleach/src/shared/stft/stft_windows.c
|
|
|
|
ALL_C_SOURCES = $(WDSP_SOURCES) $(RNNOISE_SOURCES) $(SPECBLEACH_SOURCES)
|
|
|
|
JNI_SOURCE = org_openhpsdr_dsp_Wdsp.c
|
|
JAVA_SOURCE = java/org/openhpsdr/dsp/Wdsp.java
|
|
|
|
ANDROID_OBJ_ROOT := obj/android
|
|
ANDROID_LIB_ROOT := lib/android
|
|
ANDROID_JAVA_OUT := lib/android/java
|
|
|
|
.PHONY: all clean distclean java-classes
|
|
|
|
all: $(FFTW_SRC)/configure \
|
|
$(foreach abi,$(ANDROID_ABIS),\
|
|
$(ANDROID_LIB_ROOT)/$(abi)/libfftw3.so \
|
|
$(ANDROID_LIB_ROOT)/$(abi)/libfftw3f.so \
|
|
$(ANDROID_LIB_ROOT)/$(abi)/libwdsp.so \
|
|
$(ANDROID_LIB_ROOT)/$(abi)/libwdspj.so) \
|
|
java-classes
|
|
|
|
# ── Автоматическое получение FFTW ────────────────────────────────────────────
|
|
|
|
third_party/$(FFTW_TAR):
|
|
mkdir -p third_party
|
|
@echo ">>> Скачиваем FFTW $(FFTW_VERSION)..."
|
|
@if command -v wget >/dev/null 2>&1; then \
|
|
wget -q --show-progress -O $@ "$(FFTW_URL)"; \
|
|
else \
|
|
curl -L --progress-bar -o $@ "$(FFTW_URL)"; \
|
|
fi
|
|
|
|
$(FFTW_SRC)/configure: third_party/$(FFTW_TAR)
|
|
@echo ">>> Распаковываем FFTW..."
|
|
tar xf $< -C third_party/
|
|
@touch $@
|
|
|
|
# abi_target: compiler triple for NDK clang wrapper
|
|
define abi_target
|
|
$(if $(filter $(1),arm64-v8a),aarch64-linux-android,\
|
|
$(if $(filter $(1),armeabi-v7a),armv7a-linux-androideabi,\
|
|
$(if $(filter $(1),x86_64),x86_64-linux-android,unsupported)))
|
|
endef
|
|
|
|
# fftw_host: --host value for FFTW configure (autoconf canonical names)
|
|
define fftw_host
|
|
$(if $(filter $(1),arm64-v8a),aarch64-linux-android,\
|
|
$(if $(filter $(1),armeabi-v7a),arm-linux-androideabi,\
|
|
$(if $(filter $(1),x86_64),x86_64-linux-android,$(1))))
|
|
endef
|
|
|
|
# abi_cflags: extra CFLAGS per ABI
|
|
define abi_cflags
|
|
$(if $(filter $(1),armeabi-v7a),-march=armv7-a -mfloat-abi=softfp -mfpu=neon,)
|
|
endef
|
|
|
|
# fftw3 (double) SIMD flags per ABI
|
|
define fftw_simd
|
|
$(if $(filter $(1),x86_64),--enable-sse2,)
|
|
endef
|
|
|
|
# fftw3f (float) SIMD flags per ABI
|
|
define fftwf_simd
|
|
$(if $(filter $(1),arm64-v8a),--enable-neon,\
|
|
$(if $(filter $(1),armeabi-v7a),--enable-neon,\
|
|
$(if $(filter $(1),x86_64),--enable-sse --enable-sse2,)))
|
|
endef
|
|
|
|
# -----------------------------------------------------------------------
|
|
# Per-ABI rules
|
|
# -----------------------------------------------------------------------
|
|
define make_abi_rules
|
|
|
|
ABI_$(1)_TARGET := $(call abi_target,$(1))
|
|
ABI_$(1)_CC := $(TOOLCHAIN)/bin/$$(ABI_$(1)_TARGET)$(ANDROID_API)-clang
|
|
ABI_$(1)_OBJDIR := $(ANDROID_OBJ_ROOT)/$(1)
|
|
ABI_$(1)_LIBDIR := $(ANDROID_LIB_ROOT)/$(1)
|
|
ABI_$(1)_CFLAGS := $(COMMON_CFLAGS) $(call abi_cflags,$(1))
|
|
|
|
# FFTW install prefixes (inside obj tree)
|
|
ABI_$(1)_FFTW_PREFIX := $$(ABI_$(1)_OBJDIR)/fftw-install
|
|
ABI_$(1)_FFTWF_PREFIX := $$(ABI_$(1)_OBJDIR)/fftwf-install
|
|
|
|
# Stamp files (avoid re-running configure+make on every build)
|
|
ABI_$(1)_FFTW_STAMP := $$(ABI_$(1)_FFTW_PREFIX)/.built
|
|
ABI_$(1)_FFTWF_STAMP := $$(ABI_$(1)_FFTWF_PREFIX)/.built
|
|
|
|
ABI_$(1)_CPPFLAGS := $(COMMON_CPPFLAGS) \
|
|
-I third_party/rnnoise/src -I third_party/libspecbleach/include -I third_party/libspecbleach/src -I third_party/libspecbleach/src/shared \
|
|
-I$$(ABI_$(1)_FFTW_PREFIX)/include
|
|
|
|
ABI_$(1)_WDSP_OBJS := $$(patsubst %.c,$$(ABI_$(1)_OBJDIR)/%.o,$$(ALL_C_SOURCES))
|
|
ABI_$(1)_JNI_OBJ := $$(ABI_$(1)_OBJDIR)/$(JNI_SOURCE:.c=.o)
|
|
|
|
# --- Build fftw3 (double) ---
|
|
$$(ABI_$(1)_FFTW_STAMP): $(FFTW_SRC)/configure
|
|
@mkdir -p $$(ABI_$(1)_OBJDIR)/fftw-build $$(ABI_$(1)_FFTW_PREFIX)
|
|
cd $$(ABI_$(1)_OBJDIR)/fftw-build && \
|
|
$(abspath $(FFTW_SRC))/configure \
|
|
--build=$(shell uname -m)-linux-gnu \
|
|
--host=$(strip $(call fftw_host,$(1))) \
|
|
CC="$$(ABI_$(1)_CC)" \
|
|
CFLAGS="-fPIC" \
|
|
--prefix=$(abspath $$(ABI_$(1)_FFTW_PREFIX)) \
|
|
--enable-static --disable-shared --disable-fortran \
|
|
$(call fftw_simd,$(1)) && \
|
|
$(MAKE) -j$(FFTW_MAKEJOBS) install
|
|
@touch $$@
|
|
|
|
# --- Build fftw3f (float/single) ---
|
|
$$(ABI_$(1)_FFTWF_STAMP): $(FFTW_SRC)/configure
|
|
@mkdir -p $$(ABI_$(1)_OBJDIR)/fftwf-build $$(ABI_$(1)_FFTWF_PREFIX)
|
|
cd $$(ABI_$(1)_OBJDIR)/fftwf-build && \
|
|
$(abspath $(FFTW_SRC))/configure \
|
|
--build=$(shell uname -m)-linux-gnu \
|
|
--host=$(strip $(call fftw_host,$(1))) \
|
|
CC="$$(ABI_$(1)_CC)" \
|
|
CFLAGS="-fPIC" \
|
|
--prefix=$(abspath $$(ABI_$(1)_FFTWF_PREFIX)) \
|
|
--enable-static --disable-shared --disable-fortran \
|
|
--enable-float \
|
|
$(call fftwf_simd,$(1)) && \
|
|
$(MAKE) -j$(FFTW_MAKEJOBS) install
|
|
@touch $$@
|
|
|
|
# --- Shared fftw3.so / fftw3f.so for packaging alongside libwdsp.so ---
|
|
$$(ABI_$(1)_LIBDIR)/libfftw3.so: $$(ABI_$(1)_FFTW_STAMP)
|
|
@mkdir -p $$(@D)
|
|
$$(ABI_$(1)_CC) -shared -Wl,-soname,libfftw3.so \
|
|
-Wl,--whole-archive $$(ABI_$(1)_FFTW_PREFIX)/lib/libfftw3.a -Wl,--no-whole-archive \
|
|
-lm -o $$@
|
|
|
|
$$(ABI_$(1)_LIBDIR)/libfftw3f.so: $$(ABI_$(1)_FFTWF_STAMP)
|
|
@mkdir -p $$(@D)
|
|
$$(ABI_$(1)_CC) -shared -Wl,-soname,libfftw3f.so \
|
|
-Wl,--whole-archive $$(ABI_$(1)_FFTWF_PREFIX)/lib/libfftw3f.a -Wl,--no-whole-archive \
|
|
-lm -o $$@
|
|
|
|
# --- Compile WDSP + rnnoise + specbleach sources ---
|
|
$$(ABI_$(1)_OBJDIR)/%.o: %.c | $$(ABI_$(1)_FFTW_STAMP) $$(ABI_$(1)_FFTWF_STAMP)
|
|
@mkdir -p $$(@D)
|
|
$$(ABI_$(1)_CC) $$(ABI_$(1)_CPPFLAGS) $$(ABI_$(1)_CFLAGS) -c -o $$@ $$<
|
|
|
|
# --- Build libwdsp.so (statically links fftw) ---
|
|
$$(ABI_$(1)_LIBDIR)/libwdsp.so: $$(ABI_$(1)_WDSP_OBJS) $$(ABI_$(1)_FFTW_STAMP) $$(ABI_$(1)_FFTWF_STAMP)
|
|
@mkdir -p $$(@D)
|
|
$$(ABI_$(1)_CC) -shared -Wl,-soname,libwdsp.so -o $$@ \
|
|
$$(ABI_$(1)_WDSP_OBJS) \
|
|
$$(ABI_$(1)_FFTW_PREFIX)/lib/libfftw3.a \
|
|
$$(ABI_$(1)_FFTWF_PREFIX)/lib/libfftw3f.a \
|
|
-lm -llog
|
|
|
|
# --- Compile JNI bridge ---
|
|
$$(ABI_$(1)_JNI_OBJ): $(JNI_SOURCE) org_openhpsdr_dsp_Wdsp.h | $$(ABI_$(1)_FFTW_STAMP)
|
|
@mkdir -p $$(@D)
|
|
$$(ABI_$(1)_CC) $$(ABI_$(1)_CPPFLAGS) $$(ABI_$(1)_CFLAGS) $(ANDROID_JNI_CFLAGS) \
|
|
-I$(TOOLCHAIN)/sysroot/usr/include -c -o $$@ $$<
|
|
|
|
# --- Build libwdspj.so ---
|
|
$$(ABI_$(1)_LIBDIR)/libwdspj.so: $$(ABI_$(1)_JNI_OBJ) $$(ABI_$(1)_LIBDIR)/libwdsp.so
|
|
@mkdir -p $$(@D)
|
|
$$(ABI_$(1)_CC) -shared -Wl,-soname,libwdspj.so -o $$@ \
|
|
$$(ABI_$(1)_JNI_OBJ) \
|
|
-L$$(ABI_$(1)_LIBDIR) -lwdsp -llog
|
|
|
|
endef
|
|
|
|
$(foreach abi,$(ANDROID_ABIS),$(eval $(call make_abi_rules,$(abi))))
|
|
|
|
# -----------------------------------------------------------------------
|
|
|
|
java-classes: $(JAVA_SOURCE)
|
|
@if [ -x "$(JAVAC)" ]; then \
|
|
mkdir -p "$(ANDROID_JAVA_OUT)"; \
|
|
"$(JAVAC)" -d "$(ANDROID_JAVA_OUT)" "$(JAVA_SOURCE)"; \
|
|
echo "Java classes built in $(ANDROID_JAVA_OUT)"; \
|
|
else \
|
|
echo "Skipping Java class build: javac not found at $(JAVAC)"; \
|
|
fi
|
|
|
|
clean:
|
|
rm -rf $(ANDROID_OBJ_ROOT) $(ANDROID_LIB_ROOT)
|
|
|
|
distclean: clean
|
|
-rm -rf $(FFTW_SRC) third_party/$(FFTW_TAR)
|