0
点赞
收藏
分享

微信扫一扫

Android 条件控制宏编译

条件控制宏编译是什么?

在我们进行编译文件的编写时,时常需要根据平台信息、硬件信息等选择需要编译的模块,或者进行编译的配置,同时,这也是为了向前兼容之前的模块,大部分代码都是共主线开发,使用编译宏进行控制,这一点在 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_PRINT
endif

LOCAL_SHARED_LIBRARIES := libcutils liblog libutils
include $(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 push
adb push Y:\AOSP\out\target\product\flame\system\bin\AndroidConditionCompileTest system/bin/
# run the executable
adb 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");

正常编译

Android 条件控制宏编译_条件编译

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

Android 条件控制宏编译_条件编译_02

push 之后执行如下

Android 条件控制宏编译_android_03

举报

相关推荐

0 条评论