【问题标题】:"ld: error: undefined symbol" when using "repeated" keyword in protobuf在 protobuf 中使用“repeated”关键字时出现“ld: error: undefined symbol”
【发布时间】:2021-03-11 10:49:54
【问题描述】:

经过数小时的调试,我得到了以下极简 .proto 文件:

syntax = "proto3";

message PbCaptureResult {
    bool checkedValid = 1;
}

message PbCaptureResultSequence {
    PbCaptureResult captureResults = 1;
}

它编译和链接成功。 但是,如果我添加一个“重复”,例如:

syntax = "proto3";

message PbCaptureResult {
    bool checkedValid = 1;
}

message PbCaptureResultSequence {
    repeated PbCaptureResult captureResults = 1;
}

然后我有一个链接错误并得到:

cmd.exe /C "cd . && C:\Android\Sdk\ndk\22.0.6917172\toolchains\llvm\prebuilt\windows-x86_64\bin\clang++.exe --target=aarch64-none-linux-android29 --gcc-toolchain=C:/Android/Sdk/ndk/22.0.6917172/toolchains/llvm/prebuilt/windows-x86_64 --sysroot=C:/Android/Sdk/ndk/22.0.6917172/toolchains/llvm/prebuilt/windows-x86_64/sysroot -fPIC -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security  -Wno-deprecated-declarations -O0 -fno-limit-debug-info  -Wl,--exclude-libs,libgcc.a -Wl,--exclude-libs,libgcc_real.a -Wl,--exclude-libs,libatomic.a -Wl,--build-id=sha1 -Wl,--fatal-warnings -Wl,--no-undefined -Qunused-arguments -shared -Wl,-soname,libnative-lib.so -o libnative-lib.so @CMakeFiles/native-lib.rsp  && cd ."
ld: error: undefined symbol: google::protobuf::internal::RepeatedPtrFieldBase::AddOutOfLineHelper(void*)
>>> referenced by repeated_field.h:1767 (../../../../imported-lib/include\google/protobuf\repeated_field.h:1767)
>>>               CMakeFiles/native-lib.dir/src/main/cpp/authenticationLib/CaptureResultSequence.pb.cc.o:(google::protobuf::RepeatedPtrField<PbCaptureResult>::TypeHandler::Type* google::protobuf::internal::RepeatedPtrFieldBase::Add<google::protobuf::RepeatedPtrField<PbCaptureResult>::TypeHandler>(google::protobuf::RepeatedPtrField<PbCaptureResult>::TypeHandler::Type*))
clang++: error: linker command failed with exit code 1 (use -v to see invocation)

如果“重复”出现在诸如字符串之类的“标准类型”之前,则编译:

syntax = "proto3";

message PbCaptureResult {
    bool checkedValid = 1;
}

message PbCaptureResultSequence {
    repeated string captureResults = 1;
}

只有当我尝试重复自定义消息时才会出现问题。

但在 protobuf 网站上我找到了以下示例:

message SearchResponse {
  repeated Result results = 1;
}

message Result {
  string url = 1;
  string title = 2;
  repeated string snippets = 3;
} 

我已将示例按原样放在我的 .proto 文件中,但由于相同的链接错误而无法编译。我得出结论,这不是 .proto 语法问题。

它是 protobuf 3.15.5。

生成命令为:./bin/protoc.exe --cpp_out=.. CaptureResultSequence.proto

我是针对 libprotobuf.a(不是 libprotobuf-lite.a)的静态链接

我自己交叉编译了protobuf

我最初认为该问题与链接有关,但对我来说,它并没有解释为什么我可以在没有“重复”的情况下进行链接,但无法链接。

我在这上面花了 2 天时间,我相信这很明显......

编辑:

确实“AddOutOfLineHelper”在“repeated_field.cc”中定义

使用 ar x libprotobuf.a,我可以确认重复字段.cc.o 包含在库中。

奇怪的是,没有“重复”消息,我没有链接问题。

如果我不使用任何“重复”消息,我假设还需要 libprotobuf.a 并进行链接。也许不吧 ?如何检查?

根据要求。这是我的 protobuf 构建命令:

#!/bin/bash
NDK_LOCATION=/home/xxx/Android/android-ndk-r21
INCLUDE_LOCATION=/home/xxx/Android/3rdparty/include
LIB_LOCATION=/home/xxx/Android/3rdparty/lib
ABI_LIST="arm64-v8a"
#ABI_LIST="arm64-v8a armeabi-v7a x86 x86_64"
SRC_LOCATION=/home/xxx/Android/protobuf-3.15.5/cmake
BUILD_LOCATION=${SRC_LOCATION}/build

for ABI in ${ABI_LIST}
do
    [ -d ${BUILD_LOCATION} ] && echo "the build location exists: deletting" && rm -rf ${BUILD_LOCATION}

    mkdir -p ${BUILD_LOCATION}
    cd ${BUILD_LOCATION}
    cmake ${SRC_LOCATION} -DCMAKE_TOOLCHAIN_FILE=${NDK_LOCATION}/build/cmake/android.toolchain.cmake \
    -Dprotobuf_BUILD_EXAMPLES=OFF \
    -Dprotobuf_BUILD_TESTS=OFF \
    -Dprotobuf_BUILD_SHARED_LIBS=FALSE \
    -Dprotobuf_BUILD_LIBPROTOC=FALSE \
    -Dprotobuf_BUILD_PROTOC_BINARIES=FALSE \
    -Dprotobuf_DISABLE_RTTI=ON \
    -Dprotobuf_WITH_ZLIB=OFF \
    -DANDROID_ABI="${ABI}" \
    -DANDROID_STL=c++_shared \
    -DCMAKE_BUILD_TYPE=Release \
    -DANDROID_NATIVE_API_LEVEL=android-28 &&
    make -j4
done

在 Android 端的 Gradle 文件的 ndk 部分:

ndk {
    // Specifies the ABI configurations of your native
    // libraries Gradle should build and package with your APK.
    abiFilters 'arm64-v8a' //'armeabi-v7a', 'arm64-v8a'
}

externalNativeBuild {
    cmake {

        // Passes optional arguments to CMake.
        arguments  "-DANDROID_TOOLCHAIN=clang", "-DANDROID_STL=c++_shared", "NDK_DEBUG=1"

        // Sets a flag to enable format macro constants for the C compiler.
        // cFlags "-D__STDC_FORMAT_MACROS"

        // Sets optional flags for the C++ compiler.
        cppFlags "-Wno-deprecated-declarations" //, "-fexceptions", "-frtti"
    }
}

CMakeList.txt:

cmake_minimum_required(VERSION 3.10.0)


add_library( libprotobuf STATIC IMPORTED )
set_target_properties( libprotobuf PROPERTIES IMPORTED_LOCATION
        ${PROJECT_SOURCE_DIR}/imported-lib/${ANDROID_ABI}/libprotobuf.a )


find_library( zlib z )
find_library( log-lib log )
find_library( camera-lib camera2ndk )
find_library( media-lib mediandk )
find_library( android-lib android )
find_library( gl-lib GLESv2 )

file( GLOB_RECURSE app_src_files
        "${PROJECT_SOURCE_DIR}/src/main/cpp/*.c*" )


add_library( native-lib
             # Sets the library as a shared library.
             SHARED
             # Provides a relative path to your source file(s).
             ${app_src_files} )

include_directories(${PROJECT_SOURCE_DIR}/src/main/cpp)

# because we have cyclic dependencies, we need to link several times the same libary.
target_link_libraries( native-lib
        libprotobuf
        ${log-lib}
        ${zlib}
        ${camera-lib}
        ${media-lib}
        ${android-lib}
        ${gl-lib}
        
        libprotobuf
        ${log-lib}
        ${zlib}
        ${camera-lib}
        ${media-lib}
        ${android-lib}
        ${gl-lib}
        
        libprotobuf
        ${log-lib}
        ${zlib}
        ${camera-lib}
        ${media-lib}
        ${android-lib}
        ${gl-lib}

        )

【问题讨论】:

  • 您可能需要提供更多详细信息,说明您如何准确地构建自己的代码和 libprotobuf。 AddOutOfLineHelper 应该在 protobuf 源代码树的 repeated_field.cc 中定义。
  • 虽然它可能与您的直接问题无关,但您正在使用 libprotobuf 的静态 STL 实现但 native-lib 的共享实现(您已将 libprotobuf 链接到其中)这一事实似乎奇怪。
  • @Michael 很好。我在帖子中解决了这个问题。它仍然没有链接。

标签: android-ndk protocol-buffers


【解决方案1】:

经过几天的处理,问题与包含文件有关。

因为我正在为 Android 做交叉编译,所以我没有完成“make install”步骤。在我的开发机器上安装包是没有意义的。因此,我只是从编译文件夹中获取 .a 文件和源中的包含文件

这是我的错误!

我必须与已编译库一起放入的包含文件只是 src/include 文件夹中所有文件的一个子集...之后听起来很明显...

因此我必须指定一个临时的 CMAKE_INSTALL_PREFIX 并运行 make install。然后从该位置获取包含文件夹。

然后一切都按预期进行。

【讨论】:

    猜你喜欢
    • 2023-01-29
    • 2020-10-26
    • 2020-06-21
    • 2020-12-25
    • 1970-01-01
    • 2018-12-02
    • 2017-05-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多