一、准備工作
a) 首先,你要有一台PC(這不廢話么^_^),裝好了Linux。
b) 安裝好GCC(這個指的是host gcc,用於編譯生成運行於pc機程序的)、make、ncurses等工具。
c) 下載一份純凈的Linux內核源碼包,並解壓好。
注意,如果你是為當前PC機編譯內核,最好使用相應的Linux發行版的源碼包。
不過這應該也不是必須的,因為我在我的Fedora 13上(其自帶的內核版本是2.6.33.3),就下載了一個標準的內核linux-2.6.32.65.tar.xz,並且順利的編譯安裝成功了,上電重啟都OK的。不過,我使用的.config配置文件,是Fedora 13自帶內核的配置文件,即/lib/moles/`uname -r`/build/.config
d) 如果你是移植Linux到嵌入式系統,則還要再下載安裝交叉編譯工具鏈。
例如,你的目標單板CPU可能是arm或mips等cpu,則安裝相應的交叉編譯工具鏈。安裝後,需要將工具鏈路徑添加到PATH環境變數中。例如,你安裝的是arm工具鏈,那麼你在shell中執行類似如下的命令,假如有類似的輸出,就說明安裝好了。
[root@localhost linux-2.6.33.i686]# arm-linux-gcc --version
arm-linux-gcc (Buildroot 2010.11) 4.3.5
Copyright (C) 2008 Free Software Foundation, Inc.
This is free software; see the source for ing conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
註:arm的工具鏈,可以從這里下載:回復「ARM」即可查看。
二、設置編譯目標
在配置或編譯內核之前,首先要確定目標CPU架構,以及編譯時採用什麼工具鏈。這是最最基礎的信息,首先要確定的。
如果你是為當前使用的PC機編譯內核,則無須設置。
否則的話,就要明確設置。
這里以arm為例,來說明。
有兩種設置方法():
a) 修改Makefile
打開內核源碼根目錄下的Makefile,修改如下兩個Makefile變數並保存。
ARCH := arm
CROSS_COMPILE := arm-linux-
注意,這里cross_compile的設置,是假定所用的交叉工具鏈的gcc程序名稱為arm-linux-gcc。如果實際使用的gcc名稱是some-thing-else-gcc,則這里照葫蘆畫瓢填some-thing-else-即可。總之,要省去名稱中最後的gcc那3個字母。
b) 每次執行make命令時,都通過命令行參數傳入這些信息。
這其實是通過make工具的命令行參數指定變數的值。
例如
配置內核時時,使用
make ARCH=arm CROSS_COMPILE=arm-linux- menuconfig
編譯內核時使用
make ARCH=arm CROSS_COMPILE=arm-linux-
注意,實際上,對於編譯PC機內核的情況,雖然用戶沒有明確設置,但並不是這兩項沒有配置。因為如果用戶沒有設置這兩項,內核源碼頂層Makefile(位於源碼根目錄下)會通過如下方式生成這兩個變數的值。
SUBARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \
-e s/arm.*/arm/ -e s/sa110/arm/ \
-e s/s390x/s390/ -e s/parisc64/parisc/ \
-e s/ppc.*/powerpc/ -e s/mips.*/mips/ \
-e s/sh[234].*/sh/ )
ARCH?= $(SUBARCH)
CROSS_COMPILE ?=
經過上面的代碼,ARCH變成了PC編譯機的arch,即SUBARCH。因此,如果PC機上uname -m輸出的是ix86,則ARCH的值就成了i386。
而CROSS_COMPILE的值,如果沒配置,則為空字元串。這樣一來所使用的工具鏈程序的名稱,就不再有類似arm-linux-這樣的前綴,就相當於使用了PC機上的gcc。
最後再多說兩句,ARCH的值還需要再進一步做泛化。因為內核源碼的arch目錄下,不存在i386這個目錄,也沒有sparc64這樣的目錄。
因此頂層makefile中又構造了一個SRCARCH變數,通過如下代碼,生成他的值。這樣一來,SRCARCH變數,才最終匹配到內核源碼arch目錄中的某一個架構名。
SRCARCH := $(ARCH)
ifeq ($(ARCH),i386)
SRCARCH := x86
endif
ifeq ($(ARCH),x86_64)
SRCARCH := x86
endif
ifeq ($(ARCH),sparc64)
SRCARCH := sparc
endif
ifeq ($(ARCH),sh64)
SRCARCH := sh
endif
三、配置內核
內核的功能那麼多,我們需要哪些部分,每個部分編譯成什麼形式(編進內核還是編成模塊),每個部分的工作參數如何,這些都是可以配置的。因此,在開始編譯之前,我們需要構建出一份配置清單,放到內核源碼根目錄下,命名為.config文件,然後根據此.config文件,編譯出我們需要的內核。
但是,內核的配置項太多了,一個一個配,太麻煩了。而且,不同的CPU架構,所能配置的配置項集合,是不一樣的。例如,某種CPU的某個功能特性要不要支持的配置項,就是與CPU架構有關的配置項。所以,內核提供了一種簡單的配置方法。
以arm為例,具體做法如下。
a) 根據我們的目標CPU架構,從內核源碼arch/arm/configs目錄下,找一個與目標系統最接近的配置文件(例如s3c2410_defconfig),拷貝到內核源碼根目錄下,命名為.config。
注意,如果你是為當前PC機編譯內核,最好拷貝如下文件到內核源碼根目錄下,做為初始配置文件。這個文件,是PC機當前運行的內核編譯時使用的配置文件。
/lib/moles/`uname -r`/build/.config
這里順便多說兩句,PC機內核的配置文件,選擇的功能真是多。不編不知道,一編才知道。Linux發行方這樣做的目的,可能是想讓所發行的Linux能夠滿足用戶的各種需求吧。
b) 執行make menuconfig對此配置做一些需要的修改,退出時選擇保存,就將新的配置更新到.config文件中了。
注
⑵ linux 怎樣修改編譯器的庫路徑
最簡單配置就是把連接庫目錄,添加到/etc/ld.so.conf中,一行一個目錄就行,添加完成後,執行#ldconfig更新動態連接庫。
⑶ linux 怎麼編譯c的源程序的gcc,編譯命令是什麼
在Linux下面,如果要編譯一個C語言源程序,我們要使用gcc編譯器。
先將源文件編譯成目標文件:gcc - c hello.c
生成hello.o文件,再將目標文件編譯成可執行文件:gcc -o hello hello.o
如:
int main(int argc,char **argv)
{
printf("Hello Linux ");
}
(3)linux如何編譯路徑比擴展閱讀:
在使用GCC編譯器的時候,我們必須給出一系列必要的調用參數和文件名稱。GCC編譯器的調用參數大約有100多個,這里只介紹其中最基本、最常用的參數。具體可參考GCC Manual。
GCC最基本的用法是∶gcc [options] [filenames]
其中options就是編譯器所需要的參數,filenames給出相關的文件名稱。
網路_gcc
⑷ 如何在linux平台上編譯安裝zlib軟體
1、首先是編譯環境,需要最基本的gcc,autotool工具,不同平台不同的安裝方式,具體可以網路一下
2、在linux下,開源軟體的編譯安裝會有固定的通用步驟:
下載源碼上傳到伺服器上;
解壓源碼包,一般包的後綴是tar.gz、tgz、tar.gz2,這些壓縮包其實都可以使用同一個命令進行解壓 tar xvf tarfile, 進入源碼目錄
源碼目錄下一般會有軟體相關的README、install文檔,簡單的閱讀以下,多數情況下都會有相關的編譯步驟,以及依賴庫
通過步驟:./configure;make && make install
./configure --help可以獲取幫助,用來指定安裝路徑,依賴庫的路徑,編譯選項等
3、對於在linux下編譯zlib請參考步驟2,相信你能行,加油
⑸ linux編譯的c++程序位置
linux系統編神差孫譯C++程序時頭⽂件和庫⽂件搜索路徑
C++編譯時,教科書中寫道:#include 「headfile.h」優先在當前⽬錄查找頭⽂件;#include < headfile.h>從系統默認路徑查找頭⽂件。先
前以為系統默認路徑是環境變數$PATH指定的路徑,在系統上⼀查,傻了眼:
-bash-3.2$ echo$PATH
/usr/local/bin:/bin:/usr/bin:/sbin:/usr/sbin:/usr/X11R6/bin:/usr/java/j2re1.4.0/bin:/usr/atria/bin:/ccase/bin:/home/devcomp
全是bin⽬錄,$PATH是運⾏可執⾏⽂件時的搜索路徑,與include頭⽂件的搜索路徑⽆關,可能不少⼈犯了我這樣的錯誤。
頭⽂件:
1. #include「headfile.h」
搜索順序為:
①先搜索當前⽬錄
②然後搜索-I指定的⽬錄
③再搜索gcc的環境變數CPLUS_INCLUDE_PATH(C程序使⽤的是C_INCLUDE_PATH)
④最後搜索gcc的內定⽬錄
/usr/include
/usr/local/include
/usr/lib/gcc/x86_64-redhat-linux/4.1.1/include
各⽬錄存在相同⽂件時,先找到哪個使⽤哪個。
2. #include<headfile.h>
①先搜索-I指定的⽬錄
②然後搜索gcc的環境變數CPLUS_INCLUDE_PATH
③最後搜索gcc的內定⽬錄
/usr/include
/usr/local/include
/usr/lib/gcc/x86_64-redhat-linux/4.1.1/include
與上⾯的相同,各⽬錄存在相同⽂件時,先找到哪個使⽤哪游鏈個。這⾥要注意,#include<>⽅式不會搜索當前⽬錄!
這⾥要說下include的內定⽬錄,它不是由$PATH環境變數指定的,⽽是由g++的配置prefix指定的(知道它在安裝g++時可以指定,不知安
裝後如何修改的,可能是修改配置⽂件,需要時再研究下):
-bash-3.2$ g++ -v
Using built-inspecs.
Target:x86_64-redhat-linux
Configured with:../configure --prefix=/usr --mandir=/usr/share/man--infodir=/usr/share/info --enable-shared --enable-threads=posix--enable-checking=release --with-system-zlib --enable-__cxa_atexit--disable-libunwind-exceptions --enable-libgcj-multifile--enable-languages=c,c++,objc,obj-c++,java,fortran,ada--enable-java-awt=gtk --disable-dssi --enable-plugin--with-java-home=/usr/lib/jvm/java-1.4.2-gcj-1.4.2.0/jre--with-cpu=generic --host=x86_64-redhat-linux
Thread model:posix
gcc version 4.1.2 20080704(Red Hat 4.1.2-46)
在安裝g++時,指定了prefix,那麼內定搜索⽬錄就是:
Prefix/include
Prefix/local/include
Prefix/lib/gcc/--host/--version/include
編譯時可以通過-nostdinc++選項屏蔽對內定⽬錄搜索頭⽂件。
庫⽂件:
編譯的時候:
①gcc會去找-L
②再找gcc的環境變數LIBRARY_PATH
③再找內定⽬錄/lib /usr/lib/usr/local/lib 這是當初compilegcc時寫在程序內的(不可配置的?)
運⾏時動態庫的搜索路徑:
動態庫的搜索路徑搜索的先後順序是:
①編譯⽬標代碼時指定的動態庫搜索路徑(慶跡這是通過gcc 的參數"-Wl,-rpath,"指定。當指定多個動態庫搜索路徑時,路徑之間⽤冒號":"分隔)
②環境變數LD_LIBRARY_PATH指定的動態庫搜索路徑(當通過該環境變數指定多個動態庫搜索路徑時,路徑之間⽤冒號":"分隔)
③配置⽂件/etc/ld.so.conf中指定的動態庫搜索路徑;
④默認的動態庫搜索路徑/lib;
⑤默認的動態庫搜索路徑/usr/lib。
(應注意動態庫搜尋路徑並不包括當前⽂件夾,所以當即使可執⾏⽂件和其所需的so⽂件在同⼀⽂件夾,也會出現找不到so的問題,類同#include<header_file>不搜索當前⽬錄)
¥
5
網路文庫VIP限時優惠現在開通,立享6億+VIP內容
立即獲取
linux系統編譯C++程序時頭文件和庫文件搜索路徑
linux系統編譯C++程序時頭⽂件和庫⽂件搜索路徑
C++編譯時,教科書中寫道:#include 「headfile.h」優先在當前⽬錄查找頭⽂件;#include < headfile.h>從系統默認路徑查找頭⽂件。先
前以為系統默認路徑是環境變數$PATH指定的路徑,在系統上⼀查,傻了眼:
-bash-3.2$ echo$PATH
/usr/local/bin:/bin:/usr/bin:/sbin:/usr/sbin:/usr/X11R6/bin:/usr/java/j2re1.4.0/bin:/usr/atria/bin:/ccase/bin:/home/devcomp
第 1 頁
全是bin⽬錄,$PATH是運⾏可執⾏⽂件時的搜索路徑,與include頭⽂件的搜索路徑⽆關,可能不少⼈犯了我這樣的錯誤。
頭⽂件:
1. #include「headfile.h」
搜索順序為:
①先搜索當前⽬錄
②然後搜索-I指定的⽬錄
③再搜索gcc的環境變數CPLUS_INCLUDE_PATH(C程序使⽤的是C_INCLUDE_PATH)
展開全文
限免
導長圖
轉存到網盤
發送至微信
下載文檔
北京網路網訊科技有限公司 版本號8.0.70
⑹ linux 如何運行編譯程序
gcc有多達100多個參數,現介紹常用的幾個。如果對其他參數也有興趣,可以參考:man gcc
預先處理選項
-E: 只對文件進行預處理,輸出結果到標准輸出
-C: 告訴預處理器不要丟棄注釋.配合`-E『選項使用.-P: 告訴預處理器不要產生`#line'命令.配合`-E'選項使用.
-v: 顯示正在使用的gcc的版本
常用編譯選項
-c: 將源程序編譯為目標代碼但並不做鏈接的工作,不生成最終的可執行文件,只生成一個與源文件文件名相同的以.o為後綴的目標文件。
-S:將遠程序編譯為一個後綴為.s的匯編語言文件,不會生成可執行文件
-x:強制編譯器用指定的語言編譯器來編譯某個源文件
gcc -x c++ test.c 表示強制用C++編譯器來編譯c程序
-static: 強制連接靜態庫,運行時不依賴動態庫
-share: 編譯時盡量使用動態庫
-o: 指定生成的可執行文件名,如果沒有該選項,如果生成可執行文件,默認文件名為a.out
編譯路徑選項
-i : 指定特定頭文件
gcc –c -i /home/zry/test.h test.c
-I<DIR>:依賴選項,指定頭文件路徑
Linux下大多數函數將頭文件放在/usr/include目錄下,如果需要指定其他路徑,可以使用該選項
gcc –I/home/zry/include –c test.c 添加/home/zry/include到查找路徑
-L<DIR> : 指定庫文件搜素路徑,用法同上
-l<庫名>:指定特定庫文件
gcc –lapp –c test.c
Linux的庫文件有一個約定,即以lib開頭,-lapp表示連接libapp.so庫文件
目標生成選項
-shared: 生成動態庫
gcc –shared libtest.so -i /home/zry/test.h test.c
生成靜態庫需要ar命令,後面講解
-fPIC: 生成可用於動態庫的位置獨立代碼。所有的內部定址均通過全局偏移表完成。
-ansi:支持符合ANSI標準的C程序.
該選項就會關閉GNU C中某些不兼容ANSI C的特性,例如asm, inline和 typeof關鍵字以及諸如unix和vax這些表明當前系統類型的預定義宏。
__asm__, __extension__, __inline__和__typeof__仍然有效
使用`-ansi'選項的時候,預處理器會預定義一個__STRICT_ANSI__宏.有些頭文件 關注此宏,以避免聲明某些函數,或者避免定義某些宏,這些函數和宏不被ANSI標准調用;這樣就不會干擾在其他地方使用這些名字的程序了.
fno-asm:此選項實現ansi選項的功能的一部分,它禁止將asm,inline和typeof用作關鍵字。
-fno-strict-prototype:只對g++起作用,使用這個選項,g++將對不帶參數的函數,都認為是沒有顯式的對參數的個數和類型說明,而不是沒有參數.而gcc無論是否使用這個參數,都將對沒有帶參數的函數,認為沒有顯式說明的類型
-fthis-is-varialble:就是向傳統c++看齊,可以使用this當一般變數使用
-fcond-mismatch:允許條件表達式的第二和第三參數類型不匹配,表達式的值將為void類型
-funsigned-char:
-fno-signed-char:
-fsigned-char:
-fno-unsigned-char:
這四個參數是對char類型進行設置,將char類型設置unsigned char(前兩個參數)或者 signed char(後兩個參數)
-imacros file: 將file文件的宏,擴展到gcc/g++的輸入文件,宏定義本身並不出現在輸入文件中
-Dmacro: 相當於C語言中的#define macro
-Dmacro=defn: 相當於C語言中的#define macro=defn
-Umacro: 相當於C語言中的#undef macro
-undef: 取消對任何非標准宏的定義
-M: 生成文件關聯的信息。包含目標文件所依賴的所有源代碼
-MM: 和M一樣,但是它將忽略由#include<file>造成的依賴關系。
-MD: -M相同,但是輸出將導入到.d的文件裡面
-MMD: 和-MM相同,但是輸出將導入到.d的文件裡面
警告選項
fsyntax-only:檢查程序中的語法錯誤,但是不產生輸出信息.
-w:禁止所有警告信息.
-Wno-import: 禁止所有關於#import的警告信息.
-pedantic:打開完全遵從ANSI C標准所需的全部警告診斷;拒絕接受採用了被禁止的語法擴展的程序.
-Werror:將所有警告轉換為錯誤
Werror選項要求GCC將所有警告當作錯誤進行處理。
-Wall: 顯示所有警告信息
⑺ Linux編譯C語言,源程序文件放在什麼路徑
改名:mv hello hello.c
編譯:首先cd到你源文件的那個目錄下,這樣省去了指定絕對路徑的麻煩,比如cd到桌面,然後:gcc hello.c -o hello
運行:./hello
⑻ 虛擬機Linux下編譯C語言,待編譯的文件要放在那裡路徑怎麼設置如何編譯
放哪裡都可以,進到文件所放路徑,用gcc編譯器編譯。如:gcc -o test test.c 就是說把test.c文件編譯鏈接生成test可執行程序。然後再命令:./test linux下「。/」表示運行
⑼ 要怎麼在linux系統中編譯並運行c程序
linux如何編譯c程序呢,下面就讓我們來看看吧。
1、打開Linux系統,啟動shell命令終端。
2、在終端中輸入gedithelloworld.c命令並回車。
3、進入之後進行編譯,編譯好後保存並退出。
4、輸入gcchelloworld.c命令並回車,等待編譯成功。
5、輸入命令./a.out即可運行程序。
以上就是小編的分享,希望能幫助的大家。
⑽ 如何編譯linux版本
編譯安裝內核
下載並解壓內核
內核下載官網:https://www.kernel.org/
解壓內核:tar xf linux-2.6.XX.tar.xz
定製內核:make menuconfig
參見makefile menuconfig過程講解
編譯內核和模塊:make
生成內核模塊和vmlinuz,initrd.img,Symtem.map文件
安裝內核和模塊:sudo make moles_install install
復制模塊文件到/lib/moles目錄下、復制config,vmlinuz,initrd.img,Symtem.map文件到/boot目錄、更新grub
其他命令:
make mrprobe:命令的作用是在每次配置並重新編譯內核前需要先執行「make mrproper」命令清理源代碼樹,包括過去曾經配置的內核配置文件「.config」都將被清除。即進行新的編譯工作時將原來老的配置文件給刪除到,以免影響新的內核編譯。
make dep:生成內核功能間的依賴關系,為編譯內核做好准備。
幾個重要的Linux內核文件介紹
config
使用make menuconfig 生成的內核配置文件,決定將內核的各個功能系統編譯進內核還是編譯為模塊還是不編譯。
vmlinuz 和 vmlinux
vmlinuz是可引導的、壓縮的內核,「vm」代表「Virtual Memory」。Linux 支持虛擬內存,不像老的操作系統比如DOS有640KB內存的限制,Linux能夠使用硬碟空間作為虛擬內存,因此得名「vm」。vmlinuz是可執行的Linux內核,vmlinuz的建立有兩種方式:一是編譯內核時通過「make zImage」創建,zImage適用於小內核的情況,它的存在是為了向後的兼容性;二是內核編譯時通過命令make bzImage創建,bzImage是壓縮的內核映像,需要注意,bzImage不是用bzip2壓縮的,bzImage中的bz容易引起誤解,bz表示「big zImage」,bzImage中的b是「big」意思。 zImage(vmlinuz)和bzImage(vmlinuz)都是用gzip壓縮的。它們不僅是一個壓縮文件,而且在這兩個文件的開頭部分內嵌有gzip解壓縮代碼,所以你不能用gunzip 或 gzip –dc解包vmlinuz。 內核文件中包含一個微型的gzip用於解壓縮內核並引導它。兩者的不同之處在於,老的zImage解壓縮內核到低端內存(第一個640K),bzImage解壓縮內核到高端內存(1M以上)。如果內核比較小,那麼可以採用zImage 或bzImage之一,兩種方式引導的系統運行時是相同的。大的內核採用bzImage,不能採用zImage。 vmlinux是未壓縮的內核,vmlinuz是vmlinux的壓縮文件。
initrd.img
initrd是「initial ramdisk」的簡寫。initrd一般被用來臨時的引導硬體到實際內核vmlinuz能夠接管並繼續引導的狀態。比如initrd- 2.4.7-10.img主要是用於載入ext3等文件系統及scsi設備的驅動。如果你使用的是scsi硬碟,而內核vmlinuz中並沒有這個 scsi硬體的驅動,那麼在裝入scsi模塊之前,內核不能載入根文件系統,但scsi模塊存儲在根文件系統的/lib/moles下。為了解決這個問題,可以引導一個能夠讀實際內核的initrd內核並用initrd修正scsi引導問題,initrd-2.4.7-10.img是用gzip壓縮的文件。initrd映象文件是使用mkinitrd創建的,mkinitrd實用程序能夠創建initrd映象文件,這個命令是RedHat專有的,其它Linux發行版或許有相應的命令。這是個很方便的實用程序。具體情況請看幫助:man mkinitrd
System.map是一個特定內核的內核符號表,由「nm vmlinux」產生並且不相關的符號被濾出。
下面幾行來自/usr/src/linux-2.4/Makefile:
nm vmlinux | grep -v '(compiled)|(.o$$)|( [aUw] )|(..ng$$)|(LASH[RL]DI)' | sort > System.map
在進行程序設計時,會命名一些變數名或函數名之類的符號。Linux內核是一個很復雜的代碼塊,有許許多多的全局符號, Linux內核不使用符號名,而是通過變數或函數的地址來識別變數或函數名,比如不是使用size_t BytesRead這樣的符號,而是像c0343f20這樣引用這個變數。 對於使用計算機的人來說,更喜歡使用那些像size_t BytesRead這樣的名字,而不喜歡像c0343f20這樣的名字。內核主要是用c寫的,所以編譯器/連接器允許我們編碼時使用符號名,而內核運行時使用地址。 然而,在有的情況下,我們需要知道符號的地址,或者需要知道地址對應的符號,這由符號表來完成,符號表是所有符號連同它們的地址的列表。
Linux 符號表使用到2個文件: /proc/ksyms 、System.map 。/proc/ksyms是一個「proc file」,在內核引導時創建。實際上,它並不真正的是一個文件,它只不過是內核數據的表示,卻給人們是一個磁碟文件的假象,這從它的文件大小是0可以看 出來。然而,System.map是存在於你的文件系統上的實際文件。當你編譯一個新內核時,各個符號名的地址要發生變化,你的老的System.map 具有的是錯誤的符號信息,每次內核編譯時產生一個新的System.map,你應當用新的System.map來取代老的System.map。
雖然內核本身並不真正使用System.map,但其它程序比如klogd, lsof和ps等軟體需要一個正確的System.map。如果你使用錯誤的或沒有System.map,klogd的輸出將是不可靠的,這對於排除程序故障會帶來困難。沒有System.map,你可能會面臨一些令人煩惱的提示信息。 另外少數驅動需要System.map來解析符號,沒有為你當前運行的特定內核創建的System.map它們就不能正常工作。 Linux的內核日誌守護進程klogd為了執行名稱-地址解析,klogd需要使用System.map。System.map應當放在使用它的軟體能夠找到它的地方。執行:man klogd可知,如果沒有將System.map作為一個變數的位置給klogd,那麼它將按照下面的順序,在三個地方查找System.map: /boot/System.map 、/System.map 、/usr/src/linux/System.map
System.map也有版本信息,klogd能夠智能地查找正確的映象(map)文件。
makefile menuconfig過程講解
當我們在執行make menuconfig這個命令時,系統到底幫我們做了哪些工作呢?這裡面一共涉及到了一下幾個文件我們來一一探討
Linux內核根目錄下的scripts文件夾
arch/$ARCH/Kconfig文件、各層目錄下的Kconfig文件
Linux內核根目錄下的makefile文件、各層目錄下的makefile文件
Linux內核根目錄下的的.config文件、arch/$ARCH/configs/下的文件
Linux內核根目錄下的 include/generated/autoconf.h文件
1)scripts文件夾存放的是跟make menuconfig配置界面的圖形繪制相關的文件,我們作為使用者無需關心這個文件夾的內容
2)當我們執行make menuconfig命令出現上述藍色配置界面以前,系統幫我們做了以下工作:
首先系統會讀取arch/$ARCH/目錄下的Kconfig文件生成整個配置界面選項(Kconfig是整個linux配置機制的核心),那麼ARCH環境變數的值等於多少呢?它是由linux內核根目錄下的makefile文件決定的,在makefile下有此環境變數的定義:
SUBARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \
-e s/arm.*/arm/ -e s/sa110/arm/ \
-e s/s390x/s390/ -e s/parisc64/parisc/ \
-e s/ppc.*/powerpc/ -e s/mips.*/mips/ \
-e s/sh[234].*/sh/ )
..........
export KBUILD_BUILDHOST := $(SUBARCH)
ARCH ?= $(SUBARCH)
CROSS_COMPILE ?=
或者通過 make ARCH=arm menuconfig命令來生成配置界面
比如教務處進行考試,考試科數可能有外語、語文、數學等科,這里我們選擇了arm科可進行考試,系統就會讀取arm/arm/kconfig文件生成配置選項(選擇了arm科的卷子),系統還提供了x86科、milps科等10幾門功課的考試題
3)假設教務處比較「仁慈」,為了怕某些同學做錯試題,還給我們准備了一份參考答案(默認配置選項),存放在arch/$ARCH/configs/目錄下,對於arm科來說就是arch/arm/configs文件夾:
此文件夾中有許多選項,系統會讀取哪個呢?內核默認會讀取linux內核根目錄下.config文件作為內核的默認選項(試題的參考答案),我們一般會根據開發板的類型從中選取一個與我們開發板最接近的系列到Linux內核根目錄下(選擇一個最接近的參考答案)
4).config
假設教務處留了一個心眼,他提供的參考答案並不完全正確(.config文件與我們的板子並不是完全匹配),這時我們可以選擇直接修改.config文件然後執行make menuconfig命令讀取新的選項。但是一般我們不採取這個方案,我們選擇在配置界面中通過空格、esc、回車選擇某些選項選中或者不選中,最後保存退出的時候,Linux內核會把新的選項(正確的參考答案)更新到.config中,此時我們可以把.config重命名為其它文件保存起來(當你執行make distclean時系統會把.config文件刪除),以後我們再配置內核時就不需要再去arch/arm/configs下考取相應的文件了,省去了重新配置的麻煩,直接將保存的.config文件復制為.config即可.
5)經過以上兩步,我們可以正確的讀取、配置我們需要的界面了,那麼他們如何跟makefile文件建立編譯關系呢?當你保存make menuconfig選項時,系統會除了會自動更新.config外,還會將所有的選項以宏的形式保存在Linux內核根目錄下的 include/generated/autoconf.h文件下
內核中的源代碼就都會包含以上.h文件,跟宏的定義情況進行條件編譯。
當我們需要對一個文件整體選擇如是否編譯時,還需要修改對應的makefile文件,例如:
我們選擇是否要編譯s3c2410_ts.c這個文件時,makefile會根據CONFIG_TOUCHSCREEN_S3C2410來決定是編譯此文件,此宏是在Kconfig文件中定義,當我們配置完成後,會出現在.config及autconf中,至此,我們就完成了整個linux內核的編譯過程。
最後我們會發現,整個linux內核配置過程中,留給用戶的介面其實只有各層Kconfig、makefile文件以及對應的源文件。
比如我們如果想要給內核增加一個功能,並且通過make menuconfig控制其聲稱過程
首先需要做的工作是:修改對應目錄下的Kconfig文件,按照Kconfig語法增加對應的選項;
其次執行make menuconfig選擇編譯進內核或者不編譯進內核,或者編譯為模塊,.config文件和autoconf.h文件會自動生成;
最後修改對應目錄下的makefile文件完成編譯選項的添加;
最後的最後執行make命令進行編譯。
Kconfig和Makefile
Linux內核源碼樹的每個目錄下都有兩個文檔Kconfig和Makefile。分布到各目錄的Kconfig構成了一個分布式的內核配置資料庫,每個Kconfig分別描述了所屬目錄源文檔相關的內核配置菜單。在執行內核配置make menuconfig時,從Kconfig中讀出菜單,用戶選擇後保存到.config的內核配置文檔中。在內核編譯時,主Makefile調用這 個.config,就知道了用戶的選擇。這個內容說明了,Kconfig就是對應著內核的每級配置菜單。
假如要想添加新的驅動到內核的源碼中,要修改Kconfig,這樣就能夠選擇這個驅動,假如想使這個驅動被編譯,則要修改Makefile。添加新 的驅動時需要修改的文檔有兩種(如果添加的只是文件,則只需修改當前層Kconfig和Makefile文件;如果添加的是目錄,則需修改當前層和目錄下 的共一對Kconfig和Makefile)Kconfig和Makefile。要想知道怎麼修改這兩種文檔,就要知道兩種文檔的語法結構,Kconfig的語法參見參考文獻《【linux-2.6.31】kbuild》。
Makefile 文件包含 5 部分:
Makefile 頂層的 Makefile
.config 內核配置文件
arch/$(ARCH)/Makefile 體系結構 Makefile
scripts/Makefile.* 適用於所有 kbuild Makefile 的通用規則等
kbuild Makefiles 大約有 500 個這樣的文件
頂層 Makefile 讀取內核配置操作產生的.config 文件,頂層 Makefile 構建兩個主要的目標:vmlinux(內核映像)和 moles(所有模塊文件)。它通過遞歸訪問內核源碼樹下的子目錄來構建這些目標。訪問哪些子目錄取決於內核配置。頂層 Makefile 包含一個體系結構 Makefile,由 arch/$(ARCH)/Makefile 指定。體系結構 Makefile 文件為頂層 Makefile 提供了特定體系結構的信息。每個子目錄各有一個 kbuild文件和Makefile 文件來執行從上層傳遞下來的命令。kbuild和Makefile文件利用.config 文件中的信息來構造由 kbuild 構建內建或者模塊對象使用的各種文件列表。scripts/Makefile.*包含所有的定義/規則,等等。這些信息用於使用 kbuild和 Makefile 文件來構建內核。Makefile的語法參見參考文獻《【linux-2.6.31】kbuild》。
參考文獻
【linux-2.6.31】內核編譯指南.pdf
【linux-2.6.31】kbuild.pdf
Linker script in Linux.pdf
linux內核的配置機制及其編譯過程
Linux內核編譯過程詳解
Linux Kconfig及Makefile學習