一、問題引入
1、頭文件與庫
當我們在PC主機linux環境下(如ubuntu),編寫linux應用程序,然后利用gcc來編譯。在源代碼的開始位置會寫入頭文件,那是因為我們使用了系統提供的庫函數,例如printf、open、read、write等等。我們會寫入類似的內容:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> ......
我們的應用程序代碼編譯過程大概是這樣的:編譯器根據頭文件提供的庫函數接口形式,來編譯我們的代碼(如果不知道調用庫函數的形式,eg:參數個數、形式、返回值類型等,將無法對庫函數調用的代碼進行編譯),然后生成目標文件;然后,再使用鏈接器將這個目標文件與系統庫鏈接;最終生成我們需要的應用程序。所以,其實我們的代碼包含了自己寫的內容,還有系統為我們提供好的現成的庫函數,整個結合起來才形成一個完整的程序。
庫函數的頭文件,在編譯的時候被使用,而庫函數的代碼段(庫文件),在鏈接的時候被使用。
example:
應用程序代碼在使用一個系統調用的時候,例如printf()函數,需要指定包含的頭文件stdio.h;另外,在鏈接的時候對應的鏈接libc.a(筆者電腦文件所在目錄:/usr/lib/i386-linux-gnu/libc.a)。
總結一下,我們編寫應用程序,需要使用linux系統提供的庫函數。具體實現起來,需要頭文件和庫文件。頭文件是需要我們編寫應用程序的時候,在源文件開頭添加的;而庫文件則需要配置編譯環境進行指定搜索目錄。
2、頭文件和庫文件在哪兒?
編寫linux本機的應用程序、目標開發板的應用程序以及目標開發板的驅動,都會使用庫函數,那么這些情況的頭文件和庫文件在哪兒放着呢?
不知道這個問題,在編寫代碼時會有疑惑。比如說,編寫目標開發板的應用程序時,使用了open、read、write等函數。於是,想在linux內核開發的源碼包(驅動開發環境)里邊找到這些函數的完整代碼,或者降低要求,查看頭文件里的函數聲明。結果令人失望,找不到需要的頭文件能提供這樣的函數聲明。這樣造成我們不知道該如何使用這些庫函數。
事實情況是,上邊列出常見的3種編程情況,所使用的頭文件和庫文件位置都不一樣。也就是說,上述3種編程情況,所使用的庫函數調用有可能是相同的,但是庫函數所在的頭文件以及對應的庫,所在的位置卻不一樣。所以,編寫目標開發板的應用程序時,在內核開發的源碼包(驅動開發環境)中,找不到我們需要的頭文件。
下面,根據不同的編程情況,進行說明。
二、編寫linux本機的應用程序
查看命令
#echo 'main(){}'|gcc -E -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' --with-bugurl=file:///usr/share/doc/gcc-4.6/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.6 --enable-shared --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.6 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --enable-plugin --enable-objc-gc --enable-targets=all --disable-werror --with-arch-32=i686 --with-tune=generic --enable-checking=release --build=i686-linux-gnu --host=i686-linux-gnu --target=i686-linux-gnu Thread model: posix gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5) COLLECT_GCC_OPTIONS='-E' '-v' '-mtune=generic' '-march=i686' /usr/lib/gcc/i686-linux-gnu/4.6/cc1 -E -quiet -v -imultilib . -imultiarch i386-linux-gnu - -mtune=generic -march=i686 -fstack-protector ignoring nonexistent directory "/usr/local/include/i386-linux-gnu" ignoring nonexistent directory "/usr/lib/gcc/i686-linux-gnu/4.6/../../../../i686-linux-gnu/include" #include "..." search starts here: #include <...> search starts here: /usr/lib/gcc/i686-linux-gnu/4.6/include /usr/local/include /usr/lib/gcc/i686-linux-gnu/4.6/include-fixed /usr/include/i386-linux-gnu /usr/include End of search list. # 1 "<stdin>" # 1 "<built-in>" # 1 "<command-line>" # 1 "<stdin>" main{} COMPILER_PATH=/usr/lib/gcc/i686-linux-gnu/4.6/:/usr/lib/gcc/i686-linux-gnu/4.6/:/usr/lib/gcc/i686-linux-gnu/:/usr/lib/gcc/i686-linux-gnu/4.6/:/usr/lib/gcc/i686-linux-gnu/ LIBRARY_PATH=/usr/lib/gcc/i686-linux-gnu/4.6/:/usr/lib/gcc/i686-linux-gnu/4.6/../../../i386-linux-gnu/:/usr/lib/gcc/i686-linux-gnu/4.6/../../../../lib/:/lib/i386-linux-gnu/:/lib/../lib/:/usr/lib/i386-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/i686-linux-gnu/4.6/../../../:/lib/:/usr/lib/ COLLECT_GCC_OPTIONS='-E' '-v' '-mtune=generic' '-march=i686'
可見頭文件的搜索路徑如下(具體搜索路徑,要看個人的實際情況,以命令運行的結果為准):
/usr/lib/gcc/i686-linux-gnu/4.6/include /usr/local/include /usr/lib/gcc/i686-linux-gnu/4.6/include-fixed /usr/include/i386-linux-gnu /usr/include
三、目標開發板的應用程序
查看命令
#echo 'main(){}'|arm-linux-gcc -E -v -
顯示結果
Using built-in specs. Target: arm-none-linux-gnueabi Configured with: /scratch/maxim/arm-lite/src-4.3-arm-none-linux-gnueabi-lite/gcc-4.3/configure --build=i686-pc-linux-gnu --host=i686-pc-linux-gnu --target=arm-none-linux-gnueabi --enable-threads --disable-libmudflap --disable-libssp --disable-libstdcxx-pch --with-gnu-as --with-gnu-ld --with-specs='%{funwind-tables|fno-unwind-tables|mabi=*|ffreestanding|nostdlib:;:-funwind-tables}' --enable-languages=c,c++ --enable-shared --enable-symvers=gnu --enable-__cxa_atexit --with-pkgversion='Sourcery G++ Lite 2009q1-176' --with-bugurl=https://support.codesourcery.com/GNUToolchain/ --disable-nls --prefix=/opt/codesourcery --with-sysroot=/opt/codesourcery/arm-none-linux-gnueabi/libc --with-build-sysroot=/scratch/maxim/arm-lite/install-4.3-arm-none-linux-gnueabi-lite/arm-none-linux-gnueabi/libc --with-gmp=/scratch/maxim/arm-lite/obj-4.3-arm-none-linux-gnueabi-lite/host-libs-2009q1-176-arm-none-linux-gnueabi-i686-pc-linux-gnu/usr --with-mpfr=/scratch/maxim/arm-lite/obj-4.3-arm-none-linux-gnueabi-lite/host-libs-2009q1-176-arm-none-linux-gnueabi-i686-pc-linux-gnu/usr --disable-libgomp --enable-poison-system-directories --with-build-time-tools=/scratch/maxim/arm-lite/install-4.3-arm-none-linux-gnueabi-lite/arm-none-linux-gnueabi/bin --with-build-time-tools=/scratch/maxim/arm-lite/install-4.3-arm-none-linux-gnueabi-lite/arm-none-linux-gnueabi/bin Thread model: posix gcc version 4.3.3 (Sourcery G++ Lite 2009q1-176) COLLECT_GCC_OPTIONS='-march=armv4t' '-E' '-v' '-funwind-tables' /opt/EmbedSky/4.3.3/bin/../libexec/gcc/arm-none-linux-gnueabi/4.3.3/cc1 -E -quiet -v -imultilib armv4t -iprefix /opt/EmbedSky/4.3.3/bin/../lib/gcc/arm-none-linux-gnueabi/4.3.3/ -isysroot /opt/EmbedSky/4.3.3/bin/../arm-none-linux-gnueabi/libc - -march=armv4t -funwind-tables ignoring nonexistent directory "/opt/EmbedSky/4.3.3/bin/../arm-none-linux-gnueabi/libc/usr/local/include" ignoring duplicate directory "/opt/EmbedSky/4.3.3/bin/../lib/gcc/../../lib/gcc/arm-none-linux-gnueabi/4.3.3/include" ignoring duplicate directory "/opt/EmbedSky/4.3.3/bin/../lib/gcc/../../lib/gcc/arm-none-linux-gnueabi/4.3.3/include-fixed" ignoring duplicate directory "/opt/EmbedSky/4.3.3/bin/../lib/gcc/../../lib/gcc/arm-none-linux-gnueabi/4.3.3/../../../../arm-none-linux-gnueabi/include" #include "..." search starts here: #include <...> search starts here: /opt/EmbedSky/4.3.3/bin/../lib/gcc/arm-none-linux-gnueabi/4.3.3/include /opt/EmbedSky/4.3.3/bin/../lib/gcc/arm-none-linux-gnueabi/4.3.3/include-fixed /opt/EmbedSky/4.3.3/bin/../lib/gcc/arm-none-linux-gnueabi/4.3.3/../../../../arm-none-linux-gnueabi/include /opt/EmbedSky/4.3.3/bin/../arm-none-linux-gnueabi/libc/usr/include End of search list. # 1 "<stdin>" # 1 "<built-in>" # 1 "<command-line>" # 1 "<stdin>" main{} COMPILER_PATH=/opt/EmbedSky/4.3.3/bin/../libexec/gcc/arm-none-linux-gnueabi/4.3.3/:/opt/EmbedSky/4.3.3/bin/../libexec/gcc/:/opt/EmbedSky/4.3.3/bin/../lib/gcc/arm-none-linux-gnueabi/4.3.3/../../../../arm-none-linux-gnueabi/bin/ LIBRARY_PATH=/opt/EmbedSky/4.3.3/bin/../lib/gcc/arm-none-linux-gnueabi/4.3.3/armv4t/:/opt/EmbedSky/4.3.3/bin/../lib/gcc/arm-none-linux-gnueabi/4.3.3/../../../../arm-none-linux-gnueabi/lib/armv4t/:/opt/EmbedSky/4.3.3/bin/../lib/gcc/arm-none-linux-gnueabi/4.3.3/:/opt/EmbedSky/4.3.3/bin/../lib/gcc/:/opt/EmbedSky/4.3.3/bin/../lib/gcc/arm-none-linux-gnueabi/4.3.3/../../../../arm-none-linux-gnueabi/lib/:/opt/EmbedSky/4.3.3/bin/../arm-none-linux-gnueabi/libc/armv4t/lib/:/opt/EmbedSky/4.3.3/bin/../arm-none-linux-gnueabi/libc/armv4t/usr/lib/ COLLECT_GCC_OPTIONS='-march=armv4t' '-E' '-v' '-funwind-tables'
可見頭文件的搜索路徑如下(具體搜索路徑,要看個人的實際情況,以命令運行的結果為准):
/opt/EmbedSky/4.3.3/bin/../lib/gcc/arm-none-linux-gnueabi/4.3.3/include
/opt/EmbedSky/4.3.3/bin/../lib/gcc/arm-none-linux-gnueabi/4.3.3/include-fixed /opt/EmbedSky/4.3.3/bin/../lib/gcc/arm-none-linux-gnueabi/4.3.3/../../../../arm-none-linux-gnueabi/include /opt/EmbedSky/4.3.3/bin/../arm-none-linux-gnueabi/libc/usr/include
四、linux內核開發(如驅動)
在參考文章《gcc 和 arm-linux-gcc 編譯器的默認搜索頭文件路徑》中,指出由內核編譯的Makefile等編譯規則指定。我個人覺得編譯的頭文件得搜索路徑,還是應在linux內核開發的源碼包中,例如主要集中區include目錄下。