Android NDK编译报错:undefined symbol: __strlen_chk 技术求助
Flutter Android集成JUCE静态库链接错误排查
问题场景
在Flutter项目的Android端,使用JUCE框架和Projucer创建C++静态库后,集成时出现多个链接错误,例如ld: error: undefined symbol: __strlen_chk,相关配置及错误栈如下:
1. CMakeLists.txt配置
cmake_minimum_required(VERSION 3.18.1) project(JUCEAudioDemo) set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Ofast") set(CMAKE_CXX_STANDARD 17) # Oboe set(OBOE_DIR "${CMAKE_SOURCE_DIR}/../../../../../JUCE/modules/juce_audio_devices/native/oboe") add_subdirectory(${OBOE_DIR} ./oboe) # CPU Features add_library("cpufeatures" STATIC "${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c") # JUCE set(JuceAudio_DIR ${CMAKE_SOURCE_DIR}/src/main/cpp/juceaudio) add_library(JuceAudio STATIC IMPORTED) set_property(TARGET JuceAudio PROPERTY IMPORTED_LOCATION ${JuceAudio_DIR}/lib/${ANDROID_ABI}/libjuceaudio.a) set_target_properties(JuceAudio PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${JuceAudio_DIR}/lib/include) include_directories(${JuceAudio_DIR}/lib/include) include_directories(${CMAKE_SOURCE_DIR}/../../../../../JUCE/modules) add_library( native-lib SHARED src/main/cpp/native-lib.cpp src/main/cpp/PlayAudioEngine.cpp ) find_library( log-lib log) target_link_libraries( native-lib JuceAudio "cpufeatures" "oboe" ${log-lib})
2. app/build.gradle配置
def localProperties = new Properties() def localPropertiesFile = rootProject.file('local.properties') if (localPropertiesFile.exists()) { localPropertiesFile.withReader('UTF-8') { reader -> localProperties.load(reader) } } def flutterRoot = localProperties.getProperty('flutter.sdk') if (flutterRoot == null) { throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") } def flutterVersionCode = localProperties.getProperty('flutter.versionCode') if (flutterVersionCode == null) { flutterVersionCode = '1' } def flutterVersionName = localProperties.getProperty('flutter.versionName') if (flutterVersionName == null) { flutterVersionName = '1.0' } apply plugin: 'com.android.application' apply plugin: 'kotlin-android' apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" android { compileSdkVersion flutter.compileSdkVersion ndkVersion flutter.ndkVersion compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } kotlinOptions { jvmTarget = '1.8' } sourceSets { main.java.srcDirs += 'src/main/kotlin' } defaultConfig { applicationId "com.juceaudio.juceaudiodemo" minSdkVersion flutter.minSdkVersion targetSdkVersion flutter.targetSdkVersion versionCode flutterVersionCode.toInteger() versionName flutterVersionName externalNativeBuild { cmake { version = "3.24.1" abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64' arguments "-DANDROID_STL=c++_shared" cppFlags "-std=c++17" } } } externalNativeBuild { cmake { path 'CMakeLists.txt' } } buildTypes { release { // TODO: Add your own signing config for the release build. signingConfig signingConfigs.debug } } } flutter { source '../..' } dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" }
3. 完整错误栈
* What went wrong: Execution failed for task ':app:buildCMakeDebug[armeabi-v7a]'. > com.android.ide.common.process.ProcessException: ninja: Entering directory `/Users/mregnauld/ProjetsFlutter/JUCEAudioDemo/juceaudiodemo/android/app/.cxx/Debug/645e434e/armeabi-v7a' [1/1] Linking CXX shared library /Users/mregnauld/ProjetsFlutter/JUCEAudioDemo/juceaudiodemo/build/app/intermediates/cxx/Debug/645e434e/obj/armeabi-v7a/libnative-lib.so FAILED: /Users/mregnauld/ProjetsFlutter/JUCEAudioDemo/juceaudiodemo/build/app/intermediates/cxx/Debug/645e434e/obj/armeabi-v7a/libnative-lib.so : && /Users/mregnauld/AndroidSDK/ndk/23.1.7779620/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=armv7-none-linux-androideabi16 --sysroot=/Users/mregnauld/AndroidSDK/ndk/23.1.7779620/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -fPIC -std=c++17 -g -fno-limit-debug-info -Ofast -Wl,--build-id=sha1 -Wl,--no-rosegment -Wl,--fatal-warnings -Qunused-arguments -Wl,--no-undefined -shared -Wl,-soname,libnative-lib.so -o /Users/mregnauld/ProjetsFlutter/JUCEAudioDemo/juceaudiodemo/build/app/intermediates/cxx/Debug/645e434e/obj/armeabi-v7a/libnative-lib.so CMakeFiles/native-lib.dir/src/main/cpp/native-lib.cpp.o CMakeFiles/native-lib.dir/src/main/cpp/PlayAudioEngine.cpp.o ../../../../src/main/cpp/juceaudio/lib/armeabi-v7a/libjuceaudio.a libcpufeatures.a oboe/liboboe.a /Users/mregnauld/AndroidSDK/ndk/23.1.7779620/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/arm-linux-androideabi/16/liblog.so -llog -lOpenSLES -latomic -lm && : ld: error: undefined symbol: __strlen_chk >>> referenced by string.h:227 (/Users/mregnauld/AndroidSDK/ndk/23.1.7779620/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include/bits/fortify/string.h:227) >>> include_juce_core.cpp.o:(juce::logAssertion(char const*, int)) in archive ../../../../src/main/cpp/juceaudio/lib/armeabi-v7a/libjuceaudio.a >>> referenced by string.h:227 (/Users/mregnauld/AndroidSDK/ndk/23.1.7779620/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include/bits/fortify/string.h:227) >>> include_juce_core.cpp.o:(juce::File::getChildFile(juce::StringRef) const) in archive ../../../../src/main/cpp/juceaudio/lib/armeabi-v7a/libjuceaudio.a >>> referenced by string.h:227 (/Users/mregnauld/AndroidSDK/ndk/23.1.7779620/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include/bits/fortify/string.h:227) >>> include_juce_core.cpp.o:(juce::String::endsWithChar(wchar_t) const) in archive ../../../../src/main/cpp/juceaudio/lib/armeabi-v7a/libjuceaudio.a >>> referenced 174 more times ld: error: undefined symbol: __open_2 >>> referenced by fcntl.h:67 (/Users/mregnauld/AndroidSDK/ndk/23.1.7779620/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include/bits/fortify/fcntl.h:67) >>> include_juce_core.cpp.o:(juce::MemoryMappedFile::openInternal(juce::File const&, juce::MemoryMappedFile::AccessMode, bool)) in archive ../../../../src/main/cpp/juceaudio/lib/armeabi-v7a/libjuceaudio.a >>> referenced by fcntl.h:67 (/Users/mregnauld/AndroidSDK/ndk/23.1.7779620/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include/bits/fortify/fcntl.h:67) >>> include_juce_core.cpp.o:(juce::FileInputStream::FileInputStream(juce::File const&)) in archive ../../../../src/main/cpp/juceaudio/lib/armeabi-v7a/libjuceaudio.a >>> referenced by fcntl.h:67 (/Users/mregnauld/AndroidSDK/ndk/23.1.7779620/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include/bits/fortify/fcntl.h:67) >>> include_juce_core.cpp.o:(juce::FileInputStream::openHandle()) in archive ../../../../src/main/cpp/juceaudio/lib/armeabi-v7a/libjuceaudio.a >>> referenced 6 more times ld: error: undefined symbol: __read_chk >>> referenced by unistd.h:191 (/Users/mregnauld/AndroidSDK/ndk/23.1.7779620/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include/bits/fortify/unistd.h:191) >>> include_juce_core.cpp.o:(juce::FileInputStream::readInternal(void*, unsigned int)) in archive ../../../../src/main/cpp/juceaudio/lib/armeabi-v7a/libjuceaudio.a >>> referenced by unistd.h:191 (/Users/mregnauld/AndroidSDK/ndk/23.1.7779620/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include/bits/fortify/unistd.h:191) >>> include_juce_core.cpp.o:(juce::NamedPipe::Pimpl::read(char*, int, int)) in archive ../../../../src/main/cpp/juceaudio/lib/armeabi-v7a/libjuceaudio.a ld: error: undefined symbol: mkfifo >>> referenced by juce_posix_NamedPipe.cpp:130 (/Users/mregnauld/JUCE/modules/juce_core/native/juce_posix_NamedPipe.cpp:130) >>> include_juce_core.cpp.o:(juce::NamedPipe::openInternal(juce::String const&, bool, bool)) in archive ../../../../src/main/cpp/juceaudio/lib/armeabi-v7a/libjuceaudio.a >>> referenced by juce_posix_NamedPipe.cpp:130 (/Users/mregnauld/JUCE/modules/juce_core/native/juce_posix_NamedPipe.cpp:130) >>> include_juce_core.cpp.o:(juce::NamedPipe::openInternal(juce::String const&, bool, bool)) in archive ../../../../src/main/cpp/juceaudio/lib/armeabi-v7a/libjuceaudio.a ld: error: undefined symbol: signal >>> referenced by juce_SystemStats.cpp:222 (/Users/mregnauld/JUCE/modules/juce_core/system/juce_SystemStats.cpp:222) >>> include_juce_core.cpp.o:(juce::SystemStats::setApplicationCrashHandler(void (*)(void*))) in archive ../../../../src/main/cpp/juceaudio/lib/armeabi-v7a/libjuceaudio.a >>> referenced by juce_SystemStats.cpp:222 (/Users/mregnauld/JUCE/modules/juce_core/system/juce_SystemStats.cpp:222) >>> include_juce_core.cpp.o:(juce::SystemStats::setApplicationCrashHandler(void (*)(void*))) in archive ../../../../src/main/cpp/juceaudio/lib/armeabi-v7a/libjuceaudio.a >>> referenced by juce_SystemStats.cpp:222 (/Users/mregnauld/JUCE/modules/juce_core/system/juce_SystemStats.cpp:222) >>> include_juce_core.cpp.o:(juce::SystemStats::setApplicationCrashHandler(void (*)(void*))) in archive ../../../../src/main/cpp/juceaudio/lib/armeabi-v7a/libjuceaudio.a >>> referenced 4 more times ld: error: undefined symbol: __vsnprintf_chk >>> referenced by stdio.h:52 (/Users/mregnauld/AndroidSDK/ndk/23.1.7779620/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include/bits/fortify/stdio.h:52) >>> include_juce_core.cpp.o:(juce::String::formattedRaw(char const*, ...)) in archive ../../../../src/main/cpp/juceaudio/lib/armeabi-v7a/libjuceaudio.a ld: error: undefined symbol: __memcpy_chk >>> referenced by string.h:60 (/Users/mregnauld/AndroidSDK/ndk/23.1.7779620/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/include/bits/fortify/string.h:60) >>> include_juce_events.cpp.o:(juce::Timer::TimerThread::TimerThread()) in archive ../../../../src/main/cpp/juceaudio/lib/armeabi-v7a/libjuceaudio.a clang-12: error: linker command failed with exit code 1 (use -v to see invocation) ninja: build stopped: subcommand failed. C++ build system [build] failed while executing: /Users/mregnauld/AndroidSDK/cmake/3.22.1/bin/ninja \ -C \ /Users/mregnauld/ProjetsFlutter/JUCEAudioDemo/juceaudiodemo/android/app/.cxx/Debug/645e434e/armeabi-v7a \ native-lib from /Users/mregnauld/ProjetsFlutter/JUCEAudioDemo/juceaudiodemo/android/app
错误原因分析
这些链接错误主要分为两类:
- Fortify安全函数缺失:
__strlen_chk、__open_2、__read_chk等属于Android NDK的Fortify增强安全函数,这类函数在启用_FORTIFY_SOURCE宏时会替代标准库函数。如果静态库编译时启用了该宏,但链接时没有关联对应的库,或者项目与静态库的Fortify配置不一致,就会出现未定义符号。 - POSIX系统函数缺失:
mkfifo、signal属于POSIX标准函数,默认情况下Android NDK的链接器可能没有自动链接包含这些函数的系统库(如libc、libpthread)。
此外,还有可能是静态库与项目的构建配置不匹配:
- NDK版本不一致:静态库用的NDK版本和项目当前使用的NDK版本不同,导致标准库符号差异。
- STL类型不匹配:项目中指定了
ANDROID_STL=c++_shared,如果静态库编译时用了其他STL(如c++_static或gnustl),会导致符号不兼容。 - 编译选项差异:静态库和项目的优化级别(如
-Ofast)、C++标准版本不一致,也可能引发链接问题。
解决思路
1. 统一静态库与项目的构建配置
- 确认构建静态库时使用的NDK版本和项目中
flutter.ndkVersion一致。 - 确保静态库编译时指定的STL类型和项目的
ANDROID_STL=c++_shared完全相同。 - 检查静态库的编译选项:如果静态库启用了
_FORTIFY_SOURCE,项目也需要保持一致;或者在静态库编译时禁用该宏(通过添加-U_FORTIFY_SOURCE或-D_FORTIFY_SOURCE=0)。
2. 补充缺失的系统库链接
在CMakeLists.txt的target_link_libraries中添加必要的系统库:
target_link_libraries( native-lib JuceAudio
相关产品推荐
相关产品推荐

