Android.mk for your own module

來源:互聯網
上載者:User

http://blog.csdn.net/yili_xie/archive/2009/12/09/4971736.aspx

 

這個分析的不錯。原地址有圖。

 

 這裡我們向Android中添加自己的模組,只涉及到.so/*.a/elf source的編譯,以及如何將prebuilt file添加進工程。對於APK以及jar的source暫時沒有仔細研究,要添加進去的話可以參照/pacakge和/framework 裡面的Android.mk ~~
     首先是可能用得到的基礎知識,必須瞭解基礎Makefile的文法,然後下面是Andriod用來編譯相應模組使用的核心makefile,當然如果要速成的話也可以不看這些東西,直接按照後面的例子添加就可以了:
     1、prebuilt
      /build/core/base_rules.mk
      /build/core/prebuilt.mk
      /build/core/multi_prebuilt.mk
     2、.so/
      /build/core/base_rules.mk
      /build/core/shared_library.mk
      /build/core/dynamic_library.mk
      /build/core/binary.mk
     3、.a
      /build/core/base_rules.mk
      /build/core/static_library.mk
      /build/core/binary.mk
     編寫可執行檔基本上和.so是差不多的,現在分為兩類來仔細講一下,一類是prebuilt files的編譯,另外就是.so/.a/elf的編譯。
     在所有這許makefile中最重要的是base_rules.mk,它是對module進行處理的核心過程,下面先看看這個檔案的內容:

     

 每個模組在編譯的時候都會產生一個編譯目錄和一個安裝目錄,編譯目錄就是這個模組編譯以後產生的目標檔案,安裝目錄就代表著這個模組是否會編譯進檔案系統,就是是否編譯進IMG啦~~在base_rules.mk提供了兩個變數來定義你要輸出的目錄,仔細弄懂對你瞭解編譯後的組建目錄是很有協助的~~
      built_module_path := $(intermediates)
      LOCAL_BUILT_MODULE := $(built_module_path)/$(LOCAL_BUILT_MODULE_STEM)
      LOCAL_INSTALLED_MODULE := $(LOCAL_MODULE_PATH)/$(LOCAL_MODULE_SUBDIR)$(LOCAL_INSTALLED_MODULE_STEM)
      built_module_path是編譯產生的中間檔案所在的目錄,LOCAL_BUILT_MODULE_STEM就是你要產生的編譯目標啦,如果本地模組指定了LOCAL_MODULE_STEM的話,它的值就是$(LOCAL_MODULE_STEM)$(LOCAL_MODULE_SUFFIX),如果沒有指定了的話就是$(LOCAL_MODULE)$(LOCAL_MODULE_SUFFIX)。由此可以看到LOCAL_MODULE的定義是很有講究的,比如什麼*.so,一般*就用來作模組名。LOCAL_MODULE_SUFFIX在編譯不同的模組時,GOOGLE內建會給你加上相應的值,如果你不瞭解的話還是盡量自己來指定,不然可能編譯出來的東西被篡改了檔案名稱哦噢~~
      將編譯目錄的檔案拷貝到安裝目錄就是我們的LOCAL_INSTALLED_MODULE了,是否會安裝就要看你定義的 LOCAL_MODULE_TAGS了,當然你也可以通過修改LOCAL_MODULE_PATH來自訂安裝。LOCAL_MODULE_PATH是有個很有用的變數,首先我們看看當我們在本地模組沒有指定這個值的時候,它的值實際上是:LOCAL_MODULE_PATH := $($(my_prefix)OUT$(use_data)_$(LOCAL_MODULE_CLASS)),如果你的模組定義了TAGS := TESTS則user_data的值是DATA,這樣的模組會被安裝在data/目錄下,那麼通過替換我們就知道這個LOCAL_MODULE_PATH := TARGET_OUT_$(LOCAL_MODULE_CLASS)。這個LOCAL_MODULE_CLASS在特定的類型編譯會被google賦值成固定內容,但是在prebuilt的編譯中它是由你自己來賦值的,它的值就會用來定義產生的目錄,比如LOCAL_MODULE_CLASS := ETC的時候,則就會被安裝在/system/etc目錄。那麼我們就知道如何來定義prebuilt模組裡面的CLASS了,google還提供了一個 LOCAL_MODULE_SUBDIR可以讓你來定義子目錄,但是要記得的是在每個模組的最後要將這個值清空,因為預設CLEAR_VARS是不會清空這個值的。
      當然前面說的是LOCAL_MODULE_PATH的預設值,我們可以通過給它賦值來強制指定安裝的目錄,比如說要安裝在system/etc /permissions目錄,則可以強制指定它的值為$(TARGET_OUT_ETC)/permissions,這樣模組就會被強制安裝在這個目錄了,給LOCAL_MODULE_PATH賦值的情況主要應用在prebuilt模組的編譯上,其他的應該盡量採用其預設值。
      下面我們就具體看看我寫的一個如何編譯自己的.so *.a  elf的例子,具體能使用到的變數,和要注意的地方我都寫出來了:

 

這裡要說明的是這個prelink,prelinke只有在編譯.so的時候才會有的選項,主要是通過預連結的方式來加快程式啟動和執行的速度,如果你的本地模組prelink是真的話,那你要在build/core/prelink-linux-arm.map中定義你的庫需要使用的空間,空間不夠的話會報錯(具體使用沒仔細研究過)
       下面再看看如何來將我們自己的prebuilt files編譯進工程,先讓我們和這個相關的最重要的兩個makefile:

 

 multi_prebuilt.mk只用來加入需要加入的各種庫,仔細注意它裡面的那個對加入檔案進行處理的函數,尤其是 LOCAL_MODULE,LOCAL_MODULE_SUFFIX ,LOCAL_SRC_FILES這3個變數是如何得到的,使用multi_prebuilt編譯進工程的檔案都會自動打上USER的tag。而且它最後還是會掉用prebuilt.mk來執行真正的編譯操作。
        prebuilt.mk實際上可以編譯任何檔案到我們的工程中,下面是我寫的一個例子,可以自動將目錄下相應格式的檔案編譯進工程:

 

  此外添加prebuilt.mk也有一個粗暴的方式,可以通過下面的規則簡單的將所有prebuilt files添加到你工程中去,必須一個一個添加:
        LOCAL_PATH := $(call my-dir)
        include $(CLEAR_VARS)
        # your prebuilt file name
        LOCAL_MODULE := example.so
        LOCAL_MODULE_TAGS := user eng
        # your prebuilt file (must be relative directory )
        LOCAL_SRC_FILES := lib/example.so
        # the path your prebuilt file will be installed   $(TARGET_OUT) is the system directory
        LOCAL_MODULE_PATH := $(TARGET_OUT)/lib  
        include (BUILD_PREBUILT)

  在最後說一下Android對模組唯一性檢測的規則,在base_rules.mk裡面通過module_id裡來檢測這個模組是否已經存在,我們看看這個值是如何定義的:

module_id := MODULE.$(if /
    $(LOCAL_IS_HOST_MODULE),HOST,TARGET).$(LOCAL_MODULE_CLASS).$(LOCAL_MODULE)

所以它是通過LOCAL_MODULE_CLASS和LOCAL_MODULE這兩個變數來檢測模組的唯一性,因此當你定義同一樣的CLASS和MODULE的時候,Android就會報錯,提示模組必須是唯一的。因此如果你將LOCAL_MODULE_CALSS進行修改,使用LOCAL_MODULE_PATH來指定安裝目錄的時候就會逃過Android對模組唯一性的檢測,但是這樣導致的問題就是同一個目標會有多個規則來實現它,而且每個規則都是相同的命令。這樣導致的結果就是MAKE會將所有的依賴放在一起,然後使用命令來將其產生目標,這樣是非常危險的,會造成庫的覆蓋,而且很多時候你不知道它就究竟使用的是哪個依賴來最終產生目標,只能用md5sum來檢查。

      因此當你使用prebuilt來覆蓋系統原有的檔案的時候應該特別小心,如果你確認你的檔案在覆蓋系統原有檔案以後系統能正常啟動並執行話,好的方法是還是開啟Android對module_id的檢測,同時把原來產生這個檔案的Makefile進行修改,讓其不編譯出這個檔案~

      最後補充一個Android如何來存放模組的編譯中間檔案:
1、如果你的LOCAL_MODULE_CLASS包含COMMON_MODULE_CLASS := JAVA_LIBRARIES NOTICE_FILES,則你編譯出的中間檔案會放在:
   $(TARGET__OUT_COMMON_INTERMEDIATES)/$(LOCAL_MODULE_CLASS)/$(LOCAL_MODULE)_intermediates/
TARGET_OUT_COMMON_INTERMEDIATES := out/target/common/obj
2、如果你的LOCAL_MODULE_CLASS不包含COMMON_MODULE_CLASS,則你編譯出的中間檔案會放在:
     $(TARGET__OUT_INTERMEDIATES)/$(LOCAL_MODULE_CLASS)/$(LOCAL_MODULE)_intermediates/
TARGET_OUT_INTERMEDIATES := out/target/product/msm7627_ffa/obj

本文來自CSDN部落格,轉載請標明出處:http://blog.csdn.net/yili_xie/archive/2009/12/09/4971736.aspx

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.