2013-03-01 58 views
3

我想學習C編程使用Zed Shaw的學習C困難的方式。我一直致力於在ex26上創建一個用於安裝軟件的程序「devpkg」。這個練習需要安裝Apache Portable Runtime庫。編寫代碼爲這項工作我不能讓程序使用下面的makefile編譯後:庫鏈接

PREFIX?=/user/local 
    CFLAGS=-g -Wall -I${PREFIX}/apr/include/apr-1 -I{PREFIX}/apr/include/apr-util-1 
    LDFLAGS=-L${PREFIX}/apr/lib -lapr-1 -pthread -laprutil-1 

    all: devpkg 

    install: all 
      install -d${DESTDIR}/${PREFIX}/bin/ 
      install devpkg ${DESTDIR}/${PREFIX}/bin/ 

    clean: 
      rm -f *.o 
      rm -f devpkg 
      rm -f *.dSYM 

這個Makefile似乎並沒有因爲當我用「$讓devpkg」不是所有的APR庫函數是工作聲明。作爲一個附註我正在Ubuntu虛擬機上運行這個。文中給出的解決方案說改變一個配置文件,然後「運行ldconfig」來幫助鏈接器找到合適的庫。
我不明白ldconfig的手冊頁足以正確使用該功能。如何正確運行ldconfig?

也經過一些挖掘,我發現在生成文件中使用「LDLIBS」而不是「LDFLAGS」的引用解決了問題。我修改了makefile和編譯的程序。

允許C編譯器正確鏈接到APR庫的「LDFLAGS」和「LDLIBS」有什麼區別?是否有一些方便的命令列表可以幫助我更好地理解makefile是如何正確生成的?

謝謝你的時間。

+2

你確定應該是'/ user/local'而不是'/ usr/local'嗎? – 2013-03-01 19:39:58

+0

是的,你是對的。不過,我在這裏犯了錯字,它不在makefile中。 – user2073935 2013-03-02 01:59:03

回答

3

GNU Make Manual,部分10.2目錄隱含規則的:

鏈接一個對象文件
n自動從n.o通過運行所述接頭製成(通常稱爲ld)通過C編譯器。使用的精確配方是'$(CC) $(LDFLAGS) n.o $(LOADLIBES) $(LDLIBS)'。

如您所見,LDFLAGS出現在您的目標文件和LDLIBS之後。有時候這個順序可能很重要 - 顯然它在你的情況下。

編者注:雖然使用make的隱式規則支持有時可能會很方便,但它總是會導致更多的混淆。我會敦促你寫一個完整的makefile - 它會幫助你更好地理解發生了什麼,並希望將來避免這類問題。

+0

謝謝,我想我現在明白了。也感謝你指點我的GNU make手冊。我會嘗試重寫makefile。 – user2073935 2013-03-02 02:02:29

3

我只是想添加此答案作爲將「LDFLAGS」更改爲「LDLIBS」的替代方法。上面的解決方案對我來說確實有效,但在我看到其他人可能會覺得有用或有趣的線程之前,我找到了一種替代方案(雖然不太直接)。當編譯我看到大量的「未定義的引用」的錯誤,例如:

/MyCode/LCTHW/devpkg/devpkg.c:18: undefined reference to `apr_pool_initialize' 

大量的試驗和錯誤之後,我改變了makefile文件這樣(仍在使用LDFLAGS):

CC=gcc 
PREFIX?=/usr/local 
CFLAGS=-g -Wall -I$(PREFIX)/apr/include/apr-1 -I$(PREFIX)/apr/include/apr-util-1 
LDFLAGS=-L$(PREFIX)/apr/lib -lapr-1 -laprutil-1 -pthread 
OBJECTS=bstrlib.o db.o shell.o commands.o devpkg.o 

all: devpkg 

devpkg: $(OBJECTS) 
    $(CC) $(CFLAGS) $(OBJECTS) -o devpkg $(LDFLAGS) 

install: all 
    install -d $(DESTDIR)/$(PREFIX)/bin/ 
    install devpkg $(DESTDIR)/$(PREFIX)/bin/ 

clean: 
    rm -f *.o 
    rm -f devpkg 
    rm -rf *.dSYM 

我只好再添加一個.conf文件到/etc/ld.so.conf。包含路徑四月庫,即

​​

然後d運行

sudo ldconfig 

這樣系統便拿起新的.conf文件,因此知道在哪裏可以找到庫。從我讀過的內容來看,似乎最後一步是必須的,因爲該庫不存儲在/ usr/local/lib中。如果我刪除.conf文件並重新運行ldconfig進行更新,程序將編譯,但無法在運行時找到庫(無論是使用我的makefile還是OP編譯)。

儘管我沒有完全理解我的解決方案,但它至少允許我編譯和運行程序時沒有任何錯誤。希望這個解決方案能夠引起其他人的興趣,也許更有知識的人將能夠更詳細地解釋其原因。