Android Makefile中是 如何识别 TARGET_PRODUCT 的

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android Makefile中是 如何识别 TARGET_PRODUCT 的相关的知识,希望对你有一定的参考价值。

TARGET_PRODUCT 来决定编译定制product.

首先, 编译Android 代码 通常情况下使用:

# make showcommands

这实际上等价于下面的完整命令 (具体参见 build/core/envsetup.mk )

# TARGET_ARCH=arm TARGET_PRODUCT=generic TARGET_BUILD_TYPE=release make showcommands

可见,默认情况下编译系统认为TARGET_PRODUCT 是generic 的

那如何编译特定产品的Android呢?

这就需要查看Android Makefile是如何解析环境变量TARGET_PRODUCT的。

Android Makefile 的引用关系是这样的

Makefile -> build/core/main.mk -> build/core/config.mk -> build/core/envsetup.mk -> build/core/product_config.mk

在build/core/product_config.mk 中编译系统首先调用 build/core/product.mk中定义的函数get-all-product-makefiles ,来

遍历整个vendor 的子目录, 找到vendor下所有的 AndroidProducts.mk, 不同子目录下的AndroidProducts.mk 中定义了不同的 PRODUCT_NAME, PRODUCT_DEVICE 等信息,(我们也可以通过 打开build/core/product_config.mk 中的#$(dump-products) 语句使控制台编译的时候输出所有product 的信息) , 接着build/core/product_config.mk 会调用resolve-short-product-name 将TARGET_PRODUCT匹配的AndroidProducts.mk 中定义的 PRODUCT_DEVICE 赋值给TARGET_DEVICE。

有了这个TARGET_DEVICE, 再回到 build/core/config.mk,

会include $(TARGET_DEVCIE)/BoardConfig.mk

board_config_mk := /
$(strip $(wildcard /
$(SRC_TARGET_DIR)/board/$(TARGET_DEVICE)/BoardConfig.mk /
vendor/*/$(TARGET_DEVICE)/BoardConfig.mk /
))

include $(board_config_mk)

而这个配置文件BoardConfig.mk 决定了目标系统编译属性,比如使用ALSA还是不是 GENERIC_AUDIO 等等

另外在这里TARGET_DEVICE 宏也决定了TARGET_DEVICE_DIR, 因为TARGET_DEVICE_DIR 取的是上面提到的BoardConfig.mk 的路径。

TARGET_DEVICE_DIR := $(patsubst %/,%,$(dir $(board_config_mk)))

当然Android 的Ob目标输出也是由TARGET_DEVICE决定,见build/core/envsetup.mk

TARGET_OUT_ROOT_release := $(OUT_DIR)/target
TARGET_OUT_ROOT_debug := $(DEBUG_OUT_DIR)/target
TARGET_OUT_ROOT := $(TARGET_OUT_ROOT_$(TARGET_BUILD_TYPE))

TARGET_PRODUCT_OUT_ROOT := $(TARGET_OUT_ROOT)/product

PRODUCT_OUT := $(TARGET_PRODUCT_OUT_ROOT)/$(TARGET_DEVICE)

再回到 build/core/main.mk, 编译系统接着做的一个件事情是,遍历所有字目录,找到所有Android.mk文件,并将这些Android.mk文件include 进来

#
# Typical build; include any Android.mk files we can find.
#

subdir_makefiles := /
$(shell build/tools/findleaves.py --prune=out --prune=.repo --prune=.git $(subdirs) Android.mk)

include $(subdir_makefiles)

我们再来看其中的

./build/target/board/Android.mk

,对了它引用了

include $(TARGET_DEVICE_DIR)/AndroidBoard.mk

由上面TARGET_DEVICE_DIR的定义,这下又进入了

vendor 下TARGET_DEVICE指向的目录了,这个mk文件中定义了特定Product需要编译和安装app 和 script.
参考技术A , f Q2 W8 i$ Y# i# make showcommands嵌入式开发联盟; h; Q4 ?. m, q _5 q# f4 N这实际上等价于下面的完整命令 (具体参见 build/core/envsetup.mk )# TARGET_ARCH=arm TARGET_PRODUCT=generic TARGET_BUILD_TYPE=release make showcommands可见,默认情况下编译系统认为TARGET_PRODUCT 是generic 的arm,linux,winbond,nuvoton,w90p710,w90n745,开源,嵌入式,操作系统,嵌入式开发,嵌入式联盟,linux,ecos,uclinux,t-kernel,freeos,rtems,ucos,skyeye,6 p) P/ + a9 x" e' _/ ]8 l( H8 [, e那如何编译特定产品的Android呢?arm,linux,winbond,nuvoton,w90p710,w90n745,开源,嵌入式,操作系统,嵌入式开发,嵌入式联盟,linux,ecos,uclinux,t-kernel,freeos,rtems,ucos,skyeye,7 n N* t# q" c9 c C% W这就需要查看Android Makefile是如何解析环境变量TARGET_PRODUCT的。Android Makefile 的引用关系是这样的mcuos.com1 b" z& i3 S. J5 J9 TMakefile -> build/core/main.mk -> build/core/config.mk -> build/core/envsetup.mk -> build/core/product_config.mk嵌入式开发联盟2 t1 D) I' n) x4 /+ Q# X! D在build/core/product_config.mk 中编译系统首先调用 build/core/product.mk中定义的函数get-all-product-makefiles ,来遍历整个vendor 的子目录, 找到vendor下所有的 AndroidProducts.mk, 不同子目录下的AndroidProducts.mk 中定义了不同的 PRODUCT_NAME, PRODUCT_DEVICE 等信息,(我们也可以通过 打开build/core/product_config.mk 中的#$(dump-products) 语句使控制台编译的时候输出所有product 的信息) , 接着build/core/product_config.mk 会调用resolve-short-product-name 将TARGET_PRODUCT匹配的AndroidProducts.mk 中定义的 PRODUCT_DEVICE 赋值给TARGET_DEVICE。有了这个TARGET_DEVICE, 再回到 build/core/config.mk,会include $(TARGET_DEVCIE)/BoardConfig.mkboard_config_mk := /$(strip $(wildcard /arm,linux,winbond,nuvoton,w90p710,w90n745,开源,嵌入式,操作系统,嵌入式开发,嵌入式联盟,linux,ecos,uclinux,t-kernel,freeos,rtems,ucos,skyeye,7 s6 h* H) @& B, X. [5 [' t" J& U $(SRC_TARGET_DIR)/board/$(TARGET_DEVICE)/BoardConfig.mk /vendor/*/$(TARGET_DEVICE)/BoardConfig.mk /- 我们只做简洁、实用、专业的嵌入式开发技术论坛。2 L& f% E. T& M4 S) u))我们只做简洁、专业的嵌入式开发技术论坛。5 - ~6 j# s8 s/ a* v- iinclude $(board_config_mk)嵌入式开发联盟, [. Z( H) L2 B; s, c而这个配置文件BoardConfig.mk 决定了目标系统编译属性,比如使用ALSA还是不是 GENERIC_AUDIO 等等另外在这里TARGET_DEVICE 宏也决定了TARGET_DEVICE_DIR, 因为TARGET_DEVICE_DIR 取的是上面提到的BoardConfig.mk 的路径。arm,linux,winbond,nuvoton,w90p710,w90n745,开源,嵌入式,操作系统,嵌入式开发,嵌入式联盟,linux,ecos,uclinux,t-kernel,freeos,rtems,ucos,skyeye,' ~( W" a( p& y9 g- n) A: cTARGET_DEVICE_DIR := $(patsubst %/,%,$(dir $(board_config_mk)))当然Android 的Ob目标输出也是由TARGET_DEVICE决定,见build/core/envsetup.mkTARGET_OUT_ROOT_release := $(OUT_DIR)/target我们只做简洁、专业的嵌入式开发技术论坛。 v( |. V7 ^+ T+ G& mTARGET_OUT_ROOT_debug := $(DEBUG_OUT_DIR)/targetTARGET_OUT_ROOT := $(TARGET_OUT_ROOT_$(TARGET_BUILD_TYPE))( ?. c1 J& d) o9 M. [TARGET_PRODUCT_OUT_ROOT := $(TARGET_OUT_ROOT)/productmcuos.com7 N! X' G9 T7 o& j+ # |2 S. p# xPRODUCT_OUT := $(TARGET_PRODUCT_OUT_ROOT)/$(TARGET_DEVICE)嵌入式开发联盟 P& ]2 q" C/ x: ?再回到 build/core/main.mk, 编译系统接着做的一个件事情是,遍历所有字目录,找到所有Android.mk文件,并将这些Android.mk文件include 进来## Typical build; include any Android.mk files we can find.#subdir_makefiles := /我们只做简洁、专业的嵌入式开发技术论坛。% T9 p" L4 e. O6 ?, h" @' @$(shell build/tools/findleaves.py --prune=out --prune=.repo --prune=.git $(subdirs) Android.mk)- 我们只做简洁、实用、专业的嵌入式开发技术论坛。7 N. z& r* z; @! p5 n; include $(subdir_makefiles)- 我们只做简洁、实用、专业的嵌入式开发技术论坛。0 b% j5 a+ L2 E" r9 R3 v7 m我们再来看其中的./build/target/board/Android.mk,对了它引用了本回答被提问者采纳 参考技术B , f Q2 W8 i$ Y# i# make showcommands嵌入式开发联盟; h; Q4 ?. m, q _5 q# f4 N这实际上等价于下面的完整命令 (具体参见 build/core/envsetup.mk )
# TARGET_ARCH=arm TARGET_PRODUCT=generic TARGET_BUILD_TYPE=release make showcommands
可见,默认情况下编译系统认为TARGET_PRODUCT 是generic 的arm,linux,winbond,nuvoton,w90p710,w90n745,开源,嵌入式,操作系统,嵌入式开发,嵌入式联盟,linux,ecos,uclinux,t-kernel,freeos,rtems,ucos,skyeye,6 p) P/ + a9 x" e' _/ ]8 l( H8 [, e那如何编译特定产品的Android呢?arm,linux,winbond,nuvoton,w90p710,w90n745,开源,嵌入式,操作系统,嵌入式开发,嵌入式联盟,linux,ecos,uclinux,t-kernel,freeos,rtems,ucos,skyeye,7 n N* t# q" c9 c C% W这就需要查看Android Makefile是如何解析环境变量TARGET_PRODUCT的。
Android Makefile 的引用关系是这样的mcuos.com1 b" z& i3 S. J5 J9 TMakefile -> build/core/main.mk -> build/core/config.mk -> build/core/envsetup.mk -> build/core/product_config.mk嵌入式开发联盟2 t1 D) I' n) x4 /+ Q# X! D在build/core/product_config.mk 中编译系统首先调用 build/core/product.mk中定义的函数get-all-product-makefiles ,来
遍历整个vendor 的子目录, 找到vendor下所有的 AndroidProducts.mk, 不同子目录下的AndroidProducts.mk 中定义了不同的 PRODUCT_NAME, PRODUCT_DEVICE 等信息,(我们也可以通过 打开build/core/product_config.mk 中的#$(dump-products) 语句使控制台编译的时候输出所有product 的信息) , 接着build/core/product_config.mk 会调用resolve-short-product-name 将TARGET_PRODUCT匹配的AndroidProducts.mk 中定义的 PRODUCT_DEVICE 赋值给TARGET_DEVICE。
有了这个TARGET_DEVICE, 再回到 build/core/config.mk,
会include $(TARGET_DEVCIE)/BoardConfig.mk
board_config_mk := /
$(strip $(wildcard /arm,linux,winbond,nuvoton,w90p710,w90n745,开源,嵌入式,操作系统,嵌入式开发,嵌入式联盟,linux,ecos,uclinux,t-kernel,freeos,rtems,ucos,skyeye,7 s6 h* H) @& B, X. [5 [' t" J& U $(SRC_TARGET_DIR)/board/$(TARGET_DEVICE)/BoardConfig.mk /
vendor/*/$(TARGET_DEVICE)/BoardConfig.mk /- 我们只做简洁、实用、专业的嵌入式开发技术论坛。2 L& f% E. T& M4 S) u))我们只做简洁、专业的嵌入式开发技术论坛。5 - ~6 j# s8 s/ a* v- iinclude $(board_config_mk)嵌入式开发联盟, [. Z( H) L2 B; s, c而这个配置文件BoardConfig.mk 决定了目标系统编译属性,比如使用ALSA还是不是 GENERIC_AUDIO 等等
另外在这里TARGET_DEVICE 宏也决定了TARGET_DEVICE_DIR, 因为TARGET_DEVICE_DIR 取的是上面提到的BoardConfig.mk 的路径。arm,linux,winbond,nuvoton,w90p710,w90n745,开源,嵌入式,操作系统,嵌入式开发,嵌入式联盟,linux,ecos,uclinux,t-kernel,freeos,rtems,ucos,skyeye,' ~( W" a( p& y9 g- n) A: cTARGET_DEVICE_DIR := $(patsubst %/,%,$(dir $(board_config_mk)))
当然Android 的Ob目标输出也是由TARGET_DEVICE决定,见build/core/envsetup.mk
TARGET_OUT_ROOT_release := $(OUT_DIR)/target我们只做简洁、专业的嵌入式开发技术论坛。 v( |. V7 ^+ T+ G& mTARGET_OUT_ROOT_debug := $(DEBUG_OUT_DIR)/target
TARGET_OUT_ROOT := $(TARGET_OUT_ROOT_$(TARGET_BUILD_TYPE))( ?. c1 J& d) o9 M. [TARGET_PRODUCT_OUT_ROOT := $(TARGET_OUT_ROOT)/productmcuos.com7 N! X' G9 T7 o& j+ # |2 S. p# xPRODUCT_OUT := $(TARGET_PRODUCT_OUT_ROOT)/$(TARGET_DEVICE)嵌入式开发联盟 P& ]2 q" C/ x: ?再回到 build/core/main.mk, 编译系统接着做的一个件事情是,遍历所有字目录,找到所有Android.mk文件,并将这些Android.mk文件include 进来## Typical build; include any Android.mk files we can find.#subdir_makefiles := /我们只做简洁、专业的嵌入式开发技术论坛。% T9 p" L4 e. O6 ?, h" @' @$(shell build/tools/findleaves.py --prune=out --prune=.repo --prune=.git $(subdirs) Android.mk)- 我们只做简洁、实用、专业的嵌入式开发技术论坛。7 N. z& r* z; @! p5 n; include $(subdir_makefiles)- 我们只做简洁、实用、专业的嵌入式开发技术论坛。0 b% j5 a+ L2 E" r9 R3 v7 m我们再来看其中的
./build/target/board/Android.mk
,对了它引用了

如何识别 List<T> 是不是是实现特定接口的 T 列表

【中文标题】如何识别 List<T> 是不是是实现特定接口的 T 列表【英文标题】:How to identify whether List<T> is a list of Ts that implement a specific interface如何识别 List<T> 是否是实现特定接口的 T 列表 【发布时间】:2014-10-31 20:02:24 【问题描述】:

好的,所以我有一个包含多个List 类型属性的类。

有些列表只是简单的类型,如stringint 等。 但有些是自定义类型的列表,例如 Feature、Trailer、Artwork 等。

public class Movie : IMedia

   public List<Feature> Features;
   public List<Artwork> Artwork;
   public List<string> Genres;

所有自定义类型(以及 Movie 类本身)都实现了接口 IMedia

使用反射我想遍历 Movie 属性并对 List&lt;IMedia&gt; 类型的属性做一些事情 - 但问题就在这里;因为显然我不能只使用is List&lt;IMedia&gt;,同时还想将属性指定为特定类型,例如List&lt;Feature&gt;

你们建议我如何识别这些类型?

扩展List&lt;T&gt; 本身还是完全不同的东西?

【问题讨论】:

你应该展示你的代码。没有您的代码,我们不可能知道出了什么问题。 您要识别列表的类型还是列表中元素的类型? 听起来像是扩展类的教科书用例,出于好奇,尽管 is List&lt;T&gt;.GetType() == TypeOf(List&lt;T&gt;) 应该可以工作,除非您明确重铸该类,并且如果这些类如此熟悉且仅在name 为什么区分它们的对象可以作为对象存储在类中? 这只是***.com/questions/557340/…***.com/questions/4963160/…的组合 我不建议您在简单的 BL 案例中使用反射。这似乎是一种过度概括。 IE。实现在某些条件下返回 IList 的公共方法。 【参考方案1】:

假设您实际上是在使用 properties(这是问题中提到的)而不是 private fields(这是您问题中的类正在使用的) ,你可以这样做:

var movie = new Movie()  ... ;

foreach (var prop in typeof(Movie).GetProperties())

    if (prop.PropertyType.IsGenericType && 
        prop.PropertyType.GetGenericTypeDefinition() == typeof (List<>))
    
        /* Get the generic type parameter of the List<> we're working with: */
        Type genericArg = prop.PropertyType.GetGenericArguments()[0];

        /* If this is a List of something derived from IMedia: */
        if (typeof(IMedia).IsAssignableFrom(genericArg))
        
            var enumerable = (IEnumerable)prop.GetValue(movie);

            List<IMedia> media = 
                enumerable != null ? 
                enumerable.Cast<IMedia>().ToList() : null;

            // where DoSomething takes a List<IMedia>
            DoSomething(media);
        
    

【讨论】:

这正是我想要实现的。谢谢@Andrew Whitaker @Marle1:没问题!很高兴能提供帮助。【参考方案2】:

获取第一个泛型参数的类型:

var lst = new List<MyClass>();
var t1 = lst.GetType().GenericTypeArguments[0];

检查是否可以将其转换为接口:

bool b = typeof(IInterface).IsAssignableFrom(t1);

另一种方法可能是:

var castedLst = lst.OfType<IInterface>().ToList();
bool b = castedLst.Count == lst.Count; // all items were casted successfully

【讨论】:

感谢@Yorye Nathan,您的回答对我帮助很大,非常接近我需要的,但我接受了安德鲁斯的回答,因为他提供了完整的上下文。【参考方案3】:

如果我理解正确,你必须这样做:

Type paramType = typeof(T);
if(paramType is IMedia)  /*do smt*/ 

【讨论】:

我认为你错了。 TS 想要获取 typeof(T) ,其中 T 是 List 的通用参数。 这不是“is”运算符的工作方式。 msdn.microsoft.com/en-us/library/scekt9xw.aspx

以上是关于Android Makefile中是 如何识别 TARGET_PRODUCT 的的主要内容,如果未能解决你的问题,请参考以下文章

makefile 与android.mk中加信息打印

$@ 在Linux Makefile中是啥意思

机器视觉在应用过程中是如何识别图片的?

pyqt5 如何识别该函数中是哪个qpush_button激活了该函数? [关闭]

如何将带有 Android Room 的应用添加为使用 makefile 编译的系统应用?

说一说Android事件分发中的requestDisallowInterceptTouchEvent