2013-03-29 57 views
6

我連接外部庫(通過wierd進程,mpicc + Cython +等), 但我有一個奇怪的行爲的鏈接過程。奇怪的鏈接行爲和未定義的符號

有兩個.o文件,libpetsc4py.o和PETSc.o 它們連接成一個.so文件PETSc.so

一個包含未定義的符號__pyx_tp_new_8petsc4py_5PETSc_Object

[[email protected] src]$ nm libpetsc4py.o | grep __pyx_tp_new_8petsc4py_5PETSc_Object 
         U __pyx_tp_new_8petsc4py_5PETSc_Object 

它被定義在另一.o文件將:

[[email protected] src]$ nm PETSc.o | grep __pyx_tp_new_8petsc4py_5PETSc_Object 
00000000001b92f0 t __pyx_tp_new_8petsc4py_5PETSc_Object 

然後,再將連接完成(編譯行是奇怪,不好意思)

mpicc -pthread -fPIC -wd1572 -g -shared -fno-strict-aliasing -g -O2 -DNDEBUG -O2 -g 
build/temp.linux-x86_64-2.7/arch-linux2-c-debug/src/PETSc.o build/temp.linux-x86_64- 
2.7/arch- linux2-c-debug/src/libpetsc4py.o -L/home/users/zheltkov/tmp/petsc-3.3/arch 
-linux2-c-debug/lib -L/home/users/zheltkov/ivan/soft/epd7.2/lib 
-Wl,rpath,/home/users/zheltkov/tmp/petsc-3.3/arch-linux2-c-debug/lib 
-Wl,-rpath,/home/users/zheltkov/ivan/soft/epd7.2/lib -lpetsc -lpython2.7 -o 
build/lib.linux-x86_64-2.7/petsc4py/lib/a rch-linux2-c-debug/PETSc.so -lX11 -Wl, 
-rpath,/home/users/zheltkov/tmp/petsc-3.3/arch-linux2-c-debug/lib 
-L/home/users/zheltkov/tmp/petsc-3.3/arch-linux2-c-debug/lib -lfftw3_mpi -lfftw3 -lHYPRE 
-Wl,-rpath,/opt/intel/impi/4.1.0.030/intel64/lib 
-L/opt/intel/impi/4.1.0.030/intel64/lib -Wl, 
-rpath,/opt/intel/composer_xe_2013.2.146/mkl/lib/intel64 
-L/opt/intel/composer_xe_2013.2.146/mkl/lib/intel64 
-Wl,-rpath,/opt/intel/composer_xe_2013.2.146/compiler/lib/intel64 
-L/opt/intel/composer_xe_2013.2.146/compiler/lib/intel64 -Wl, 
-rpath,/usr/lib/gcc/x86_64-redhat-linux/4.4.6 -L/usr/lib/gcc/x86_64-redhat-linux/4.4.6 
-Wl,- rpath,/mnt/data/users/dm4/vol9/zheltkov/tmp/petsc-3.3/-Xlinker -lmpigc4 
-Wl,-rpath,/opt/intel/mpi-rt/4.1 -lml -lpthread -Wl,-rpath, 
/opt/intel/composer_xe_2013/mkl/lib/intel64 
-L/opt/intel/composer_xe_2013/mkl/lib/intel64 -lmkl_intel_lp64 -lmkl_intel_thread 
-lmkl_core -liomp5 -lifport -lifcore -lm -ldl -lmpigf -lmpi_dbg -lmpigi -lrt 
-limf -lsvml -lirng -lipgo -ldecimal -lcilkrts -lstdc++  -lgcc_s -lirc -lirc_s 

但最後,生成的文件具有相同名稱,其中一人是不確定的,一切都不起作用兩個符號:

[[email protected] arch-linux2-c-debug]$ nm PETSc.so | grep __pyx_tp_new_8petsc4py_5PETSc_Object 
0000000000200d20 t __pyx_tp_new_8petsc4py_5PETSc_Object 
       U __pyx_tp_new_8petsc4py_5PETSc_Object 

我在做什麼錯?爲什麼有兩個同名的符號?

回答

7

在目標文件t中,表示該函數具有內部鏈接(即聲明爲static),而在另一個文件中,U表示函數被引用但未定義。外部功能用T表示。

當您鏈接到創建共享庫時,鏈接器不會抱怨未解析的引用,因此它包含靜態函數(僅在定義它的文件中可用)和標記爲未定義的外部符號。

這是一個更簡單的例子。兩個文件:

foo.c的

#include <stdio.h> 

static void hello(void) 
{ 
    printf("Hello\n"); 
} 

bar.c

void sayhello(void) 
{ 
    hello(); 
} 

編譯兩個:

$ gcc -c -fPIC foo.c 
$ gcc -c -fPIC bar.c 
$ nm foo.o 
0000000000000000 t hello 
$ nm bar.o 
       U hello 
0000000000000000 T sayhello 

現在創建一個共享庫

$ gcc -shared -o libhello.so foo.o bar.o 
$ nm libhello.so 
0000000000000700 t hello 
       U hello 

這樣做的結果是,如果我定義函數hello並鏈接到該庫以創建可執行文件,庫將在sayhello中調用我的函數 - 而不是靜態函數。如果我沒有定義它,鏈接器會給出一個未定義的符號錯誤。

+0

值得注意的是,外部符號的類型應該是'T'(而不是't')。 – shakurov

+0

@shakurov - 添加。 – teppic