具體錯誤:
[cc] Starting link
[cc] /usr/bin/ld: libtest1.so: no symbol version section for versioned symbol `memcpy@GLIBC_2.0'
[cc] /usr/bin/ld: 最後的鍊結失敗: nonrepresentable section on output
[cc] collect2: error: ld returned 1 exit status
關于此類錯誤,吾有不少博文。這意思就是沒有這個函數。具體來說:
tsit@tsit-loong:~/jogamp232-loongarch64/gluegen$ strings /usr/lib/loongarch64-linux-gnu/libc.so.6 | grep GLIBCGLIBC_2.27
GLIBC_2.28
GLIBC_PRIVATE
GNU C Library (Debian GLIBC 2.28-10.lnd.26) stable release version 2.28.
sit@tsit-loong:~/jogamp232-loongarch64/gluegen$ objdump -T /usr/lib/loongarch64-linux-gnu/libc.so.6 | fgrep memcpy
000000000008d328 w DF .text 0000000000000008 GLIBC_2.27 wmemcpy
00000000000eeb78 g DF .text 000000000000001c GLIBC_2.27 __wmemcpy_chk
0000000000086588 g DF .text 00000000000003f4 GLIBC_2.27 memcpy
00000000000ed228 g DF .text 0000000000000014 GLIBC_2.27 __memcpy_chk
也就是連結時要求使用2.0,實際上是2.27。
- 解決辦法一
加連結庫,下文中三個逐個加試試:
g++ -o main main.c -lm -ldl -lrt
有時确實可以解決問題。
- 解決辦法二
g++ -Wl,--no-as-needed -o main main.c -lm -ldl -lrt
- 終極解決辦法
回到問題本身。我們平常調用函數memcpy,不管怎麼編譯,并不會出現這個問題。出問題的都是下載下傳的源碼編譯時。這就有意思了,為什麼會出現這個錯誤?一定是代碼寫法不同導緻的。
基于這個思路,我們來搜尋一下GLIBC,果然發現了一個檔案glibc-compat-symbols.h,内容是:
#ifndef __GLIBC_COMPAT_SYMBOLS_H__
#define __GLIBC_COMPAT_SYMBOLS_H__ 1
/**
*
* Note: Patching a specific glibc symbol version is only required if *not* statically linking glibc,
* which should be preferred.
*
* Note: JogAmp's minimum GLIBC is 2.4 due to '__stack_chk_fail' (stack overflow checking)
*
* GLIBC 2.4 - March 2006 - Standard for LSB 4.0, Used in SLES 10
*
* We could add compile/link option '-fno-stack-protector', however stack protection seems reasonable
* and a pre 2006 distribution a bit too 'far fetched' for our multimedia bindings anyway.
*
* Check build-in macro definitions via 'gcc -dM -E - < /dev/null'
*/
#if defined(__linux__) /* Actually we like to test whether we link against GLIBC .. */
#if defined(__GNUC__)
#if defined(__aarch64__)
#define GLIBC_COMPAT_SYMBOL(FFF) __asm__(".symver " #FFF "," #FFF "@GLIBC_2.4");
#elif defined(__arm__)
#define GLIBC_COMPAT_SYMBOL(FFF) __asm__(".symver " #FFF "," #FFF "@GLIBC_2.4");
#elif defined(__amd64__)
#define GLIBC_COMPAT_SYMBOL(FFF) __asm__(".symver " #FFF "," #FFF "@GLIBC_2.2.5");
#else
#define GLIBC_COMPAT_SYMBOL(FFF) __asm__(".symver " #FFF "," #FFF "@GLIBC_2.0");
#endif /*__amd64__*/
#elif defined(__clang__)
#if defined(__aarch64__)
#define GLIBC_COMPAT_SYMBOL(FFF) asm(".symver " #FFF "," #FFF "@GLIBC_2.4");
#elif defined(__arm__)
#define GLIBC_COMPAT_SYMBOL(FFF) asm(".symver " #FFF "," #FFF "@GLIBC_2.4");
#elif defined(__amd64__)
#define GLIBC_COMPAT_SYMBOL(FFF) asm(".symver " #FFF "," #FFF "@GLIBC_2.2.5");
#else
#define GLIBC_COMPAT_SYMBOL(FFF) asm(".symver " #FFF "," #FFF "@GLIBC_2.0");
#endif /*__amd64__*/
#else
#warning GLIBC_COMPAT_SYMBOL not supported with current compiler on GNU/Linux
#define GLIBC_COMPAT_SYMBOL(FFF)
#endif
#else
#warning GLIBC_COMPAT_SYMBOL not supported with target OS
#define GLIBC_COMPAT_SYMBOL(FFF)
#endif
GLIBC_COMPAT_SYMBOL(memcpy)
#endif /*__GLIBC_COMPAT_SYMBOLS_H__*/
其中果然有一個字串叫GLIBC_2.0。這不就好辦了嘛。
辦法一:把2.0改成2.27(或相應的字串)。
辦法二:幹脆改為""。這樣到哪裡編譯都皆大歡喜。