Search code examples
android-ndkundefined-referenceopus

Undefined Reference issues incorporating Opus as a shared library in an Android project


After many hours searching through similar problems, and trying many alternatives, with no resolution. I bring this question to the brilliant minds here at StackOverflow. I've been trying to incorporate Opus audio codec into my Android project, but I keep getting Undefined Reference errors.

The Typical problems mentioned in other posts don't seem to apply. The names and paths seem correct, all header files from Opus are included, and my function headers were generated by Javah.

structure is:
jni--(dir)
--Android.mk
--opus_jni.c
--com_ether_viz_OpusCodec.h
--opus----(dir)
----Android.mk
----include----(dir)
----src--------(dir)

top level Android.mk:

JNIPATH := $(call my-dir)
include $(call all-subdir-makefiles)
LOCAL_PATH := $(JNIPATH)
include $(CLEAR_VARS)    
LOCAL_MODULE:=opus_jni
LOCAL_SRC_FILES:= opus_jni.c
LOCAL_SHARED_LIBRARIES := opus
include $(BUILD_SHARED_LIBRARY)

Android.mk in opus directory:

    LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

MY_MODULE_DIR       := opus

LOCAL_MODULE        := opus
LOCAL_SRC_FILES     := \
$(subst $(ROOT_DIR)/$(MY_MODULE_DIR)/,,$(wildcard $(ROOT_DIR)/$(MY_MODULE_DIR)/src/*.c*)) \
$(subst $(ROOT_DIR)/$(MY_MODULE_DIR)/,,$(wildcard $(ROOT_DIR)/$(MY_MODULE_DIR)/celt/*.c*)) \
$(subst $(ROOT_DIR)/$(MY_MODULE_DIR)/,,$(wildcard $(ROOT_DIR)/$(MY_MODULE_DIR)/silk/*.c*)) \
$(subst $(ROOT_DIR)/$(MY_MODULE_DIR)/,,$(wildcard $(ROOT_DIR)/$(MY_MODULE_DIR)/silk/fixed/*.c*))
LOCAL_LDLIBS        := -lm -llog
LOCAL_C_INCLUDES    := \
$(ROOT_DIR)/$(MY_MODULE_DIR)/include \
$(ROOT_DIR)/$(MY_MODULE_DIR)/silk \
$(ROOT_DIR)/$(MY_MODULE_DIR)/silk/fixed \
$(ROOT_DIR)/$(MY_MODULE_DIR)/celt
LOCAL_CFLAGS        := -DNULL=0 -DSOCKLEN_T=socklen_t -DLOCALE_NOT_USED -D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64
LOCAL_CFLAGS    += -Drestrict='' -D__EMX__ -DOPUS_BUILD -DFIXED_POINT -DUSE_ALLOCA -DHAVE_LRINT -DHAVE_LRINTF -O3 -fno-math-errno
LOCAL_CPPFLAGS      := -DBSD=1 
LOCAL_CPPFLAGS          += -ffast-math -O3 -funroll-loops

LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)


include $(BUILD_SHARED_LIBRARY)

Console output:

/Users/ethervision/Documents/AAAA_New/Android/android-ndk-r10b/ndk-build all 
[armeabi] SharedLibrary  : libopus.so
[armeabi] Install        : libopus.so => libs/armeabi/libopus.so
[armeabi] Compile thumb  : opus_jni <= opus_jni.c
[armeabi] SharedLibrary  : libopus_jni.so
/Users/ethervision/Documents/AAAA_New/Android/android-ndk-r10b/toolchains/arm-linux-androideabi-
4.6/prebuilt/darwin-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-
androideabi/bin/ld: ./obj/local/armeabi/objs/opus_jni/opus_jni.o: in function
Java_com_plworld_partyline_OpusCodec_initOpusDecoder:jni/opus_jni.c:30: 
error: undefined reference to 'opus_decoder_create'

I'm fairly new to the NDK, so I'm probably just missing something simple, but I have tried dozens of variations I found here and on other sites.


Solution

  • I created this unified Android.mk file before getting the reply from @ph0b who was almost certainly correct. I post it here for anyone else dealing with the same library.

    ROOT := $(call my-dir)
    LOCAL_PATH := $(call my-dir)
    
    include $(CLEAR_VARS)
    
    LOCAL_MODULE    := opus_jni
    LOCAL_SRC_FILES := opus_jni.c
    LOCAL_LDLIBS := -llog
    LOCAL_SHARED_LIBRARIES := opus
    include $(BUILD_SHARED_LIBRARY)
    
    LOCAL_PATH := $(ROOT)/opus
    include $(CLEAR_VARS)
    LOCAL_MODULE := opus
    LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
    LOCAL_C_INCLUDES := $(LOCAL_PATH)/include $(LOCAL_PATH)/celt $(LOCAL_PATH)/silk $(LOCAL_PATH)/silk/fixed
    LOCAL_SRC_FILES := celt/bands.c celt/celt.c \
    celt/cwrs.c celt/entcode.c \
    celt/entdec.c celt/entenc.c \
    celt/celt_decoder.c celt/celt_encoder.c \
    celt/kiss_fft.c celt/laplace.c \
    celt/mathops.c celt/mdct.c \
    celt/modes.c celt/pitch.c \
    celt/celt_lpc.c celt/quant_bands.c \
    celt/rate.c celt/vq.c \
    silk/CNG.c silk/code_signs.c \
    silk/init_decoder.c silk/decode_core.c \
    silk/decode_frame.c silk/decode_parameters.c \
    silk/decode_indices.c silk/decode_pulses.c \
    silk/decoder_set_fs.c silk/dec_API.c \
    silk/enc_API.c silk/encode_indices.c \
    silk/encode_pulses.c silk/gain_quant.c \
    silk/interpolate.c silk/LP_variable_cutoff.c \
    silk/NLSF_decode.c silk/NSQ.c \
    silk/NSQ_del_dec.c silk/PLC.c \
    silk/shell_coder.c silk/tables_gain.c \
    silk/tables_LTP.c silk/tables_NLSF_CB_NB_MB.c \
    silk/tables_NLSF_CB_WB.c silk/tables_other.c \
    silk/tables_pitch_lag.c silk/tables_pulses_per_block.c \
    silk/VAD.c silk/control_audio_bandwidth.c \
    silk/quant_LTP_gains.c silk/VQ_WMat_EC.c \
    silk/HP_variable_cutoff.c silk/NLSF_encode.c \
    silk/NLSF_VQ.c silk/NLSF_unpack.c \
    silk/NLSF_del_dec_quant.c silk/process_NLSFs.c \
    silk/stereo_LR_to_MS.c silk/stereo_MS_to_LR.c \
    silk/check_control_input.c silk/control_SNR.c \
    silk/init_encoder.c silk/control_codec.c \
    silk/A2NLSF.c silk/ana_filt_bank_1.c \
    silk/biquad_alt.c silk/bwexpander_32.c \
    silk/bwexpander.c silk/debug.c \
    silk/decode_pitch.c silk/inner_prod_aligned.c \
    silk/lin2log.c silk/log2lin.c \
    silk/LPC_analysis_filter.c silk/LPC_inv_pred_gain.c \
    silk/table_LSF_cos.c silk/NLSF2A.c \
    silk/NLSF_stabilize.c silk/NLSF_VQ_weights_laroia.c \
    silk/pitch_est_tables.c silk/resampler.c \
    silk/resampler_down2_3.c silk/resampler_down2.c \
    silk/resampler_private_AR2.c silk/resampler_private_down_FIR.c \
    silk/resampler_private_IIR_FIR.c silk/resampler_private_up2_HQ.c \
    silk/resampler_rom.c silk/sigm_Q15.c \
    silk/sort.c silk/sum_sqr_shift.c \
    silk/stereo_decode_pred.c silk/stereo_encode_pred.c \
    silk/stereo_find_predictor.c silk/stereo_quant_pred.c \
    silk/fixed/LTP_analysis_filter_FIX.c silk/fixed/LTP_scale_ctrl_FIX.c \
    silk/fixed/corrMatrix_FIX.c silk/fixed/encode_frame_FIX.c \
    silk/fixed/find_LPC_FIX.c silk/fixed/find_LTP_FIX.c \
    silk/fixed/find_pitch_lags_FIX.c silk/fixed/find_pred_coefs_FIX.c \
    silk/fixed/noise_shape_analysis_FIX.c silk/fixed/prefilter_FIX.c \
    silk/fixed/process_gains_FIX.c silk/fixed/regularize_correlations_FIX.c \
    silk/fixed/residual_energy16_FIX.c silk/fixed/residual_energy_FIX.c \
    silk/fixed/solve_LS_FIX.c silk/fixed/warped_autocorrelation_FIX.c \
    silk/fixed/apply_sine_window_FIX.c silk/fixed/autocorr_FIX.c \
    silk/fixed/burg_modified_FIX.c silk/fixed/k2a_FIX.c \
    silk/fixed/k2a_Q16_FIX.c silk/fixed/pitch_analysis_core_FIX.c \
    silk/fixed/vector_ops_FIX.c silk/fixed/schur64_FIX.c \
    silk/fixed/schur_FIX.c src/opus.c \
    src/opus_decoder.c src/opus_encoder.c \
    src/opus_multistream.c src/repacketizer.c 
    LOCAL_CFLAGS    := -Drestrict='' -D__EMX__ -DOPUS_BUILD -DFIXED_POINT -DDISABLE_FLOAT_API -DUSE_ALLOCA -DHAVE_LRINT -DHAVE_LRINTF -O3 -fno-math-errno
    include $(BUILD_SHARED_LIBRARY)