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