zoukankan      html  css  js  c++  java
  • Android驱动笔记(7)——makefile

     makefile关系到了整个工程的编译规则。一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了规则来指定,哪些文件先编译,哪些文件后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作。makefile带来的好处就是“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。
     makefile并不是唯一用来定义编译规则的,Android BP侧代码基于python的scons的一套编译机制(几乎不需要修改)。Android AP侧代码并不单纯的是makefile机制,还引入了ninja以及google改造后的Android.mk语法,编译效率更高。后续google可能会用go语言改造整个流程。
    makefile流程

     Android项目的主Makefile文件就放在根目录下,里面指向build/core/main.mk

    ### DO NOT EDIT THIS FILE ###
    include build/core/main.mk
    ### DO NOT EDIT THIS FILE ###
    

     这时如果直接运行make指令的话,就会把目标设为DEFAULT_GOAL

    #This is the default target.  It must be the first declared target.
    .PHONY:droid
    DEFAULT_GOAL := droid
    $(DEFAULT_GOAL): droid_targets
    

     droid依赖到下面的代码。

    #Build files and then package it into the rom formats
    .PHONY:droidcore
    droidcore: files 
               systemimage 
               $(INSTALLED_BOOTIMAGE_TARGET) 
               $(INSTALLED_RECOVERYIMAGE_TARGET) 
               …
    

     如果我们想加一个自己的image,也默认make可以编译出来,可以在这里加上依赖关系。
     另外项目里面的一些环境变量可以通过printconfig和export命令查询。可以获得当前编译的版本:

    TARGET_BUILD_VARIANT=userdebug
    

     说明当前的编译配置是userdebug。

    7.1、Android.mk怎么写?

     拿一个自己写过的文件来简单说明一下Android.mk的写法。一般情况下如果相同路径下有类似的makefile文件可以直接搬来使用。

    LOCAL_PATH := $(call my-dir)
    #这个变量用于给出当前文件的路径,必须在Android.mk的开头定义,可以这样使用:LOCAL_PATH := $(call my-dir),这样这个变量不会被$(CLEAR_VARS)清除
    common_cflags := -std=c99 -Wall
    
    include $(CLEAR_VARS)
    #因为一个Android.mk可能定义多个模块,每个模块都用到同样的变量名,这句话是清除掉前面变量。
    LOCAL_SRC_FILES := mifunctiontest.c 
    #要编译的源文件
    LOCAL_C_INCLUDES := system/core/libcutils/include 
    	system/core/include
    
    LOCAL_CFLAGS := $(common_cflags)
    #定义了c编译用的一些参数,比较常用的-DXXXX_YYYY来定义一个宏,其效果和在.c/.h文件的语句里面的#define XXXX_YYYY相同。
    LOCAL_STATIC_LIBRARIES := libcurl libz libcrypto_static liblog libcutils
    *表明本模块在编译时要用到的静态库。如果用到动态库可以用LOCAL_SHARED_LIBRARIES。
    LOCAL_MODULE := mifunctiontest
    * LOCAL_MODULE定义了你这个module生成目标最终的文件名。
    LOCAL_MODULE_CLASS := EXECUTABLES
    LOCAL_MODULE_PATH := $(PRODUCT_OUT)/system/bin
    LOCAL_MODULE_TAGS := optional
    
    include $(BUILD_EXECUTABLE)
    #表明该module的类型,有以下几类:
    #   include $(BUILD_STATIC_LIBRARY)表明生成一个静态库文件;
    #   include $(BUILD_SHARED_LIBRARY) 表明生成一个动态库文件;
    #   include $(BUILD_HOST_EXECUTABLE) 生成一个用于host主机即PC端运行的可执行程序,bin文件;
    

     当Android.mk新加一个module以后,make此时并不会自动地编译到系统。需要在PRODUCT_PACKAGES变量里增加LOCAL_MODULE所对应的名字。PRODUCT_PACKAGES变量对于有zproject的项目,在相应的文件夹下Config文件里面有,在后面追加即可。在没有zproject的项目里面,可以在device/qcom/msmXXX/msmXXX.mk文件里面追加。
     关于变量定义如果过长,需要换行的时候,可以用''连接两行,但是注意''后面不能有空格,否则会导致编译不过。

    LOCAL_SRC_FILES := a.c 
    

    7.2、kernel makefile怎么写?

     在kernel添加驱动编译相关的配置通常需要修改3个文件:Makefile,Kconfig,msmxxx_defconfig或perf_config。
    其中Makefile里面添加源文件对应的.o配置。里面的obj-((CONFIG_XXXXX)中)(CONFIG_XXXXX)是个变量,需要在Kconfig里面定义

    Path:/drivers/misc/Makefile
    
    obj-$(CONFIG_OKL4_LINK_SHBUF)    += okl4-link-shbuf.o
    obj-$(CONFIG_SIMTRAY_STATUS)     += simtray.o
    

    *在makefile中新添加一个节点的状态,这里是编译的保证。里面的obj-$(CONFIG_XXXXX)中$(CONFIG_XXXXX)是个变量,需要在Kconfig里面定义

    Path: /drivers/misc/Kconfig
    
    config SIMTRAY_STATUS
    	tristate "SIM tray status"
    #tristate:意思是三态(3种状态,对应Y、N、M三种选择方式),意思就是这个(CONFIG_XXXXX)可以被三种选择。Y会 被编入,M会#被单独链接成一个.ko模块,N则不会被编译。
    	default n
    	help
    	  Say 'y' here to support SIM tray GPIO detection
     source "drivers/misc/c2port/Kconfig"
     source "drivers/misc/eeprom/Kconfig"
     source "drivers/misc/cb710/Kconfig"
    

     $(CONFIG_XXXXX)的开关是在kernel/arch/arm64/configs/vendor/xxx_defconfig里面定义的。龙旗一个项目通常对应两个xxx_defconfig,一个是xxx_defconfig一个是xxx-perf_defconfig,xxx_defconfig里面有很多debug开关是打开的,msmxxx-perf_defconfig是user版本默认的配置的,所以提交配置两个文件通常都需要提交。而对于选择哪个defconfig是定义在device/qcom/xxx/AndroidBoard.mk里面

    #----------------------------------------------------------------------
    # Compile Linux Kernel
    #----------------------------------------------------------------------
    ifeq ($(KERNEL_DEFCONFIG),)
        ifeq ($(TARGET_BUILD_VARIANT),user)
            KERNEL_DEFCONFIG := vendor/trinket-perf_defconfig
        else
            KERNEL_DEFCONFIG := vendor/trinket_defconfig
        endif
    endif
    

     config编译生成的中间文件放在out/target/product/xxx/obj/KERNEL_OBJ/.config.如果添加驱动后.c没有编译到,可以到这文件里面确认相关config是否有配置成功。

  • 相关阅读:
    Unity 绘制带颜色的流线 streamline
    Tinyply 源码阅读
    题解 [BZOJ2952]长跑
    莫比乌斯反演技巧
    题解 pyh的求和
    Java Web基础
    后端常用数据持久层模板及框架以及一些工具类模板的配置使用集合
    12306火车订票系统(C++)
    C++/Java文件读写并执行相关操作、文件复制、文件格式转换等(举例)
    《Java EE编程技术》综合应用系统开发_作业管理系统_Struts2_设计报告
  • 原文地址:https://www.cnblogs.com/hansenn/p/12728626.html
Copyright © 2011-2022 走看看