代码之家  ›  专栏  ›  技术社区  ›  Daniele

Android NDK-Gradle构建错误

  •  1
  • Daniele  · 技术社区  · 7 年前

    libs 文件夹

    library

    在每个文件夹中都有一个 libsoundtouch.so 文件

    jni

    • 应用mk公司

    我的Android。mk看起来像这样:

    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)
    

    这是我的 module build.gradle 文件:

    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'
        })
    

    我导入本机函数:

    public final class SoundTouch {
        public native final static String getVersionString();
    
    // Load the native library upon startup
    static
    {
        System.loadLibrary("soundtouch");
    }
    }
    

    soundtouch-jni.cpp

    #include <jni.h>
    #include <android/log.h>
    #include <stdexcept>
    #include <string>
    
    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 <pthread.h>
    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) && (_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->setSampleRate(sampleRate);
        pSoundTouch->setChannels(nChannels);
    
        assert(nChannels > 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->putSamples(sampleBuffer, nSamples);
    
            // Read ready samples from SoundTouch processor & 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->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->flush();
        do
        {
            nSamples = pSoundTouch->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->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->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->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->setRate(speed);
    }
    
    
    extern "C" DLL_PUBLIC jstring Java_net_surina_soundtouch_SoundTouch_getErrorString(JNIEnv *env, jobject thiz)
    {
        jstring result = env->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->GetStringUTFChars(jinputFile, 0);
        const char *outputFile = env->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 &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->ReleaseStringUTFChars(jinputFile, inputFile);
        env->ReleaseStringUTFChars(joutputFile, outputFile);
    
        return 0;
    }
    

    编辑:

    按照亚历克斯·科恩的建议,我最终犯了以下错误:

    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 <= 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 
    

    生成命令失败。

    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" > /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" >> /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 <= 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
    

    请注意:我使用 ndk-build

    有没有关于如何解决这个问题的线索?

    2 回复  |  直到 7 年前
        1
  •  2
  •   Alex Cohn    7 年前

    我看你在建筑方面有问题 libsoundtouch.so 在Android Studio中。例如,当第三方库的构建脚本需要特殊环境时,就会发生这种情况。E、 g.为Android构建webrtc的唯一受支持的方法是在64位Linux上。

    jniLibs 项目下的文件夹( jniLibs/armeabi-v7a/libsoundtouch.so ),或设置 custom folder for jniLibs 建筑格拉德尔 (英寸 块):

    sourceSets.main.jniLibs.srcDir 'libs'
    

    你不应该使用 再加上这个。

        2
  •  2
  •   Alex Cohn    7 年前

    您应该设置gradle项目来构建C++库。

    以下行(在 android{}

    externalNativeBuild.ndkBuild.path = 'jni/Android.mk'
    

    (假设路径~/AndroidStudioProjects/Chords2/app/build.gradle和~/AndroidStudioProjects/Chords2/app/jni/Android.mk)。

    ndk { abiFilters 'armeabi-v7a' }
    

    defaultConfig{}

    无论如何,在APK就绪后,您可以使用 从Android Studio的菜单中,选中所有 文件被打包到其中。