gcc这几年发展很快,C++20标准之后,gcc版本也随之到了GCC11了,老的代码还是在C++11的标准上,使用-std=c++11来进行编译。
编译当前GRPC的最新版本时,发现所依赖的abseil-cpp有一些问题,编译xxx的时候出现如下错误:
/usr/bin/ld: libgrpc.so.18.0.0: undefined reference to `absl::lts_20210324::numbers_internal::safe_strto64_base(absl::lts_20210324::string_view, long*, int)'
/usr/bin/ld: libgrpc.so.18.0.0: undefined reference to `absl::lts_20210324::EndsWithIgnoreCase(absl::lts_20210324::string_view, absl::lts_20210324::string_view)'
/usr/bin/ld: libgrpc.so.18.0.0: undefined reference to `absl::lts_20210324::numbers_internal::safe_strtou64_base(absl::lts_20210324::string_view, unsigned long*, int)'
/usr/bin/ld: libgpr.so.18.0.0: undefined reference to `absl::lts_20210324::Cord::GetFlatAux(absl::lts_20210324::cord_internal::CordRep*, absl::lts_20210324::string_view*)'
/usr/bin/ld: libgrpc.so.18.0.0: undefined reference to `absl::lts_20210324::string_view::find_first_of(absl::lts_20210324::string_view, unsigned long) const'
/usr/bin/ld: libgrpc.so.18.0.0: undefined reference to `absl::lts_20210324::StartsWithIgnoreCase(absl::lts_20210324::string_view, absl::lts_20210324::string_view)'
/usr/bin/ld: libgrpc.so.18.0.0: undefined reference to `absl::lts_20210324::optional_internal::throw_bad_optional_access()'
/usr/bin/ld: libgrpc.so.18.0.0: undefined reference to `absl::lts_20210324::numbers_internal::safe_strtou32_base(absl::lts_20210324::string_view, unsigned int*, int)'
/usr/bin/ld: libgrpc.so.18.0.0: undefined reference to `absl::lts_20210324::Status::SetPayload(absl::lts_20210324::string_view, absl::lts_20210324::Cord)'
/usr/bin/ld: libgrpc.so.18.0.0: undefined reference to `absl::lts_20210324::StrReplaceAll[abi:cxx11](absl::lts_20210324::string_view, std::initializer_list<std::pair<absl::lts_20210324::string_view, absl::lts_20210324::string_view> >)'
/usr/bin/ld: libgrpc.so.18.0.0: undefined reference to `absl::lts_20210324::string_view::find(absl::lts_20210324::string_view, unsigned long) const'
/usr/bin/ld: libgrpc.so.18.0.0: undefined reference to `absl::lts_20210324::Base64Escape[abi:cxx11](absl::lts_20210324::string_view)'
/usr/bin/ld: libgrpc.so.18.0.0: undefined reference to `absl::lts_20210324::BytesToHexString[abi:cxx11](absl::lts_20210324::string_view)'
/usr/bin/ld: libgrpc.so.18.0.0: undefined reference to `absl::lts_20210324::InternalError(absl::lts_20210324::string_view)'
/usr/bin/ld: libgrpc.so.18.0.0: undefined reference to `absl::lts_20210324::string_view::rfind(char, unsigned long) const'
/usr/bin/ld: libgrpc.so.18.0.0: undefined reference to `bool absl::lts_20210324::str_format_internal::FormatArgImpl::Dispatch<absl::lts_20210324::string_view>(absl::lts_20210324::str_format_internal::FormatArgImpl::Data, absl::lts_20210324::str_format_internal::FormatConversionSpecImpl, void*)'
/usr/bin/ld: libgrpc.so.18.0.0: undefined reference to `absl::lts_20210324::ByChar::Find(absl::lts_20210324::string_view, unsigned long) const'
/usr/bin/ld: libgpr.so.18.0.0: undefined reference to `absl::lts_20210324::CHexEscape[abi:cxx11](absl::lts_20210324::string_view)'
/usr/bin/ld: libgrpc.so.18.0.0: undefined reference to `absl::lts_20210324::FailedPreconditionError(absl::lts_20210324::string_view)'
/usr/bin/ld: libgrpc.so.18.0.0: undefined reference to `absl::lts_20210324::strings_internal::CatPieces[abi:cxx11](std::initializer_list<absl::lts_20210324::string_view>)'
/usr/bin/ld: libgpr.so.18.0.0: undefined reference to `absl::lts_20210324::Status::ForEachPayload(std::function<void (absl::lts_20210324::string_view, absl::lts_20210324::Cord const&)> const&) const'
/usr/bin/ld: libgpr.so.18.0.0: undefined reference to `absl::lts_20210324::Cord::Cord(absl::lts_20210324::string_view)'
/usr/bin/ld: libgrpc.so.18.0.0: undefined reference to `absl::lts_20210324::ParseTime(absl::lts_20210324::string_view, absl::lts_20210324::string_view, absl::lts_20210324::Time*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*)'
/usr/bin/ld: libgrpc.so.18.0.0: undefined reference to `absl::lts_20210324::InvalidArgumentError(absl::lts_20210324::string_view)'
/usr/bin/ld: libgrpc.so.18.0.0: undefined reference to `absl::lts_20210324::NotFoundError(absl::lts_20210324::string_view)'
/usr/bin/ld: libgrpc.so.18.0.0: undefined reference to `absl::lts_20210324::string_view::find_first_not_of(absl::lts_20210324::string_view, unsigned long) const'
/usr/bin/ld: libgrpc.so.18.0.0: undefined reference to `absl::lts_20210324::UnavailableError(absl::lts_20210324::string_view)'
/usr/bin/ld: libgrpc.so.18.0.0: undefined reference to `absl::lts_20210324::UnimplementedError(absl::lts_20210324::string_view)'
/usr/bin/ld: libgrpc.so.18.0.0: undefined reference to `absl::lts_20210324::FormatTime[abi:cxx11](absl::lts_20210324::string_view, absl::lts_20210324::Time, absl::lts_20210324::TimeZone)'
/usr/bin/ld: libgrpc.so.18.0.0: undefined reference to `absl::lts_20210324::EqualsIgnoreCase(absl::lts_20210324::string_view, absl::lts_20210324::string_view)'
/usr/bin/ld: libgrpc.so.18.0.0: undefined reference to `absl::lts_20210324::Status::Status(absl::lts_20210324::StatusCode, absl::lts_20210324::string_view)'
/usr/bin/ld: libgrpc.so.18.0.0: undefined reference to `absl::lts_20210324::CUnescape(absl::lts_20210324::string_view, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*)'
/usr/bin/ld: libgrpc.so.18.0.0: undefined reference to `absl::lts_20210324::Status::GetPayload(absl::lts_20210324::string_view) const'
/usr/bin/ld: libgrpc.so.18.0.0: undefined reference to `absl::lts_20210324::string_view::find(char, unsigned long) const'
/usr/bin/ld: libgrpc.so.18.0.0: undefined reference to `absl::lts_20210324::numbers_internal::safe_strto32_base(absl::lts_20210324::string_view, int*, int)'
当前认为链接选项没有加上,由于是cmake编译,打开详细编译参数,通过
make VERBOSE=1
c++ CMakeFiles/gen_hpack_tables.dir/tools/codegen/core/gen_hpack_tables.cc.o -o gen_hpack_tables -Wl,-rpath,/home/cnangel/works/grpc /usr/lib64/libprotobuf.so -ldl -lrt -lm -lpthread libgrpc.so.18.0.0 libgpr.so.18.0.0 /usr/lib64/libz.so /usr/lib64/libcares.so.2.4.3 libaddress_sorting.so.18.0.0 -pthread -lre2 libupb.so.18.0.0 -ldl -lrt -lm -lpthread /usr/lib64/libabsl_hash.so.2103.0.1 /usr/lib64/libabsl_city.so.2103.0.1 /usr/lib64/libabsl_wyhash.so.2103.0.1 /usr/lib64/libabsl_raw_hash_set.so.2103.0.1 /usr/lib64/libabsl_hashtablez_sampler.so.2103.0.1 /usr/lib64/libabsl_synchronization.so.2103.0.1 /usr/lib64/libabsl_graphcycles_internal.so.2103.0.1 /usr/lib64/libabsl_time.so.2103.0.1 /usr/lib64/libabsl_civil_time.so.2103.0.1 /usr/lib64/libabsl_time_zone.so.2103.0.1 /usr/lib64/libabsl_exponential_biased.so.2103.0.1 /usr/lib64/libabsl_statusor.so.2103.0.1 /usr/lib64/libabsl_status.so.2103.0.1 /usr/lib64/libabsl_cord.so.2103.0.1 /usr/lib64/libabsl_str_format_internal.so.2103.0.1 /usr/lib64/libabsl_bad_optional_access.so.2103.0.1 /usr/lib64/libabsl_stacktrace.so.2103.0.1 /usr/lib64/libabsl_symbolize.so.2103.0.1 /usr/lib64/libabsl_malloc_internal.so.2103.0.1 /usr/lib64/libabsl_debugging_internal.so.2103.0.1 /usr/lib64/libabsl_demangle_internal.so.2103.0.1 /usr/lib64/libabsl_strings.so.2103.0.1 /usr/lib64/libabsl_throw_delegate.so.2103.0.1 /usr/lib64/libabsl_strings_internal.so.2103.0.1 /usr/lib64/libabsl_base.so.2103.0.1 -lpthread /usr/lib64/libabsl_spinlock_wait.so.2103.0.1 /usr/lib64/libabsl_int128.so.2103.0.1 /usr/lib64/libabsl_bad_variant_access.so.2103.0.1 /usr/lib64/libabsl_raw_logging_internal.so.2103.0.1 /usr/lib64/libabsl_log_severity.so.2103.0.1 /usr/lib64/libssl.so /usr/lib64/libcrypto.so
检查发现,并没有发现问题;于是开始排查abseil-cpp的链接符号没有加入造成,通过
nm -Do /usr/lib64/libabsl_* 2>/dev/null|grep XXX # 这里填入对应的符号查询即可
发现符号都存在,且都正常,即使换上静态库也无法进行链接;那说明编译的.o文件有问题,一般是编译问题造成,检查absl和grpc的两者编译选项,发现absl-20210324.2版本已经去除了-std=c++11选项,而grpc为了保证版本gcc的兼容性,仍然使用了-std=c++11选项造成,这里没有对GCC版本做兼容,于是去除选项,整个编译过程无问题。
在GCC11.2上有这个问题,GCC8.4没有发现,GCC的man手册如下:
-std=
Determine the language standard. This option is currently only supported when compiling C or C++.The compiler can accept several base standards, such as c90 or c++98, and GNU dialects of those standards, such as gnu90 or gnu++98. When a base standard is specified, the compiler accepts all programs following that
standard plus those using GNU extensions that do not contradict it. For example, -std=c90 turns off certain features of GCC that are incompatible with ISO C90, such as the "asm" and "typeof" keywords, but not other GNU
extensions that do not have a meaning in ISO C90, such as omitting the middle term of a "?:" expression. On the other hand, when a GNU dialect of a standard is specified, all features supported by the compiler are
enabled, even when those features change the meaning of the base standard. As a result, some strict-conforming programs may be rejected. The particular standard is used by -Wpedantic to identify which features are GNU
extensions given that version of the standard. For example -std=gnu90 -Wpedantic warns about C++ style // comments, while -std=gnu99 -Wpedantic does not.
并没有说明GCC11版本对c++11的不兼容问题,但选项c++20里面有说到could change in incompatible ways in future releases.,如下图:
so, 怎么完美解决这个问题呢? 需要grpc添加一个m4宏如下:
GCC_VERSION=$(cc -dumpversion | sed 's/\([[0-9]]\{1,\}\.[[0-9]]\{1,\}\)\.*\([[0-9]]\{1,\}\)\{0,1\}/\1\2/')
CURR_MIN_VERSION=$(echo "$GCC_VERSION 5.0.0" | tr " " "\n" | sort -rV | head -n 1)
AS_IF([test "$CURR_MIN_VERSION" == '5.0.0' ], [ CXXFLAGS="${CXXFLAGS} -std=c++11" ], [])
这样达到目的。
如果没有记错的话,4.8.5开始支持cxx11。