条件控制宏编译是什么?
在我们进行编译文件的编写时,时常需要根据平台信息、硬件信息等选择需要编译的模块,或者进行编译的配置,同时,这也是为了向前兼容之前的模块,大部分代码都是共主线开发,使用编译宏进行控制,这一点在 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 = YES
ifeq ($(CONDITION_TEST),"YES")
LOCAL_CFLAGS += -DMK_CONDITION_PRINT
endif
复制代码
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");
复制代码
正常编译
设置环境变量后编译,export ANDROIDBP_TEST="YES"
push 之后执行如下
评论