title: Android NDK - Gradle Build Error
body: <p>I've successfully compiled the SoundTouch library and copied the resulting files into my project's <code>libs</code> folder.</p>
  
  <p><a href="https://i.stack.imgur.com/3U5Bl.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/3U5Bl.png" alt="library"></a></p>
  
  <p>within each one of this folders there is a <code>libsoundtouch.so</code> file.</p>
  
  <p>in my project's <code>jni</code> folder I have the following files:</p>
  
  <ul>
  <li>Android.mk</li>
  <li>Application.mk</li>
  <li>soundtouch-jni.cpp</li>
  </ul>
  
  <p>my Android.mk looks like this:</p>
  
  <pre><code>LOCAL_PATH := $(call my-dir)
  
  include $(CLEAR_VARS)
  
  # *** Remember: Change -O0 into -O2 in add-applications.mk ***
  
  LOCAL_MODULE    := soundtouch
  LOCAL_SRC_FILES := soundtouch-jni.cpp ../../SoundTouch/AAFilter.cpp  ../../SoundTouch/FIFOSampleBuffer.cpp \
                  ../../SoundTouch/FIRFilter.cpp ../../SoundTouch/cpu_detect_x86.cpp \
                  ../../SoundTouch/sse_optimized.cpp ../../SoundStretch/WavFile.cpp \
                  ../../SoundTouch/RateTransposer.cpp ../../SoundTouch/SoundTouch.cpp \
                  ../../SoundTouch/InterpolateCubic.cpp ../../SoundTouch/InterpolateLinear.cpp \
                  ../../SoundTouch/InterpolateShannon.cpp ../../SoundTouch/TDStretch.cpp \
                  ../../SoundTouch/BPMDetect.cpp ../../SoundTouch/PeakFinder.cpp 
  
  # for native audio
  LOCAL_SHARED_LIBRARIES += -lgcc 
  # --whole-archive -lgcc 
  # for logging
  LOCAL_LDLIBS    += -llog
  # for native asset manager
  #LOCAL_LDLIBS    += -landroid
  
  # Custom Flags: 
  # -fvisibility=hidden : don't export all symbols
  LOCAL_CFLAGS += -fvisibility=hidden -I ../../../include -fdata-sections -ffunction-sections
  
  # OpenMP mode : enable these flags to enable using OpenMP for parallel computation 
  #LOCAL_CFLAGS += -fopenmp
  #LOCAL_LDFLAGS += -fopenmp
  
  
  # Use ARM instruction set instead of Thumb for improved calculation performance in ARM CPUs 
  LOCAL_ARM_MODE := arm
  
  include $(BUILD_SHARED_LIBRARY)
  </code></pre>
  
  <p>and this is my <code>module build.gradle</code> file:</p>
  
  <pre><code>apply plugin: 'com.android.application'
  
  android {
      signingConfigs {
          dev_key {
              keyAlias '#########'
              keyPassword '########'
              storeFile file('/Users/daniele/Desktop/Chords/########')
              storePassword '#######'
          }
      }
      compileSdkVersion 26
      buildToolsVersion "26.0.1"
      defaultConfig {
          applicationId "com.dancam.chords"
          minSdkVersion 21
          targetSdkVersion 26
          versionCode 16
          versionName "2.1"
          signingConfig ##########
          multiDexEnabled true
      }
      buildTypes {
          release {
              shrinkResources true
              minifyEnabled true
              proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
          }
      }
      productFlavors {
      }
  
      dataBinding {
          enabled = true
      }
  }
  
  dependencies {
      compile fileTree(include: ['*.jar'], dir: 'libs')
      androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
          exclude group: 'com.android.support', module: 'support-annotations'
      })
  </code></pre>
  
  <p>I import a native function:</p>
  
  <pre><code>public final class SoundTouch {
      public native final static String getVersionString();
  
  // Load the native library upon startup
  static
  {
      System.loadLibrary("soundtouch");
  }
  }
  </code></pre>
  
  <p>This is my <code>soundtouch-jni.cpp</code> file:</p>
  
  <pre><code>#include &lt;jni.h&gt;
  #include &lt;android/log.h&gt;
  #include &lt;stdexcept&gt;
  #include &lt;string&gt;
  
  using namespace std;
  
  #include "../../../include/SoundTouch.h"
  #include "../source/SoundStretch/WavFile.h"
  
  #define LOGV(...)   __android_log_print((int)ANDROID_LOG_INFO, "SOUNDTOUCH", __VA_ARGS__)
  //#define LOGV(...)
  
  
  // String for keeping possible c++ exception error messages. Notice that this isn't
  // thread-safe but it's expected that exceptions are special situations that won't
  // occur in several threads in parallel.
  static string _errMsg = "";
  
  
  #define DLL_PUBLIC __attribute__ ((visibility ("default")))
  #define BUFF_SIZE 4096
  
  
  using namespace soundtouch;
  
  
  // Set error message to return
  static void _setErrmsg(const char *msg)
  {
      _errMsg = msg;
  }
  
  
  #ifdef _OPENMP
  
  #include &lt;pthread.h&gt;
  extern pthread_key_t gomp_tls_key;
  static void * _p_gomp_tls = NULL;
  
  /// Function to initialize threading for OpenMP.
  ///
  /// This is a workaround for bug in Android NDK v10 regarding OpenMP: OpenMP works only if
  /// called from the Android App main thread because in the main thread the gomp_tls storage is
  /// properly set, however, Android does not properly initialize gomp_tls storage for other threads.
  /// Thus if OpenMP routines are invoked from some other thread than the main thread,
  /// the OpenMP routine will crash the application due to NULL pointer access on uninitialized storage.
  ///
  /// This workaround stores the gomp_tls storage from main thread, and copies to other threads.
  /// In order this to work, the Application main thread needws to call at least "getVersionString"
  /// routine.
  static int _init_threading(bool warn)
  {
      void *ptr = pthread_getspecific(gomp_tls_key);
      LOGV("JNI thread-specific TLS storage %ld", (long)ptr);
      if (ptr == NULL)
      {
          LOGV("JNI set missing TLS storage to %ld", (long)_p_gomp_tls);
          pthread_setspecific(gomp_tls_key, _p_gomp_tls);
      }
      else
      {
          LOGV("JNI store this TLS storage");
          _p_gomp_tls = ptr;
      }
      // Where critical, show warning if storage still not properly initialized
      if ((warn) &amp;&amp; (_p_gomp_tls == NULL))
      {
          _setErrmsg("Error - OpenMP threading not properly initialized: Call SoundTouch.getVersionString() from the App main thread!");
          return -1;
      }
      return 0;
  }
  
  #else
  static int _init_threading(bool warn)
  {
      // do nothing if not OpenMP build
      return 0;
  }
  #endif
  
  
  // Processes the sound file
  static void _processFile(SoundTouch *pSoundTouch, const char *inFileName, const char *outFileName)
  {
      int nSamples;
      int nChannels;
      int buffSizeSamples;
      SAMPLETYPE sampleBuffer[BUFF_SIZE];
  
      // open input file
      WavInFile inFile(inFileName);
      int sampleRate = inFile.getSampleRate();
      int bits = inFile.getNumBits();
      nChannels = inFile.getNumChannels();
  
      // create output file
      WavOutFile outFile(outFileName, sampleRate, bits, nChannels);
  
      pSoundTouch-&gt;setSampleRate(sampleRate);
      pSoundTouch-&gt;setChannels(nChannels);
  
      assert(nChannels &gt; 0);
      buffSizeSamples = BUFF_SIZE / nChannels;
  
      // Process samples read from the input file
      while (inFile.eof() == 0)
      {
          int num;
  
          // Read a chunk of samples from the input file
          num = inFile.read(sampleBuffer, BUFF_SIZE);
          nSamples = num / nChannels;
  
          // Feed the samples into SoundTouch processor
          pSoundTouch-&gt;putSamples(sampleBuffer, nSamples);
  
          // Read ready samples from SoundTouch processor &amp; write them output file.
          // NOTES:
          // - 'receiveSamples' doesn't necessarily return any samples at all
          //   during some rounds!
          // - On the other hand, during some round 'receiveSamples' may have more
          //   ready samples than would fit into 'sampleBuffer', and for this reason
          //   the 'receiveSamples' call is iterated for as many times as it
          //   outputs samples.
          do
          {
              nSamples = pSoundTouch-&gt;receiveSamples(sampleBuffer, buffSizeSamples);
              outFile.write(sampleBuffer, nSamples * nChannels);
          } while (nSamples != 0);
      }
  
      // Now the input file is processed, yet 'flush' few last samples that are
      // hiding in the SoundTouch's internal processing pipeline.
      pSoundTouch-&gt;flush();
      do
      {
          nSamples = pSoundTouch-&gt;receiveSamples(sampleBuffer, buffSizeSamples);
          outFile.write(sampleBuffer, nSamples * nChannels);
      } while (nSamples != 0);
  }
  
  
  
  extern "C" DLL_PUBLIC jstring Java_net_surina_soundtouch_SoundTouch_getVersionString(JNIEnv *env, jobject thiz)
  {
      const char *verStr;
  
      LOGV("JNI call SoundTouch.getVersionString");
  
      // Call example SoundTouch routine
      verStr = SoundTouch::getVersionString();
  
      /// gomp_tls storage bug workaround - see comments in _init_threading() function!
      _init_threading(false);
  
      int threads = 0;
      #pragma omp parallel
      {
          #pragma omp atomic
          threads ++;
      }
      LOGV("JNI thread count %d", threads);
  
      // return version as string
      return env-&gt;NewStringUTF(verStr);
  }
  
  
  
  extern "C" DLL_PUBLIC jlong Java_net_surina_soundtouch_SoundTouch_newInstance(JNIEnv *env, jobject thiz)
  {
      return (jlong)(new SoundTouch());
  }
  
  
  extern "C" DLL_PUBLIC void Java_net_surina_soundtouch_SoundTouch_deleteInstance(JNIEnv *env, jobject thiz, jlong handle)
  {
      SoundTouch *ptr = (SoundTouch*)handle;
      delete ptr;
  }
  
  
  extern "C" DLL_PUBLIC void Java_net_surina_soundtouch_SoundTouch_setTempo(JNIEnv *env, jobject thiz, jlong handle, jfloat tempo)
  {
      SoundTouch *ptr = (SoundTouch*)handle;
      ptr-&gt;setTempo(tempo);
  }
  
  
  extern "C" DLL_PUBLIC void Java_net_surina_soundtouch_SoundTouch_setPitchSemiTones(JNIEnv *env, jobject thiz, jlong handle, jfloat pitch)
  {
      SoundTouch *ptr = (SoundTouch*)handle;
      ptr-&gt;setPitchSemiTones(pitch);
  }
  
  
  extern "C" DLL_PUBLIC void Java_net_surina_soundtouch_SoundTouch_setSpeed(JNIEnv *env, jobject thiz, jlong handle, jfloat speed)
  {
      SoundTouch *ptr = (SoundTouch*)handle;
      ptr-&gt;setRate(speed);
  }
  
  
  extern "C" DLL_PUBLIC jstring Java_net_surina_soundtouch_SoundTouch_getErrorString(JNIEnv *env, jobject thiz)
  {
      jstring result = env-&gt;NewStringUTF(_errMsg.c_str());
      _errMsg.clear();
  
      return result;
  }
  
  
  extern "C" DLL_PUBLIC int Java_net_surina_soundtouch_SoundTouch_processFile(JNIEnv *env, jobject thiz, jlong handle, jstring jinputFile, jstring joutputFile)
  {
      SoundTouch *ptr = (SoundTouch*)handle;
  
      const char *inputFile = env-&gt;GetStringUTFChars(jinputFile, 0);
      const char *outputFile = env-&gt;GetStringUTFChars(joutputFile, 0);
  
      LOGV("JNI process file %s", inputFile);
  
      /// gomp_tls storage bug workaround - see comments in _init_threading() function!
      if (_init_threading(true)) return -1;
  
      try
      {
          _processFile(ptr, inputFile, outputFile);
      }
      catch (const runtime_error &amp;e)
      {
          const char *err = e.what();
          // An exception occurred during processing, return the error message
          LOGV("JNI exception in SoundTouch::processFile: %s", err);
          _setErrmsg(err);
          return -1;
      }
  
  
      env-&gt;ReleaseStringUTFChars(jinputFile, inputFile);
      env-&gt;ReleaseStringUTFChars(joutputFile, outputFile);
  
      return 0;
  }
  </code></pre>
  
  <p>EDIT:</p>
  
  <p>After doing what Alex Cohn suggested, I ended up with the following errors:</p>
  
  <blockquote>
    <p>Build command failed.</p>
  </blockquote>
  
  <pre><code>Error while executing process /Users/daniele/Library/Android/sdk/ndk-bundle/ndk-build with arguments {NDK_PROJECT_PATH=null APP_BUILD_SCRIPT=/Users/daniele/Developer/AndroidProjects/Chords2/app/jni/Android.mk NDK_APPLICATION_MK=/Users/daniele/Developer/AndroidProjects/Chords2/app/jni/Application.mk APP_ABI=armeabi-v7a NDK_ALL_ABIS=armeabi-v7a NDK_DEBUG=0 APP_PLATFORM=android-21 NDK_OUT=/Users/daniele/Developer/AndroidProjects/Chords2/app/build/intermediates/ndkBuild/release/obj NDK_LIBS_OUT=/Users/daniele/Developer/AndroidProjects/Chords2/app/build/intermediates/ndkBuild/release/lib APP_SHORT_COMMANDS=false LOCAL_SHORT_COMMANDS=false -B -n}
  rm -f /Users/daniele/Developer/AndroidProjects/Chords2/app/build/intermediates/ndkBuild/release/lib/armeabi-v7a/*
  rm -f /Users/daniele/Developer/AndroidProjects/Chords2/app/build/intermediates/ndkBuild/release/lib/armeabi-v7a/gdbserver
  rm -f /Users/daniele/Developer/AndroidProjects/Chords2/app/build/intermediates/ndkBuild/release/lib/armeabi-v7a/gdb.setup
  mkdir -p /Users/daniele/Developer/AndroidProjects/Chords2/app/build/intermediates/ndkBuild/release/obj/local/armeabi-v7a/objs/soundtouch
  echo [armeabi-v7a] "Compile++ arm  ": "soundtouch &lt;= soundtouch-jni.cpp"
  /Users/daniele/Library/Android/sdk/ndk-bundle/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ -MMD -MP -MF /Users/daniele/Developer/AndroidProjects/Chords2/app/build/intermediates/ndkBuild/release/obj/local/armeabi-v7a/objs/soundtouch/soundtouch-jni.o.d -gcc-toolchain /Users/daniele/Library/Android/sdk/ndk-bundle/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64 -fpic -ffunction-sections -funwind-tables -fstack-protector-strong -Wno-invalid-command-line-argument -Wno-unused-command-line-argument -no-canonical-prefixes -fno-integrated-as -g -target armv7-none-linux-androideabi -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 -fno-exceptions -fno-rtti -marm -O2 -DNDEBUG  -I/Users/daniele/Library/Android/sdk/ndk-bundle/sources/cxx-stl/stlport/stlport -I/Users/daniele/Library/Android/sdk/ndk-bundle/sources/cxx-stl//gabi++/include -I/Users/daniele/Developer/AndroidProjects/Chords2/app/jni -DANDROID -fvisibility=hidden -I ../../../include -fdata-sections -ffunction-sections -Wa,--noexecstack -Wformat -Werror=format-security  -frtti   -fexceptions  -isystem /Users/daniele/Library/Android/sdk/ndk-mbundake: *** No rule to make target `/Users/daniele/Delveeloper/platforms/android-/AndroidProjects/Chords2/app/jni/../../SoundTouch/AAFilter.cpp', needed by `/Users/daniele/Developer/AndroidProjects/Chords2/app/build/intermedi2ates/ndkBuild/1/arch-arm/usr/include -c release/obj/local/armeabi-v7a/objs/soun /Users/dtdaniele/Douch/__/__/SoeveloundTouch/AAFpilter.o'.  Stop.
  er/AndroidProjects/Chords2/app/jni/soundtouch-jni.cpp -o /Users/daniele/Developer/AndroidProjects/Chords2/app/build/intermediates/ndkBuild/release/obj/local/armeabi-v7a/objs/soundtouch/soundtouch-jni.o 
  </code></pre>
  
  <blockquote>
    <p>Build command failed.</p>
  </blockquote>
  
  <pre><code>Error while executing process /Users/daniele/Library/Android/sdk/ndk-bundle/ndk-build with arguments {NDK_PROJECT_PATH=null APP_BUILD_SCRIPT=/Users/daniele/Developer/AndroidProjects/Chords2/app/jni/Android.mk NDK_APPLICATION_MK=/Users/daniele/Developer/AndroidProjects/Chords2/app/jni/Application.mk APP_ABI=armeabi-v7a NDK_ALL_ABIS=armeabi-v7a NDK_DEBUG=1 APP_PLATFORM=android-21 NDK_OUT=/Users/daniele/Developer/AndroidProjects/Chords2/app/build/intermediates/ndkBuild/debug/obj NDK_LIBS_OUT=/Users/daniele/Developer/AndroidProjects/Chords2/app/build/intermediates/ndkBuild/debug/lib APP_SHORT_COMMANDS=false LOCAL_SHORT_COMMANDS=false -B -n}
  rm -f /Users/daniele/Developer/AndroidProjects/Chords2/app/build/intermediates/ndkBuild/debug/lib/armeabi-v7a/*
  rm -f /Users/daniele/Developer/AndroidProjects/Chords2/app/build/intermediates/ndkBuild/debug/lib/armeabi-v7a/gdbserver
  rm -f /Users/daniele/Developer/AndroidProjects/Chords2/app/build/intermediates/ndkBuild/debug/lib/armeabi-v7a/gdb.setup
  mkdir -p /Users/daniele/Developer/AndroidProjects/Chords2/app/build/intermediates/ndkBuild/debug/lib/armeabi-v7a
  echo [armeabi-v7a] "Gdbserver      ": "[arm-linux-androideabi] /Users/daniele/Developer/AndroidProjects/Chords2/app/build/intermediates/ndkBuild/debug/lib/armeabi-v7a/gdbserver"
  install -p /Users/daniele/Library/Android/sdk/ndk-bundle/prebuilt/android-arm/gdbserver/gdbserver /Users/daniele/Developer/AndroidProjects/Chords2/app/build/intermediates/ndkBuild/debug/lib/armeabi-v7a/gdbserver
  echo [armeabi-v7a] "Gdbsetup       ": "/Users/daniele/Developer/AndroidProjects/Chords2/app/build/intermediates/ndkBuild/debug/lib/armeabi-v7a/gdb.setup"
  echo "set solib-search-path /Users/daniele/Developer/AndroidProjects/Chords2/app/build/intermediates/ndkBuild/debug/obj/local/armeabi-v7a" &gt; /Users/daniele/Developer/AndroidProjects/Chords2/app/build/intermediates/ndkBuild/debug/lib/armeabi-v7a/gdb.setup
  echo "directory /Users/daniele/Library/Android/sdk/ndk-bundle/platforms/android-21/arch-arm/usr/include /Users/daniele/Library/Android/sdk/ndk-bundle/sources/cxx-stl/stlport/stlport /Users/daniele/Library/Android/sdk/ndk-bundle/sources/cxx-stl//gabi++/include /Users/daniele/Developer/AndroidProjects/Chords2/app/jni" &gt;&gt; /Users/daniele/Developer/AndroidProjects/Chords2/app/build/intermediates/ndkBuild/debug/lib/armeabi-v7a/gdb.setup
  mkdir -p /Users/daniele/Developer/AndroidProjects/Chords2/app/build/intermediates/ndkBuild/debug/obj/local/armeabi-v7a/objs/soundtouch
  echo [armeabi-v7a] "Compile++ arm  ": "soundtouch &lt;= soundtouch-jni.cpp"
  /Users/daniele/Library/Android/sdk/ndk-bundle/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ -MMD -MP -MF /Users/daniele/Developer/Androidmake: *** No rule to make target `/Users/daniele/Developer/AndroidProjects/Chords2/app/jniPro/../../SojeundTouch/AAFilter.cpp'c, ts/nCheeded by `o/Usrdsers/daniele/Develo2/apper/AndroidpProjects/Chords2/app/build/intermediates/ndkBuild//bdebug/obj/local/uiarmeabi-v7a/objs/soundtouch/__/__/SoundldTouch/AAFilter.o'.  Stop.
  /intermediates/ndkBuild/debug/obj/local/armeabi-v7a/objs/soundtouch/soundtouch-jni.o.d -gcc-toolchain /Users/daniele/Library/Android/sdk/ndk-bundle/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64 -fpic -ffunction-sections -funwind-tables -fstack-protector-strong -Wno-invalid-command-line-argument -Wno-unused-command-line-argument -no-canonical-prefixes -fno-integrated-as -g -target armv7-none-linux-androideabi -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 -fno-exceptions -fno-rtti -marm -O2 -DNDEBUG  -I/Users/daniele/Library/Android/sdk/ndk-bundle/sources/cxx-stl/stlport/stlport -I/Users/daniele/Library/Android/sdk/ndk-bundle/sources/cxx-stl//gabi++/include -I/Users/daniele/Developer/AndroidProjects/Chords2/app/jni -DANDROID -fvisibility=hidden -I ../../../include -fdata-sections -ffunction-sections -Wa,--noexecstack -Wformat -Werror=format-security  -frtti   -fexceptions  -isystem /Users/daniele/Library/Android/sdk/ndk-bundle/platforms/android-21/arch-arm/usr/include -c  /Users/daniele/Developer/AndroidProjects/Chords2/app/jni/soundtouch-jni.cpp -o /Users/daniele/Developer/AndroidProjects/Chords2/app/build/intermediates/ndkBuild/debug/obj/local/armeabi-v7a/objs/soundtouch/soundtouch-jni.o
  </code></pre>
  
  <p><strong>Please notice: I compiled the Soundtouch Library using <code>ndk-build</code> on Ubuntu Linux, then copied it over to macOS where I normally work</strong></p>
  
  <p><strong>Any clue on how to fix this?</strong></p>