"ld: error: undefined symbol" when using "repeated" keyword in protobuf
"ld: error: undefined symbol" when using "repeated" keyword in protobuf
经过几个小时的调试,我得到了以下极简 .proto 文件:
syntax = "proto3";
message PbCaptureResult {
bool checkedValid = 1;
}
message PbCaptureResultSequence {
PbCaptureResult captureResults = 1;
}
编译成功,links。
但是,如果我添加一个“重复”,如:
syntax = "proto3";
message PbCaptureResult {
bool checkedValid = 1;
}
message PbCaptureResultSequence {
repeated PbCaptureResult captureResults = 1;
}
然后我有一个 link 错误并得到:
cmd.exe /C "cd . && C:\Android\Sdk\ndk.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 文件中,但它无法编译并出现相同的 linking 错误。我断定这不是 .proto 语法问题。
这是 protobuf 3.15.5.
生成命令为:./bin/protoc.exe --cpp_out=.. CaptureResultSequence.proto
我是静态的link反对libprotobuf.a(不是libprotobuf-lite.a)
我自己交叉编译了protobuf
我最初认为这个问题与 linking 有关,但对我来说这并不能解释为什么我可以 link 没有“重复”但不能 link有了它。
我已经在这上面花了 2 天时间,我相信这很明显...
编辑:
确实在“repeated_field.cc”
中定义了“AddOutOfLineHelper”
使用 ar x libprotobuf.a,我可以确认 repeated_field.cc.o 包含在库中。
奇怪的是,没有“重复”消息,我没有 link 问题。
我认为如果我不使用任何“重复”消息,也需要 libprotobuf.a 和 linked。也许不吧 ?我该如何检查?
根据要求。这是我的 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
并且在 Gradle 文件的 Android 侧 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}
)
经过几天的努力,问题与包含文件有关。
因为我正在为 Android 进行交叉编译,所以我没有完成“make install”步骤。在我的开发机器上安装软件包毫无意义。因此,我只是从编译文件夹中获取 .a 文件,从源代码中获取包含文件。
这是我的错误!
我必须放在已编译库中的包含文件只是在 src/include 文件夹中找到的所有文件的一个子集...之后听起来很明显...
因此我必须指定临时 CMAKE_INSTALL_PREFIX 和 运行 make install。然后从该位置获取包含文件夹。
然后一切正常。
经过几个小时的调试,我得到了以下极简 .proto 文件:
syntax = "proto3";
message PbCaptureResult {
bool checkedValid = 1;
}
message PbCaptureResultSequence {
PbCaptureResult captureResults = 1;
}
编译成功,links。 但是,如果我添加一个“重复”,如:
syntax = "proto3";
message PbCaptureResult {
bool checkedValid = 1;
}
message PbCaptureResultSequence {
repeated PbCaptureResult captureResults = 1;
}
然后我有一个 link 错误并得到:
cmd.exe /C "cd . && C:\Android\Sdk\ndk.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 文件中,但它无法编译并出现相同的 linking 错误。我断定这不是 .proto 语法问题。
这是 protobuf 3.15.5.
生成命令为:./bin/protoc.exe --cpp_out=.. CaptureResultSequence.proto
我是静态的link反对libprotobuf.a(不是libprotobuf-lite.a)
我自己交叉编译了protobuf
我最初认为这个问题与 linking 有关,但对我来说这并不能解释为什么我可以 link 没有“重复”但不能 link有了它。
我已经在这上面花了 2 天时间,我相信这很明显...
编辑:
确实在“repeated_field.cc”
中定义了“AddOutOfLineHelper”使用 ar x libprotobuf.a,我可以确认 repeated_field.cc.o 包含在库中。
奇怪的是,没有“重复”消息,我没有 link 问题。
我认为如果我不使用任何“重复”消息,也需要 libprotobuf.a 和 linked。也许不吧 ?我该如何检查?
根据要求。这是我的 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
并且在 Gradle 文件的 Android 侧 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}
)
经过几天的努力,问题与包含文件有关。
因为我正在为 Android 进行交叉编译,所以我没有完成“make install”步骤。在我的开发机器上安装软件包毫无意义。因此,我只是从编译文件夹中获取 .a 文件,从源代码中获取包含文件。
这是我的错误!
我必须放在已编译库中的包含文件只是在 src/include 文件夹中找到的所有文件的一个子集...之后听起来很明显...
因此我必须指定临时 CMAKE_INSTALL_PREFIX 和 运行 make install。然后从该位置获取包含文件夹。
然后一切正常。