Android.mk 淺析 模組編譯Makefile編寫

來源:互聯網
上載者:User

終於將C++代碼porting到了bootloader中,唯一的收穫就是熟悉了Makefile,有工廠的公司傷不起啊,每次都得先做一些東西滿足工廠端測試的需求,為了能夠做到工廠在boot中測試的要求,經過與晶片公司討論,只有將C++弄到了boot中,真是一個很二的決定boot最終做到了2M比有些kernel還要大。不過老闆要這麼做就硬著頭皮做了現在做成了心中還蠻高興的,原來被逼之後人的潛能還是蠻大的。

        對於Makefile中所用的函數還在研究中,之後會寫一寫主要函數的用法。

         因為從事著android驅動開發所以天天要接觸Android.mk。
        1、在運行  . build/envsetup.sh 會產生一些操作例如:chooseproduct mmm
        2、運行 chooseproduct project  選擇所要編譯的工程
        3、運行make,回去編譯整個android source

怎麼說到了編譯Android Source的方法呢

切入主題 先寫一個簡單的Android.mk

[python]
view plaincopyprint?
  1. LOCAL_PATH := $(call my-dir)             #指定目前的目錄 
  2.     
  3. include $(CLEAR_VARS)                   
    #引入編譯變數 
  4.  
  5. LOCAL_MODULE_TAGS := optional           
    #編譯選項便是在何種情況下編譯 
  6.  
  7. LOCAL_SRC_FILES := hello.c              
    #源檔案(可以指定多個)  
  8.   
  9. LOCAL_MODULE := hello                   
    #編譯出來的模組名 
  10.  
  11. LOCAL_MODULE_CLASS := EXECUTABLES       
    #指定編譯之後放置的位置(此處指示放在system/bin下) 
  12.  
  13. include $(BUILD_EXECUTABLE)             
    #引入編譯成可執行檔的規則  
LOCAL_PATH := $(call my-dir)             #指定目前的目錄   include $(CLEAR_VARS)                    #引入編譯變數LOCAL_MODULE_TAGS := optional            #編譯選項便是在何種情況下編譯LOCAL_SRC_FILES := hello.c               #源檔案(可以指定多個)  LOCAL_MODULE := hello                    #編譯出來的模組名LOCAL_MODULE_CLASS := EXECUTABLES        #指定編譯之後放置的位置(此處指示放在system/bin下)include $(BUILD_EXECUTABLE)              #引入編譯成可執行檔的規則 

以上的Android.mk 會編譯出一個hello的可執行檔,並放入system/bin

LOCAL_PATH : 指定目錄,以上是一般用法指示目前的目錄(my-dir函數是Android編譯時間. build/envsetup.sh命令產生的 能夠擷取目前的目錄的路徑)

CLEAR_VARS: android有自己的一套代碼編譯規則跟編譯選項等變數的定義,此變數會引入,實際是android/build/core下的clear_vas.mk,

clear_vas.mk

[plain]
view plaincopyprint?
  1. ########################################################## 
  2. ## Clear out values of all variables used by rule templates. 
  3. ########################################################### 
  4.  
  5. LOCAL_MODULE:=                                                                           
  6. LOCAL_MODULE_PATH:= 
  7. LOCAL_MODULE_STEM:= 
  8. LOCAL_DONT_CHECK_MODULE:= 
  9. LOCAL_CHECKED_MODULE:=  
  10. LOCAL_CERTIFICATE:= 
  11. LOCAL_SDK_VERSION:= 
  12. LOCAL_NDK_VERSION:= 
  13. LOCAL_NO_EMMA_INSTRUMENT:= 
  14. LOCAL_NO_EMMA_COMPILE:= 
  15. LOCAL_PROGUARD_ENABLED:= # '',optonly,full,custom 
  16. LOCAL_PROGUARD_FLAGS:= 
  17. LOCAL_PROGUARD_FLAG_FILES:= 
  18. LOCAL_EMMA_COVERAGE_FILTER:= 
  19. LOCAL_MANIFEST_FILE:= 
  20. LOCAL_BUILD_HOST_DEX:= 
  21. LOCAL_DEX_PREOPT:= 
  22. LOCAL_DEX_PREOPT:= 
  23.  
  24. # Trim MAKEFILE_LIST so that $(call my-dir) doesn't need to 
  25. # iterate over thousands of entries every time. 
  26. # Leave the current makefile to make sure we don't break anything 
  27. # that expects to be able to find the name of the current makefile. 
  28. MAKEFILE_LIST := $(lastword $(MAKEFILE_LIST)) 
############################################################ Clear out values of all variables used by rule templates.###########################################################LOCAL_MODULE:=                                                                          LOCAL_MODULE_PATH:=LOCAL_MODULE_STEM:=LOCAL_DONT_CHECK_MODULE:=LOCAL_CHECKED_MODULE:= ...LOCAL_CERTIFICATE:=LOCAL_SDK_VERSION:=LOCAL_NDK_VERSION:=LOCAL_NO_EMMA_INSTRUMENT:=LOCAL_NO_EMMA_COMPILE:=LOCAL_PROGUARD_ENABLED:= # '',optonly,full,customLOCAL_PROGUARD_FLAGS:=LOCAL_PROGUARD_FLAG_FILES:=LOCAL_EMMA_COVERAGE_FILTER:=LOCAL_MANIFEST_FILE:=LOCAL_BUILD_HOST_DEX:=LOCAL_DEX_PREOPT:=LOCAL_DEX_PREOPT:=# Trim MAKEFILE_LIST so that $(call my-dir) doesn't need to# iterate over thousands of entries every time.# Leave the current makefile to make sure we don't break anything# that expects to be able to find the name of the current makefile.MAKEFILE_LIST := $(lastword $(MAKEFILE_LIST))

在編譯C/C++代碼時候常用的變數定義

LOCAL_MODULE 指示當前編譯出來的模組名

LOCAL_MODULE_TAGS 標識在什麼情況下去編譯起模組

有幾個選項

user 模組只在user下編譯
eng 模組在eng模式下編譯
tests test狀態下編譯
optional 此模組在所有版本下都編譯

即 TARGET_BUILD_VARIANT=eng 編譯TAGS為eng和optional的模組

LOCAL_SRC_FILES 表示編譯出此模組需要的來源程式 可以有多個

LOCAL_C_INCLUDE  如果不去調用標準庫標頭檔,跟目前的目錄的標頭檔,則需要在此指定標頭檔的位置,在此指定標頭檔的目錄。

LOCAL_STATIC_LIBRARIES:  指定需要串連的靜態庫像一些比較通用的標準庫就無需指定了

LOCAL_SHARED_LIBRARIES: 指定需要串連的動態庫

最後include $(BUILD_XXX) 表示編譯出來的模組類型,有三種

BUILD_EXECUTABLE 編譯成可執行檔模組 build/core/host_executable.mk
BUILD_STATIC_LIBRARY 編譯成靜態庫 build/core/host_static_library.mk
BUILD_SHARED_LIBRARY 編譯成動態庫 build/core/host_shared_library.mk

LOCAL_MODULE_CLASS 標識了所編譯模組最後放置的位置,如果不指定,不會放到系統中,之後放在最後的obj目錄下的對應目錄中。

LOCAL_MODULE_CLASS := ETC                                    #表示放於system/etc目錄

LOCAL_MODULE_CLASS := EXECUTABLES               #放於/system/bin

LOCAL_MODULE_CLASS := SHARED_LIBRARIES     #放在/system/lib下

build/core下有很多編譯的全域的mk,如編譯C/C++規則definitions.mk ......

再說一下編譯核心模組的Makefile

[plain]
view plaincopyprint?
  1. ifneq ($(KERNELRELEASE),)  #查看是都已定義kernel版本 
  2.  
  3. obj-m := gps_onoff.o       #如果已定義則編譯出得模組名是gps_onoff.o 
  4.                            #(在linux2.6編譯模組後會產生module_name.ko module_name.o  
  5.                            #使用insmod module_name.ko來裝載模組moudule_name.o已經棄用  
  6.                            #即moudule_name.ko 是最終產物) 
  7.  
  8. else                       #第一次運行時候會走此分支 
  9.  
  10. PWD := $(shell pwd)        #指定源檔案目錄         
  11.  
  12. KDIR ?= /home/zk/POP_TD/marvell-pxa920-kernel      #指定到已經編譯的核心的目錄 
  13.                            #如果編譯PC機上的模組則指定到當前啟動並執行核心 
  14.                            #(uname -r 查看當前的核心版本) 
  15.                            #(此時核心版本也被定義KERNELRELEASE非空) 
  16.                                
  17. #核心編譯命令 此處可以指定硬體體系與交叉編譯工具 
  18. all:  
  19.     $(MAKE) -C $(KDIR) M=$(PWD) modules ARCH=arm CROSS_COMPILE=arm-eabi-  
  20.  
  21. #重新編譯核心前需要先make clean 清空編譯產生的檔案 否則編譯會出錯 
  22. clean:  
  23.     rm -rf .* *.ko *.o *.cmd *.tmp_version *.mod.c *.order Module.*endif 
ifneq ($(KERNELRELEASE),)  #查看是都已定義kernel版本obj-m := gps_onoff.o       #如果已定義則編譯出得模組名是gps_onoff.o                           #(在linux2.6編譯模組後會產生module_name.ko module_name.o                            #使用insmod module_name.ko來裝載模組moudule_name.o已經棄用                            #即moudule_name.ko 是最終產物)else                       #第一次運行時候會走此分支PWD := $(shell pwd)        #指定源檔案目錄        KDIR ?= /home/zk/POP_TD/marvell-pxa920-kernel      #指定到已經編譯的核心的目錄                           #如果編譯PC機上的模組則指定到當前啟動並執行核心                           #(uname -r 查看當前的核心版本)                           #(此時核心版本也被定義KERNELRELEASE非空)                              #核心編譯命令 此處可以指定硬體體系與交叉編譯工具all:     $(MAKE) -C $(KDIR) M=$(PWD) modules ARCH=arm CROSS_COMPILE=arm-eabi- #重新編譯核心前需要先make clean 清空編譯產生的檔案 否則編譯會出錯clean:     rm -rf .* *.ko *.o *.cmd *.tmp_version *.mod.c *.order Module.*endif

編譯模組的Mkefile會被讀取兩次,Makefile從命令列調用時候KERNELRELEASE尚未設定,

在運行到KDIR時即會指向一個核心構造樹,

在運行$(MAKE)時 會會第二次運行make命令,此時設定obj-m 構造真正的核心模組

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.