Analytics

2009年11月5日 星期四

我承認我是笨蛋系列之#include問題 1

這是在看程式碼開頭產生的疑問
有時候看到一段程式碼裡有一大堆#include



如下:
#include < linux/init.h >
#include < linux/spinlock.h >
#include < linux/workqueue.h >
#include < linux/interrupt.h >
#include < linux/delay.h >
#include < linux/errno.h >
#include < linux/err.h >
#include < linux/clk.h >
#include < linux/platform_device.h >

#include < linux/spi/spi.h >
#include < linux/spi/spi_bitbang.h >

#include < asm/io.h >
#include < asm/dma.h >
#include < asm/hardware.h >

#include < asm/arch/regs-gpio.h >
#include < asm/plat-s3c24xx/regs-spi.h >
#include < asm/arch/spi.h >

 這些都是從哪裡include進來的阿?

有時候我會在好幾個地方看到一樣的東西
那到底編譯時用的是哪一個,該如何知道?

4 則留言:

  1. kernel src code裡應該有個include 資料夾,kernel code裡的include linux/spi/spi.h 應該就是 kernel src dir裡的include/spi/spi.h,header file的路徑設定方式 1. gcc預設 2. Makefile特別指定。像我的kernel 最上層Makefile裡有一段
    # Use LINUXINCLUDE when you must reference the include/ directory.
    # Needed to be compatible with the O= option
    LINUXINCLUDE := -Iinclude \
    $(if $(KBUILD_SRC),-Iinclude2 -I$(srctree)/include) \
    -include include/linux/autoconf.h

    CPPFLAGS := -D__KERNEL__ $(LINUXINCLUDE)

    先說明一下,雖然你可能已經知道了:
    對gcc 而言,如果要多增加include path,可以下參數 -Imypath: 這樣gcc就會去mypath這個路徑搜尋標頭檔。如果有多個path: -Imypath1 mypath2 mypath3

    然後,讓我們看看那一段Makefile在做什麼:
    LINUXINCLUDE := -Iinclude \
    $(if $(KBUILD_SRC),-Iinclude2 -I$(srctree)/include) -include include/linux/autoconf.h
    這裡先定義一個變數LINUXINCLUDE ,其值為-Iinclude 加上後面的

    $(if $(KBUILD_SRC),-Iinclude2 -I$(srctree)/include) -include include/linux/autoconf.h
    所產生output。

    在Makefile裡面,變數值的表示方式: $(var)。

    這裡的 if 是Makefile 的 if function,別跟shell script的if搞錯了
    if $(KBUILD_SRC),-Iinclude2
    的意思是,如果 KBUILD_SRC 這個變數有值,傳回-Iinclude2。

    所以
    LINUXINCLUDE := -Iinclude \
    $(if $(KBUILD_SRC),-Iinclude2 -I$(srctree)/include) -include include/linux/autoconf.h
    的意思是說,如果 KBUILD_SRC 變數有值,
    定義 LINUXINCLUDE 為: -Iinclude -Iinclude2 -I$(srctree)/include) -include include/linux/autoconf.h

    這裡的-I$(srctree)/include ,就是一開始提到的kernel src dir裡的include資料夾。所以才說 include linux/spi/spi.h 應該就是kernel src dir裡的include/spi/spi.h


    LINUXINCLUDE 最後會被export出來變環境變數,
    export CPPFLAGS NOSTDINC_FLAGS LINUXINCLUDE OBJCOPYFLAGS LDFLAGS

    最後gcc 在build 個別.c 的時候,就會用到LINUXINCLUDE,所以 gcc知道要去include, include2, $(srctree)/include......

    回覆刪除
  2. 先謝謝學姐!我覺得我真的找到救星了,真是感人T_T
    之後還要麻煩學姐照顧了m(_ _)m

    把學姐寫的看過一遍,我在想我大概要多看幾遍才會懂orz
    這大部分是makefile的語法嗎?

    另外
    我想問一個問題
    就是學姐一開始提到的那個"kernel code"指的是?

    是說只要是driver module之類的
    都算是嗎?

    所以我要區分為kernel code和user code?

    謝謝!!

    回覆刪除
  3. 是阿,都是Makefile的語法,Makefile寫起來可以寫得超複雜@@,不過如果想要知道header file的include path,搜尋-I 就對了。

    kernel module是kernel src code的一部份,具有一些異於user base的code特型,像無法使用libc,因為它只認識kernel的code(不能使用printf要使用printk, 不能使用malloc要使用kmalloc...),所以在kernel code裡從來都不會看到include "stdio.h"之類的。Linux的device driver用kernel module的方式寫的話,就是kernel code ,算是kerenl 的一部份。

    我不會的還有很多@@,像我就沒自己裝過tool chain,都用人家已經安裝好的@@ 請多多指教,一起學習。

    回覆刪除
  4. 現在的 Makefile 也不會是作者自己打的
    有很多套件可以自動產生 Makefile

    目前 cmake 好像還蠻紅的
    可以去玩玩看 XD

    回覆刪除