Миграция с ndk-build на CMake — ошибка с build.ninja

avatar
Swapnil
8 апреля 2018 в 06:36
1636
1
0

Я пытался перейти с моей конфигурации ndk-build на CMake с целью создания различных общих библиотек в моей библиотеке Android. Мой файл Android.mk:

    LOCAL_PATH := $(call my-dir)

######################################################
####   Building internal evaluation and dsp library
######################################################
include $(CLEAR_VARS)

LOCAL_MODULE    := pitchYIN
LOCAL_SRC_FILES := yin.c yinOld.c DSPAlgorithms.c singingEvaluation.c myutils.c
LOCAL_LDLIBS := -llog
LOCAL_CFLAGS := -DVERBOSE=0

include $(BUILD_SHARED_LIBRARY)

######################################################
####   Building soundtouch library
######################################################
include $(CLEAR_VARS)

### Update this local path wrt system ###
MY_SOUNDTOUCH_SRC_DIR := <path-to-the-src-dir>

LOCAL_MODULE    := soundtouch
LOCAL_SRC_FILES := soundtouch-jni.cpp $(MY_SOUNDTOUCH_SRC_DIR)/SoundTouch/AAFilter.cpp  $(MY_SOUNDTOUCH_SRC_DIR)/SoundTouch/FIFOSampleBuffer.cpp \
                    $(MY_SOUNDTOUCH_SRC_DIR)/SoundTouch/FIRFilter.cpp $(MY_SOUNDTOUCH_SRC_DIR)/SoundTouch/cpu_detect_x86.cpp \
                    $(MY_SOUNDTOUCH_SRC_DIR)/SoundTouch/sse_optimized.cpp $(MY_SOUNDTOUCH_SRC_DIR)/SoundStretch/WavFile.cpp \
                    $(MY_SOUNDTOUCH_SRC_DIR)/SoundTouch/RateTransposer.cpp $(MY_SOUNDTOUCH_SRC_DIR)/SoundTouch/SoundTouch.cpp \
                    $(MY_SOUNDTOUCH_SRC_DIR)/SoundTouch/InterpolateCubic.cpp $(MY_SOUNDTOUCH_SRC_DIR)/SoundTouch/InterpolateLinear.cpp \
                    $(MY_SOUNDTOUCH_SRC_DIR)/SoundTouch/InterpolateShannon.cpp $(MY_SOUNDTOUCH_SRC_DIR)/SoundTouch/TDStretch.cpp \
                    $(MY_SOUNDTOUCH_SRC_DIR)/SoundTouch/BPMDetect.cpp $(MY_SOUNDTOUCH_SRC_DIR)/SoundTouch/PeakFinder.cpp

# Including the header files for sound touch ..
LOCAL_C_INCLUDES := $(MY_SOUNDTOUCH_SRC_DIR)
LOCAL_C_INCLUDES += $(MY_SOUNDTOUCH_SRC_DIR)/../includes

# for native audio
LOCAL_LDLIBS += -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 $(MY_SOUNDTOUCH_SRC_DIR)/../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)

Здесь я пытаюсь создать две разделяемые библиотеки pitchYIN и soundtouch. Сейчас я пытаюсь перейти к более независимому от платформы методу использования CMake. Это эквивалент CMakeLists.txt, который я пытался написать:

    # Sets the minimum version of CMake required to build your native library.
# This ensures that a certain set of CMake features is available to
# your build.

cmake_minimum_required(VERSION 3.4.1)

################Loading other libraries############################
find_library( # Defines the name of the path variable that stores the
              # location of the NDK library.
              log-lib

              # Specifies the name of the NDK library that
              # CMake needs to locate.
              log )

find_library( # Defines the name of the path variable that stores the
              # location of the NDK library.
              gcc-lib

              # Specifies the name of the NDK library that
              # CMake needs to locate.
              gcc )
######################################################################################
######### Adding pitchYIN library to the module
######################################################################################
set( jni_src_DIR ./src/main/jni )

add_library( # Specifies the name of the library.
             pitchYIN

             # Sets the library as a shared library.
             SHARED

             # Provides a relative path to your source file(s).
             ${jni_src_DIR}/yin.c
             ${jni_src_DIR}/yinOld.c
             ${jni_src_DIR}/DSPAlgorithms.c
             ${jni_src_DIR}/singingEvaluation.c
             ${jni_src_DIR}/myutils.c )

# Specifies a path to native header files.
include_directories(${jni_src_DIR})

# Links your native library against one or more other native libraries.
target_link_libraries( # Specifies the target library.
                       pitchYIN

                       # Links the log library to the target library.
                       ${log-lib} )


######################################################################################
######### Adding soundtouch library to the module
######################################################################################

set( soundtouch_src_DIR <path-to-src> )

add_library( # Specifies the name of the library.
             soundtouch

             # Sets the library as a shared library.
             SHARED

             # Provides a relative path to your source file(s).
             ${jni_src_DIR}/soundtouch-jni.cpp
             ${soundtouch_src_DIR}/SoundTouch/AAFilter.cpp
             ${soundtouch_src_DIR}/SoundTouch/FIFOSampleBuffer.cpp
             ${soundtouch_src_DIR}/SoundTouch/FIRFilter.cpp
             ${soundtouch_src_DIR}/SoundTouch/cpu_detect_x86.cpp
             ${soundtouch_src_DIR}/SoundTouch/sse_optimized.cpp
             ${soundtouch_src_DIR}/SoundStretch/WavFile.cpp
             ${soundtouch_src_DIR}/SoundTouch/RateTransposer.cpp
             ${soundtouch_src_DIR}/SoundTouch/SoundTouch.cpp
             ${soundtouch_src_DIR}/SoundTouch/InterpolateCubic.cpp
             ${soundtouch_src_DIR}/SoundTouch/InterpolateLinear.cpp
             ${soundtouch_src_DIR}/SoundTouch/InterpolateShannon.cpp
             ${soundtouch_src_DIR}/SoundTouch/TDStretch.cpp
             ${soundtouch_src_DIR}/SoundTouch/BPMDetect.cpp
             ${soundtouch_src_DIR}/SoundTouch/PeakFinder.cpp
             )

# Specifies a path to native header files.
include_directories(${soundtouch_src_DIR}
                    ${soundtouch_src_DIR}/../includes)

# Custom Flags:
# -fvisibility=hidden : don't export all symbols
set(gcc_coverage_compile_flags "-fvisibility=hidden -I ${soundtouch_src_DIR}/../include -fdata-sections -ffunction-sections")
add_definitions($(gcc_coverage_compile_flags))

# OpenMP mode : enable these flags to enable using OpenMP for parallel computation
add_definitions("-fopenmp")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fopenmp")

# Use ARM instruction set instead of Thumb for improved calculation performance in ARM CPUs
# Equivalent to LOCAL_ARM_MODE := arm in Android.mk
# set(CMAKE_ANDROID_ARM_MODE ON)

# Links your native library against one or more other native libraries.
target_link_libraries( # Specifies the target library.
                       soundtouch

                       # Links the log library to the target library.
                       ${log-lib} )

Кроме того, в моем файле gradle есть аргумент cmake, например:

.........
defaultConfig {
    /*sourceSets.main {
        jni.srcDirs = [] //disable automatic ndk-build call
        jniLibs.srcDir 'src/main/libs' //set .so files location to libs
    }*/
    externalNativeBuild {
        cmake {
            arguments "-DANDROID_TOOLCHAIN=clang", "-DANDROID_ARM_MODE=arm"
        }
    }
}

....
externalNativeBuild {
    /*ndkBuild {
        path 'src/main/jni/Android.mk'
    }*/

    cmake {
        // Provides a relative path to your CMake build script.
        path "CMakeLists.txt"
    }
}
.........

Добавление arguments "-DANDROID_TOOLCHAIN=clang", "-DANDROID_ARM_MODE=arm" произошло из-за LOCAL_ARM_MODE := arm в моем файле Android.mk для библиотеки soundtouch. Когда я сейчас пытаюсь собрать это, я получаю следующую ошибку:

Build command failed.
Error while executing process /Users/swapnilgupta/Library/Android/sdk/cmake/3.6.4111459/bin/cmake with arguments {--build /Users/swapnilgupta/work/musicmuni/riyaz/android_lib/audioiolib/.externalNativeBuild/cmake/debug/armeabi-v7a --target clean}
ninja: error: build.ninja:57: bad $-escape (literal $ must be written as $$)

57-я строка в build.ninja:

FLAGS = -isystem /Users/swapnilgupta/Library/Android/sdk/ndk-bundle/sysroot/usr/include/aarch64-linux-android -D__ANDROID_API__=21 -g -DANDROID -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -Wa,--noexecstack -Wformat -Werror=format-security   -fopenmp -O2 -DNDEBUG  -fPIC   $(gcc_coverage_compile_flags) -fopenmp

Я попытался немного прочитать об этом в Интернете, но не смог понять, что вызывает это в моем случае. Помогите пожалуйста :)

РЕДАКТИРОВАТЬ 1

Я пробовал вещи, упомянутые в ответе Алекса. Это помогло мне решить некоторые проблемы, но я все еще получаю следующую ошибку связывания:

Build command failed.
Error while executing process /Users/swapnilgupta/Library/Android/sdk/cmake/3.6.4111459/bin/cmake with arguments {--build /Users/swapnilgupta/work/musicmuni/riyaz/android_lib/audioiolib/.externalNativeBuild/cmake/debug/arm64-v8a --target soundtouch}
[1/1] Linking CXX shared library ../../../../build/intermediates/cmake/debug/obj/arm64-v8a/libsoundtouch.so
FAILED: : && /Users/swapnilgupta/Library/Android/sdk/ndk-bundle/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++  --target=aarch64-none-linux-android --gcc-toolchain=/Users/swapnilgupta/Library/Android/sdk/ndk-bundle/toolchains/aarch64-linux-android-4.9/prebuilt/darwin-x86_64 --sysroot=/Users/swapnilgupta/Library/Android/sdk/ndk-bundle/sysroot -fPIC -isystem /Users/swapnilgupta/Library/Android/sdk/ndk-bundle/sysroot/usr/include/aarch64-linux-android -D__ANDROID_API__=21 -g -DANDROID -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -Wa,--noexecstack -Wformat -Werror=format-security   -O0 -fno-limit-debug-info  -Wl,--exclude-libs,libgcc.a -Wl,--exclude-libs,libatomic.a --sysroot /Users/swapnilgupta/Library/Android/sdk/ndk-bundle/platforms/android-21/arch-arm64 -Wl,--build-id -Wl,--warn-shared-textrel -Wl,--fatal-warnings -Wl,--no-undefined -Wl,-z,noexecstack -Qunused-arguments -Wl,-z,relro -Wl,-z,now -shared -Wl,-soname,libsoundtouch.so -o ../../../../build/intermediates/cmake/debug/obj/arm64-v8a/libsoundtouch.so CMakeFiles/soundtouch.dir/src/main/jni/soundtouch-jni.cpp.o CMakeFiles/soundtouch.dir/Users/swapnilgupta/work/musicmuni/soundtouch/source/SoundTouch/AAFilter.cpp.o CMakeFiles/soundtouch.dir/Users/swapnilgupta/work/musicmuni/soundtouch/source/SoundTouch/FIFOSampleBuffer.cpp.o CMakeFiles/soundtouch.dir/Users/swapnilgupta/work/musicmuni/soundtouch/source/SoundTouch/FIRFilter.cpp.o CMakeFiles/soundtouch.dir/Users/swapnilgupta/work/musicmuni/soundtouch/source/SoundTouch/cpu_detect_x86.cpp.o CMakeFiles/soundtouch.dir/Users/swapnilgupta/work/musicmuni/soundtouch/source/SoundTouch/sse_optimized.cpp.o CMakeFiles/soundtouch.dir/Users/swapnilgupta/work/musicmuni/soundtouch/source/SoundStretch/WavFile.cpp.o CMakeFiles/soundtouch.dir/Users/swapnilgupta/work/musicmuni/soundtouch/source/SoundTouch/RateTransposer.cpp.o CMakeFiles/soundtouch.dir/Users/swapnilgupta/work/musicmuni/soundtouch/source/SoundTouch/SoundTouch.cpp.o CMakeFiles/soundtouch.dir/Users/swapnilgupta/work/musicmuni/soundtouch/source/SoundTouch/InterpolateCubic.cpp.o CMakeFiles/soundtouch.dir/Users/swapnilgupta/work/musicmuni/soundtouch/source/SoundTouch/InterpolateLinear.cpp.o CMakeFiles/soundtouch.dir/Users/swapnilgupta/work/musicmuni/soundtouch/source/SoundTouch/InterpolateShannon.cpp.o CMakeFiles/soundtouch.dir/Users/swapnilgupta/work/musicmuni/soundtouch/source/SoundTouch/TDStretch.cpp.o CMakeFiles/soundtouch.dir/Users/swapnilgupta/work/musicmuni/soundtouch/source/SoundTouch/BPMDetect.cpp.o CMakeFiles/soundtouch.dir/Users/swapnilgupta/work/musicmuni/soundtouch/source/SoundTouch/PeakFinder.cpp.o  -llog -lomp -latomic -lm "/Users/swapnilgupta/Library/Android/sdk/ndk-bundle/sources/cxx-stl/gnu-libstdc++/4.9/libs/arm64-v8a/libgnustl_static.a" && :
CMakeFiles/soundtouch.dir/src/main/jni/soundtouch-jni.cpp.o: In function `_init_threading(bool)':
/Users/swapnilgupta/work/musicmuni/riyaz/android_lib/audioiolib/src/main/jni/soundtouch-jni.cpp:69: undefined reference to `gomp_tls_key'
/Users/swapnilgupta/work/musicmuni/riyaz/android_lib/audioiolib/src/main/jni/soundtouch-jni.cpp:69: undefined reference to `gomp_tls_key'
/Users/swapnilgupta/work/musicmuni/riyaz/android_lib/audioiolib/src/main/jni/soundtouch-jni.cpp:74: undefined reference to `gomp_tls_key'
/Users/swapnilgupta/work/musicmuni/riyaz/android_lib/audioiolib/src/main/jni/soundtouch-jni.cpp:74: undefined reference to `gomp_tls_key'
clang++: error: linker command failed with exit code 1 (use -v to see invocation)
ninja: build stopped: subcommand failed.

Ошибка связана с переменной gomp_tls_key, которая является переменной extern в указанном файле.

Источник
Alex Cohn
8 апреля 2018 в 06:50
0

не могли бы вы опубликовать строку 57 сгенерированного файла build.ninja?

Swapnil
8 апреля 2018 в 06:53
1

@AlexCohn обновлен! :)

Alex Cohn
8 апреля 2018 в 13:47
0

относительно gomp_tls_key прочитайте это: coderhelper.com/a/28579559/192373

Swapnil
8 апреля 2018 в 13:49
0

Хорошо... но для объявления этой переменной используется extern pthread_key_t gomp_tls_key;, а pthread_key_t имеет тип int

Swapnil
8 апреля 2018 в 13:52
0

Я не уверен, что это как-то связано с правильным пользователем ключевого слова extern extern. Кажется, что проблема вызова потока, отличного от пользовательского интерфейса, уже решена в следующем коде. Код, в котором я получаю эту ошибку, можно найти по адресу pastebin.com/phf96Nx9.

Ответы (1)

avatar
Alex Cohn
8 апреля 2018 в 06:56
0
add_definitions($(gcc_coverage_compile_flags)) → add_definitions(${gcc_coverage_compile_flags}) 

На самом деле, я не знаю, зачем вам это set(); вы ничего не теряете, если напрямую

add_definitions("-fvisibility=hidden -I ${soundtouch_src_DIR}/../include -fdata-sections -ffunction-sections")

также с -fopenmp вам не нужно добавлять этот флаг дважды; строка

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fopenmp")

можно безопасно удалить.

И наконец, обратите внимание, что вам не нужно найти liblog.

target_link_libraries( # Specifies the target library.
                   soundtouch
                   log omp)

будет работать нормально благодаря скрипту цепочки инструментов NDK CMake.

Swapnil
8 апреля 2018 в 07:31
0

Обновлен код с изменениями, которые вы упомянули. Теперь получаю эту ошибку сборки: pastebin.com/mxQSbgGj. К вашему сведению: мне пришлось включить #include <cstring>, так как процесс сборки не смог найти memcpy()

Alex Cohn
8 апреля 2018 в 08:04
0

Вы пропустили libomp, не так ли?

Swapnil
8 апреля 2018 в 10:19
0

Ах да.. это я забыл... но даже после включения получаю ту же проблему!

Swapnil
8 апреля 2018 в 13:05
0

Я потратил еще немного времени и обновил вопрос с ошибкой, с которой я сталкиваюсь сейчас.

Alex Cohn
8 апреля 2018 в 15:41
0

Если я не ошибаюсь, этот обходной путь был придуман для NDK r10 и уже не актуален для текущего NDK. Некоторое время назад я предложил просто использовать готовую библиотеку SoundTouch. Вы ничего не получите от его самостоятельной компиляции.

Swapnil
8 апреля 2018 в 16:43
0

Хорошо.. Если бы я использовал готовый soundtouch... будет ли пользовательский код для создания пользовательской библиотеки работать с использованием cmake?

Alex Cohn
8 апреля 2018 в 17:45
0

Вам не нужен cmake, если вы используете готовый двоичный файл Android.

Swapnil
9 апреля 2018 в 00:58
0

Я имею в виду использование его для какой-то другой библиотеки?

Alex Cohn
9 апреля 2018 в 02:22
0

Ваш скрипт cmake не показывает зависимости от SoundTouch. Но при желании вы можете использовать его с add_library(st SHARED IMPORTED) и set_target_properties(st PROPERTIES IMPORTED_LOCATION path/armeabi-v7a/libSoundTouch.so )

Swapnil
9 апреля 2018 в 06:34
0

Давайте продолжим обсуждение в чате.