写点什么

Android 条件控制宏编译

作者:桑榆
  • 2022 年 8 月 04 日
  • 本文字数:2709 字

    阅读完需:约 9 分钟

条件控制宏编译是什么?

在我们进行编译文件的编写时,时常需要根据平台信息、硬件信息等选择需要编译的模块,或者进行编译的配置,同时,这也是为了向前兼容之前的模块,大部分代码都是共主线开发,使用编译宏进行控制,这一点在 Android 平台中尤其明显。

随着 Android 版本的演进迭代,旧有版本上面的 Android.mk 被替代为 Android.bp,原始的 Android.mk 是基于 Makefile 进行开发的,在 Makefile 文件中,我们可以很轻松地使用 ifeq 等条件判断进行编译控制,但是 Android.bp 本质上是一个配置文件,其中没有复杂的条件控制,需要借助 go 语言来进行控制。接下来,我们就一起看看这两种方式的区别与具体实现。

一 Android.mk 条件编译

这里的条件编译就与 Makefile 中大致相同,我们看下有条件和无条件的情况分别是如何实现的?

(1)无条件控制宏编译

LOCAL_CFLAGS += -DMK_NO_CONDITION_PRINT
复制代码

通过赋值运算符使用-D 参数增加了一个宏 MK_NO_CONDITION_PRINT

(2)有条件控制宏编译

CONDITION_TEST = YESifeq ($(CONDITION_TEST),"YES")    LOCAL_CFLAGS += -DMK_CONDITION_PRINTendif
复制代码

ifeq 比较两个值,满足条件,则添加对应的宏,这里的条件可以是对应的平台,系统设置的 property 等。

让我们来看一个完整的代码例子:在 Android.mk 文件中增加两个宏 MK_NO_CONDITION_PRINT,MK_CONDITION_PRINT,代码中增加打印。

在 frameworks/av/services/camera/libcameraservice 下 mm -j 编译

LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS)
LOCAL_MODULE := AndroidConditionCompileTest LOCAL_SRC_FILES := main.c
# no condition macro control LOCAL_CFLAGS += -DMK_NO_CONDITION_PRINT
# condition macro control CONDITION_TEST = "YES" ifeq ($(CONDITION_TEST),"YES") LOCAL_CFLAGS += -DMK_CONDITION_PRINTendif
LOCAL_SHARED_LIBRARIES := libcutils liblog libutilsinclude $(BUILD_EXECUTABLE)
复制代码


/************************************************************************* @File Name    : main.c @Author       : SangYu @Email        : sangyu.code@gmail.com @Created Time : Fri 24 Jun 2022 01:48:55 AM UTC @Description  : android condition macro Test ************************************************************************/
#include <stdio.h>
int main(){ printf("condition compile test begin!\n");
#ifdef MK_NO_CONDITION_PRINT printf("MK_NO_CONDITION_PRINT here!\n");#endif
#ifdef MK_CONDITION_PRINT printf("MK_CONDITION_PRINT here!\n");#endif
printf("condition compile test end!\n"); return 0;}
复制代码

push 可执行文件到手机中,执行,得到结果如下

# adb pushadb push Y:\AOSP\out\target\product\flame\system\bin\AndroidConditionCompileTest system/bin/# run the executableadb shell system/bin/AndroidConditionCompileTest
condition compile test begin!MK_NO_CONDITION_PRINT here!MK_CONDITION_PRINT here!condition compile test end!
复制代码

二 Android.bp 条件编译

Android.mk 中的条件编译较简单,可以使用条件语句 ifeq 等关键字进行控制

但是 Android.bp 文件是一个配置文件,不能配置复杂的分支逻辑,这种情况下必须要使用 go 语言来写相关逻辑,并集成中 Android.bp 中。

(1)无条件控制宏编译

cc_library_shared {    name: "libcameraservice",    ...    cflags: [        "-Wall",        "-Wextra",        "-Werror",        "-Wno-ignored-qualifiers",        "-DMP_NO_CONDITION_PRINT"    ],}
复制代码

使用方法与 Android.mk 类似

(2)有条件控制宏编译

Android.bp 文件 主要是声明 cameraparser_defaults 的来源是 cameraparser.go 文件,然后在 go 文件中添加注册,并书写相关的条件判断逻辑。

bootstrap_go_package {                                                                                                                                                                                          name: "soong-cameraparser",    pkgPath: "android/soong/xxxparser",    deps: [        "blueprint",        "blueprint-pathtools",        "soong",        "soong-android",        "soong-cc",        "soong-genrule",    ],    srcs:[        "cameraparser.go"    ],    pluginFor:["soong_build"],}
cameraparser_defaults{ name:"cameraparser_defaults",}
cc_binary { name: "AndroidBPConditionCompileTest",
defaults:["cameraparser_defaults"],
// Camera service source
srcs: [ "main.c", ],
shared_libs: [ "libcutils", "liblog", "libutils", ],
cflags: [ "-DMP_NO_CONDITION_PRINT" ],}
复制代码

Go 语言文件 主要的代码细节就是注册 cameraparser_defaults,然后在注册过程中设定相关 Flag,这样就能够通过条件控制宏是否添加,实现的效果与 Android.mk 一致。

package cameraparser               
import( "android/soong/android" "android/soong/cc" "fmt")
func init(){ //register a module "cameraparser_defaults" android.RegisterModuleType("cameraparser_defaults", cameraDroidDefaultsFactory)}
func cameraDroidDefaultsFactory()(android.Module){ module := cc.DefaultsFactory() android.AddLoadHook(module, cameraDroidDefaults) return module}
func cameraDroidDefaults(ctx android.LoadHookContext){ type props struct{ Cflags []string } p:=&props{} p.Cflags = globalDefaults(ctx) ctx.AppendProperties(p)}
func globalDefaults(ctx android.BaseContext)([]string){ var cppflags []string fmt.Println("wcy debug here") if ctx.AConfig().Getenv("ANDROIDBP_TEST") == "YES"{ cppflags = append(cppflags,"-DMP_CONDITION_PRINT") fmt.Println("wcy debug here cppflags:", cppflags) } return cppflags}
复制代码

main.c 修改

+    printf("-------------------------->\n");++#ifdef MP_NO_CONDITION_PRINT+    printf("MP_NO_CONDITION_PRINT here!\n");+#endif++#ifdef MP_CONDITION_PRINT+    printf("MP_CONDITION_PRINT here!\n");+#endif+     printf("condition compile test end!\n");
复制代码

正常编译

设置环境变量后编译,export ANDROIDBP_TEST="YES"

push 之后执行如下


发布于: 刚刚阅读数: 3
用户头像

桑榆

关注

北海虽赊,扶摇可接;东隅已逝,桑榆非晚! 2020.02.29 加入

Android手机厂商-相机软件系统工程师 爬山/徒步/Coding

评论

发布
暂无评论
Android条件控制宏编译_八月月更_桑榆_InfoQ写作社区