1

I am getting an "undefined reference" error building my Android app. I am using JNI and the NDK.

What is inexplicable to me is that it seems to be doing an NDK build during my build of the Android app itself. Yet I've already used the command line to build my Android.mk and Application.mk files to produce the desired library. All the the Android app is supposed to do is link to the library and make calls into it. But even if I'm wrong about this, I don't understand why it is complaining about errors in AILSuperFFT.o. This object file is already a part of the library I successfully built. The build process of my Android app should not know anything about AILSuperFFT.cpp or its internal calls to the Superpowered library.

Here's the Console output in Android Studio.

. . .
:app:compileDebugJavaWithJavac
:app:compileDebugJavaWithJavac - is not incremental (e.g. outputs have changed, no previous execution, etc.).
:app:compileDebugNdk
/Users/user1/Documents/AndroidStudioProjects/hello-jnicpp/app/build/intermediates/ndk/debug/obj/local/arm64-v8a/objs/hello-jni//Users/user1/Documents/AndroidStudioProjects/hello-jnicpp/app/src/main/jni/sources/AILSuperFFT.o: In function `CAILSuperFFT::LinearFFT_Quick(DSPSplitComplex*, int, int, int, FFTDirection, bool)':
/Users/user1/Documents/AndroidStudioProjects/hello-jnicpp/app/src/main/jni/sources/AILSuperFFT.cpp:139: undefined reference to `SuperpoweredFFTComplex(float*, float*, int, bool)'
/Users/user1/Documents/AndroidStudioProjects/hello-jnicpp/app/src/main/jni/sources/AILSuperFFT.cpp:139: undefined reference to `SuperpoweredFFTComplex(float*, float*, int, bool)'
/Users/user1/Documents/AndroidStudioProjects/hello-jnicpp/app/build/intermediates/ndk/debug/obj/local/arm64-v8a/objs/hello-jni//Users/user1/Documents/AndroidStudioProjects/hello-jnicpp/app/src/main/jni/sources/AILSuperFFT.o: In function `CAILSuperFFT::FFT2D(DSPSplitComplex*, int, int, FFTDirection)':
/Users/user1/Documents/AndroidStudioProjects/hello-jnicpp/app/src/main/jni/sources/AILSuperFFT.cpp:52: undefined reference to `__android_log_print'
collect2: error: ld returned 1 exit status
make: *** [/Users/user1/Documents/AndroidStudioProjects/hello-jnicpp/app/build/intermediates/ndk/debug/obj/local/arm64-v8a/libhello-jni.so] Error 1


 FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:compileDebugNdk'.
> com.android.ide.common.process.ProcessException: org.gradle.process.internal.ExecException: Process 'command '/Users/user1/Documents/NDKDev/android-ndk-r10e/ndk-build'' finished with non-zero exit value 2

BUILD FAILED

and here is very similar output in the Messages window:

:app:incrementalDebugJavaCompilationSafeguard
:app:compileDebugJavaWithJavac
:app:compileDebugJavaWithJavac - is not incremental (e.g. outputs have changed, no previous execution, etc.).
:app:compileDebugNdk
/Users/user1/Documents/AndroidStudioProjects/hello-jnicpp/app/build/intermediates/ndk/debug/obj/local/arm64-v8a/objs/hello-jni//Users/user1/Documents/AndroidStudioProjects/hello-jnicpp/app/src/main/jni/sources/AILSuperFFT.o: In function `CAILSuperFFT::LinearFFT_Quick(DSPSplitComplex*, int, int, int, FFTDirection, bool)':
/Users/user1/Documents/AndroidStudioProjects/hello-jnicpp/app/build/intermediates/ndk/debug/obj/local/arm64-v8a/objs/hello-jni//Users/user1/Documents/AndroidStudioProjects/hello-jnicpp/app/src/main/jni/sources/AILSuperFFT.o: In function `CAILSuperFFT::FFT2D(DSPSplitComplex*, int, int, FFTDirection)':
/Users/user1/Documents/AndroidStudioProjects/hello-jnicpp/app/src/main/jni/sources/AILSuperFFT.cpp
Error:(139) undefined reference to `SuperpoweredFFTComplex(float*, float*, int, bool)'
Error:(139) undefined reference to `SuperpoweredFFTComplex(float*, float*, int, bool)'
Error:(52) undefined reference to `__android_log_print'
Error:error: ld returned 1 exit status
make: *** [/Users/user1/Documents/AndroidStudioProjects/hello-jnicpp/app/build/intermediates/ndk/debug/obj/local/arm64-v8a/libhello-jni.so] Error 1
Error:Execution failed for task ':app:compileDebugNdk'.
> com.android.ide.common.process.ProcessException: org.gradle.process.internal.ExecException: Process 'command '/Users/user1/Documents/NDKDev/android-ndk-r10e/ndk-build'' finished with non-zero exit value 2
Information:BUILD FAILED
Information:Total time: 5.858 secs
Information:5 errors

Upon request below is the source code function call that is being complained about. Note that not only does this code build and link fine using ndk-build in Mac's Terminal, but the resulting library is then used without problem in a different app. I am not able to tell (yet) what is the difference between these two apps, but be aware of the dependencies here: Android app uses our proprietary library, which builds and links in the Superpowered lib. The app only knows about the interface exposed by library A, and all of this works fine in one app. (I'm constructing a test app to demonstrate a certain issue, which can't be done with the main app). Log2() returns an int.

    DSPSplitComplex data;

    data.imagp=(float *) malloc(sizeof(float)*BUF_SIZE*BUF_SIZE);
    data.realp=(float *) malloc(sizeof(float)*BUF_SIZE*BUF_SIZE);

    . . . (some code) 

    DSPSplitComplex *pBuffer = &data;

    SuperpoweredFFTComplex(&pBuffer->realp[0]), &(pBuffer->imagp[0]), Log2(length), (direction==kFFTDirection_Forward) ? true : false);
Alyoshak
  • 2,696
  • 10
  • 43
  • 70
  • You built AILSuperFFT.o. Now you have to link it and it looks like you are missing some pieces. Where is `SuperpoweredFFTComplex` implemented, is this implementation included in the link, and does the implementation exactly match the prototype that is allowing the AILSuperFFT.o to compile? Please add this information. Without it this question cannot be answered. – user4581301 Jun 30 '16 at 20:40
  • Possible duplicate of [What is an undefined reference/unresolved external symbol error and how do I fix it?](http://stackoverflow.com/questions/12573816/what-is-an-undefined-reference-unresolved-external-symbol-error-and-how-do-i-fix) – user4581301 Jun 30 '16 at 22:09
  • @user4581301 -- Yes, my implementation matches the prototype. The problem was, as suggested in my question, that the build process was trying to build (and then link) c++ source files that I had already built into a library using the command line. See answer marked correct. Thx for help. – Alyoshak Jul 01 '16 at 16:12

1 Answers1

4

An ndk-build will be attempted if you have JNI files and haven't explicitly turned off the auto-build by adding this to your build.gradle:

android {
    sourceSets.main {
        jni.srcDirs = []
    }
}

If the ndk-build you did prior to building the app worked correctly, the reason is likely that the automated ndk-build called by Gradle ignores your Android.mk file.

Francesca Nannizzi
  • 1,695
  • 13
  • 18