關於apue.3e中apue.h的使用
近來要學一遍APUE第三版,並於此開博做為記錄。
先下載源文件:
1 # url: http://http//www.apuebook.com/code3e.html 2 curl -O http://www.apuebook.com/src.3e.tar.gz 3 tar -zxvf src.3e.tar.gz 4 cd apue.3e 5 ls
從上面ls的結果看,其實完全看不明白這些目錄與APUE書中代碼的關系,或者有些目錄可以猜測出是那一章。不過有個小技巧:
ls -l figlinks/
你會發現,這個目錄下全是軟鏈。通過軟鏈正好可以對應到書上的代碼。比如,書上圖1-3為ls命令的簡易實現,這正是:
# fig1.3 -> ../intro/ls1.c
先從apue.h的使用上做一說明。個人覺得有兩種方式來使用,整理如下。 至於編譯環境,本人使用Ubuntu 14.04 LTS。
一次編譯生成libapue.a文件,長久使用
代碼如下:
1 sudo apt-get install libbsd-dev 2 # 用於解決make時報:can,t find -lbsd錯誤。 3 make 4 # 編譯成功后,執行如下copy操作: 5 # libapue.a是apue.h文件的靜態鏈接庫 6 7 sudo cp ./include/apue.h /usr/include/ 8 sudo cp ./lib/libapue.a /usr/local/lib/ 9 10 # 至於為什么要放置靜態文件在上述目錄,是因為gcc在加載靜態文件時設置的從上述目錄查詢,可以通過如下文件知曉。 11 # /etc/ld.conf.d/libc.conf
下面來測試上述配置的效果。實際上,上述make時,已經將所有c文件編譯成目標文件了。可以看下各個目錄下都有相應.c文件的.o文件了。
1 gcc ls1.c 2 /tmp/ccyhkMzS.o: In function `main': 3 ls1.c:(.text+0x20): undefined reference to `err_quit' 4 ls1.c:(.text+0x5b): undefined reference to `err_sys' 5 collect2: error: ld returned 1 exit status 6 7 # 上述編譯因為沒有帶apue表態庫,所以gcc找不到APUE作者定義的錯誤處理函數,err_quit, err_sys。 8 gcc ls1.c -lapue # 帶上apue表態庫 9 ./a.out ./ 10 . 11 testerror.c 12 shell2.c 13 hello 14 # ...
如上,只有每次編譯時帶上-lapue的參數,即可以使用部署在/usr/local/lib/下的libapue.a庫。
如果你是在Mac os X 10.11系統下編譯,當copy文件到/usr/inlucde目錄時,會出現Operation not permitted報錯。
因為10.11啟動了SIP特性,即使使用sudo cp也會失敗。要關閉SIP,需要在Recovery OS環境下執行如下命令:
sudo csrutil disable
每次獨立編譯apue.h和error.c文件
第二種方式是每次單獨編譯apue,方法如下。需要先清理掉上述方法生成的編譯環境:
1 sudo rm -vf /usr/include/apue.h /usr/local/lib/libapue.a 2 make clean # 清掉之前的編譯臨時文件 3 4 cp include/apue.h ./ cp lib/error.c ./ vi apue.h 5 6 # 在最后一行的endif預編譯命令前加上一行include指令如下(包括井號): 7 #inclulde "error.c" 8 9 cp intro/ls1.c . 10 gcc -o ls ls.c 11 ./ls ./ 12 # 編譯成功,執行成功。ls1.c需要的inlucde文件都已經copy到當前目錄了
這種方式的好處是,每次編譯時,使用了apue.h中的什么文件,直接從lib/下拷到當前目錄即可,比較清楚的知道用了那些apue.h中的函數。
不足之處是每次都需要拷貝。