|
終於將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- 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) #引入编译成可执行文件的规则
複製代碼 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- ##########################################################
- ## 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,custom
- LOCAL_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- 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
複製代碼 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 構造真正的內核模塊
|
|