赞
踩
Makefile笔记
外部模块头文件的检索:当编译的目标模块依赖多个头文件时,kbuild对头文件的搜索位置有这样的规定:
(1) 直接放置在 Makefile 同在的目录下,在编译时当前目录会被添加到头文件搜索目录。
(2) 放置在系统目录,这个系统目录是源代码目录中的 include,注意是源代码目录而不是系统目录的。
(3) 与通用的 Makefile 一样,使用 -I$ (DIR) 来指定,不同的是,编译选项的变量固定为 ccflag,当前 Makefile 是镶嵌到 Kbuild 系统中,ccflags-y += -I$(DIR)/include,kbuild就会将 $(DIR)/include 目录添加到编译时的头文件搜索目录中。一般使用"+="来进行追加赋值,各个Makefile中加的只影响自己的编译。
以源码中linux-source-4.15.0为例
模块A:
~/linux-source-4.15.0/linux-source-4.15.0/drivers/staging/most/hdm-usb/
hdm_usb.c Kconfig Makefile
模块B:
~linux-source-4.15.0/linux-source-4.15.0/drivers/staging/most/mostcore/
core.c Kconfig Makefile mostcore.h
若模块A需要调用模块B中的函数,则需要在模块A中的Makefile使用到ccflag-y,在头文件中引用模块B函数定义的头文件
模块A: Makefile obj-$(CONFIG_HDM_USB) += hdm_usb.o ccflags-y += -Idrivers/staging/most/mostcore/ ccflags-y += -Idrivers/staging/most/aim-network/ hdm_usb.c #include "mostcore.h" static void wq_clear_halt(struct work_struct *wq_obj){ ... most_stop_enqueue(&mdev->iface, channel); most_resume_enqueue(&mdev->iface, channel); 模块B: mostcore.h void most_stop_enqueue(struct most_interface *iface, int channel_idx); void most_resume_enqueue(struct most_interface *iface, int channel_idx);
如果ccflag的路径没有写对的话,去引用头文件则会报错,
fatal error: 'cam_sensor_io.h' file not found
如果显示如下ld 链接的时候未定义的符号引用问题
ld.lld: error: undefined symbol: cam_sensor_power_up
因为在之前的高通平台上使用ccflags没有类似问题,起初是以为ccflags在内核版本变更上可能会有新特性,但没有找到类似的答案,接着就看了qcom camera kernel的变化,发现Android12下Makefile将camera编译成了camera.ko,
尝试删除out/target/product/xxx/obj/kernel/msm-5.4/techpack/camera/drivers之前编译生成的产物,修改代码将camera目录下都使能obj-y编译后,则编译调用目前都还正常,obj-y生成built-in.o,Kbuild编译所有的obj-y文件,并调用”$(LD) -r”把所有这些文件合并到built-in.o文件。这个built-in.o会被上一级目录的Makefile使用,最终链接到vmlinux中,所以之前模块化后是没有链接到一起,所以导致报了ld的错误。看到都是ko的模块间调用可以使用EXPORT_SYMBOL 非static函数定义 + extern的方式,这个后续有时间我在尝试一下,需要注意模块间的加载顺序。
export CONFIG_SPECTRA_CAMERA=y
ifeq ($(CONFIG_SPECTRA_CAMERA),m)
$(info "SPECTRA CAMERA IS BUILT AS DLKM")
BOARD_VENDOR_KERNEL_MODULES += $(KERNEL_MODULES_OUT)/camera.ko
endif
那为什么Android12上会出现camera.ko这个的变化呢,主要是GKI的引入
后续这里有尝试了第二种方法,将我们的驱动以ko模块的方式编译,通过EXPORT_SYMBOL的方式传递接口
techpack/camera/drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c
EXPORT_SYMBOL(cam_sensor_power_up);
drivers/ourdriver/ourdrvier.h
extern int cam_sensor_power_up(struct cam_sensor_ctrl_t *s_ctrl);
Makefile 需要注意多个.o编译成一个模块
obj-m += xxx.o
xxx-objs := xxx1.o xxx2.o or xxx-y := xxx1.o xxx2.o
通用内核映像
Android内核中运行的代码中有多达 50% 是树外代码(并非来自上游 Linux 和 AOSP 通用内核),供应商通过修改内核源代码并添加设备驱动程序,添加了对 SoC 和外围设备的支持。几乎所有设备都具有自定义内核。这就导致了内核碎片化问题。
通用内核映像 (GKI) 项目通过统一核心内核并将 SoC 和板级支持从核心内核移至可加载模块中,解决了内核碎片化问题。GKI 内核为内核模块提供了稳定的内核模块接口 (KMI),因此模块和内核可以独立进行更新。
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。