2010-04-01 49 views
2

我試圖編譯一些fortran代碼,我遇到了一些令人困惑的鏈接錯誤。我有一些代碼,我編譯並放入一個靜態庫:未定義的參考

>gfortran -c -I../../inc -o bdout.o bdout.F 
>ar rv libgeo.a bdout.o 

然後我嘗試編譯針對圖書館與一些簡單的測試代碼,並得到如下:

>gfortran -o mytest -L -lgeo mytest.F 
/tmp/cc4uvcsj.o: In function `MAIN__': 
mytest.F:(.text+0xb0): undefined reference to `ncwrite1_' 
collect2: ld returned 1 exit status 

這不是在對象命名,因爲一切都看起來不錯:

>nm -u libgeo.a 

bdout.o: 
    U _gfortran_exit_i4 
    U _gfortran_st_write 
    U _gfortran_st_write_done 
    U _gfortran_transfer_character 
    U _gfortran_transfer_integer 
    U ncobjcl_ 
    U ncobjwrp_ 
    U ncopencr_ 
    U ncopenshcr_ 
    U ncopenwr_ 
    U ncwrite1_ 
    U ncwrite2_ 
    U ncwrite3_ 
    U ncwrite4_ 
    U ncwritev_ 

我可以檢查太原始對象文件:

>nm -u bdout.o 

    U _gfortran_exit_i4 
    U _gfortran_st_write 
    U _gfortran_st_write_done 
    U _gfortran_transfer_character 
    U _gfortran_transfer_integer 
    U ncobjcl_ 
    U ncobjwrp_ 
    U ncopencr_ 
    U ncopenshcr_ 
    U ncopenwr_ 
    U ncwrite1_ 
    U ncwrite2_ 
    U ncwrite3_ 
    U ncwrite4_ 
    U ncwritev_ 

測試代碼只包含在bdout.o定義的函數的單個調用:

program hello 
     print *,"Hello World!" 
     call ncwrite1(istat, f, ix2, ix3, ix4, ix5, ih) 
end program hello 

我想不通的問題是什麼。有沒有人有什麼建議?甚至可能只是一種追蹤問題的方法?

乾杯。

回答

0

首先,感謝大家的回答。我正在發佈,以便正式結束此主題。事實證明,編寫庫(libgeo.a)的人已經在使用編譯器標誌宏-D(宏)打開的代碼中放置了多個#ifdef語句。這些#ifdef將被用於擴展具有特定參數的函數名稱。如果不向編譯器提供適當的宏,則函數名稱未被展開,因此符號未定義。 Grrrr ...

1

不知道這是否有助於解決這個特定問題,但一般情況下,始終在目標文件之後放置鏈接器命令。其次,如果libgeo.a位於當前目錄中,則需要明確添加,空的-L AFAIK什麼也不做。即

gfortran -o mytest mytest.F -L. -lgeo 

編輯:另請注意,nm輸出中的「U」表示符號未定義。即.o文件引用所述符號,但該符號實際上是在其他文件中。即您可能需要在定義ncwrite1_符號的庫中顯式鏈接。

+0

是的,我只是試圖把鏈接器命令最後但問題仍然存在。-L。意味着-L在。 (當前)目錄。 – Brandon 2010-04-01 20:48:43

+0

我的意思是,在你的問題中你有一個空的-L,沒有「。」 – janneb 2010-04-01 21:25:34

+0

對不起,沒有注意到。它在輸入問題時丟失了。顯然這也不是問題。 – Brandon 2010-04-02 01:22:52

0

問題可能是對ncwrite1的調用與子例程的庫定義的簽名不匹配,以及錯誤消息實際試圖告訴您的是它無法找到具有簽名的ncwrite1版本以匹配呼叫。你的程序似乎沒有使用ncwrite1的顯式接口,所以類似這樣的錯誤不會在編譯時被捕獲。

1

問題是,您沒有鏈接到包含該函數的。這有兩個可能的原因:

  1. ncwrite1功能是不是在你鏈接的庫定義。使用nm來驗證這是(或不是)的情況。
  2. 這些庫位於命令行(!)上的對象/源代碼文件之前。連接器是有史以來最愚蠢的事情,並且不會試圖解決所有其他問題(並且這對於高級技術偶爾也是有用的)但這意味着您需要將庫放在其他所有內容之後。如果有多個庫,則需要對它們之間的依賴關係使用拓撲排序,以確定將它們列出到鏈接器的正確順序。

如果我們假設地理圖書館具有您正在使用的功能(請檢查!)那麼你應該建立和鏈接像這樣:

gfortran -o mytest -L. mytest.F -lgeo