最近更新: 2015-05-29

GCC 4.6 Linker Argument Picky

最近公司有一些 C 程式碼在 Ubuntu 12.04 上編譯時發生目標參照錯誤。原因在於 Ubuntu 12.04 採用的 gcc 4.6 有一項特殊的參數順序要求(argument picky),這個中間版本一定要把 linker 參數放最後面。這項要求在舊版沒有(~ 4.4),後來的 gcc 新版(4.8, 4.9)也拿掉了。所以 gcc 4.6 以外的版本, linker 參數順序怎麼放都行。

gcc 常見的 linker 參數有 -l, -L, -Wl 。

Debian gcc list: https://packages.debian.org/search?keywords=gcc

  • squeeze (v6): 4.4.5
  • wheezy (v7): 4.7.2 (x86 arch)
  • jessie (v8): 4.9.2

Ubuntu gcc list:

  • lucid (10.04): 4.4.3
  • precise (12.04): 4.6.3
  • trusty (14.04): 4.8.2

我這幾年的主要開發環境是在 Debian 上,剛好跳過 gcc 4.6 。現在想想,2011,2012 年時,確實有不少 gcc 用家抱怨過這件事。所以後來才又取消了這項限制吧。

我做了一些測試確認 gcc 參數順序限制:


// test.c
#include <glib.h>
#include <stdio.h>

int main()
{
    char *s = g_strdup_printf("test %s\n", "hello");
    puts(s);
    g_free(s);
    return 0;
}
Ubuntu 10.04
ubuntu-lucid-vm:~$ gcc -v
Using built-in specs.
Target: i486-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.4.3-4ubuntu5.1'
Thread model: posix
gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5.1)

ubuntu-lucid-vm:~$ ld -v
GNU ld (GNU Binutils for Ubuntu) 2.20.1-system.20100303

# Work
ubuntu-lucid-vm:~$ gcc `pkg-config --cflags --libs glib-2.0` -o test test.c

# Work
ubuntu-lucid-vm:~$ gcc `pkg-config --cflags glib-2.0` -o test test.c \
  `pkg-config --libs glib-2.0`
Ubuntu 12.04
ubuntu12-vm:~$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/i686-linux-gnu/4.6/lto-wrapper
Target: i686-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu/Linaro 4.6.3-1ubuntu5'
Thread model: posix
gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5)

ubuntu12-vm:~$ ld -v
GNU ld (GNU Binutils for Ubuntu) 2.22

# Failed. You should put linker arguments in last part.
ubuntu12-vm:~$ gcc `pkg-config --cflags --libs glib-2.0` -o test test.c
/tmp/cc5BM90K.o: In function `main':
test.c:(.text+0x19): undefined reference to `g_strdup_printf'
test.c:(.text+0x35): undefined reference to `g_free'
collect2: ld returned 1 exit status

# Work
ubuntu12-vm:~$ gcc `pkg-config --cflags glib-2.0` -o test test.c \
  `pkg-config --libs glib-2.0`

Debian 6
debian6-vm:~$ gcc -v
Using built-in specs.
Target: i486-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Debian 4.4.5-8'
Thread model: posix
gcc version 4.4.5 (Debian 4.4.5-8)

debian6-vm:~$ ld -v
GNU ld (GNU Binutils for Debian) 2.20.1-system.20100303

# Work
debian6-vm:~$ gcc `pkg-config --cflags --libs glib-2.0` -o test test.c

# Work
debian6-vm:~$ gcc `pkg-config --cflags glib-2.0` -o test test.c \
  `pkg-config --libs glib-2.0`

Debian 8
desktop:~$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.9/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Debian 4.9.2-10'
Thread model: posix
gcc version 4.9.2 (Debian 4.9.2-10)

desktop:~$ ld -v
GNU ld (GNU Binutils for Debian) 2.25

# Work
desktop:~$ gcc `pkg-config --cflags --libs glib-2.0` -o test test.c

# Work
desktop:~$ gcc `pkg-config --cflags glib-2.0` -o test test.c \
  `pkg-config --libs glib-2.0`

See also: Undefined reference gcc 4.6

樂多舊網址: http://blog.roodo.com/rocksaying/archives/44517666.html