Android.mk语法规范

LOCAL_PATH:=$(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
        NmpMediaBase.cpp 

LOCAL_CPPFLAGS+= -Wall -W -Wno-format \
        -Os -O2 -fmessage-length=0 -MMD -MP -DSILENT
LOCAL_C_INCLUDES+= \
        $(LOCAL_PATH)/3rdpart/3901/include \
        /opt/ali_sdk/staging/usr/include/ali/nmp/

LOCAL_SHARED_LIBRARIES := -lstdc++ libstlport -lpthread 

LOCAL_LDLIBS:= -L./ -ljson -lc -ldl -lstdc++ -lm

#LOCAL_CXX := arm-linux-gnueabi-g++  

#LOCAL_CPP_FEATURES += exceptions
LOCAL_CPPFLAGS += -fexceptions -fpermissive

LOCAL_MODULE:=mediabase
LOCAL_MODULE_TAGS := optional
include $(BUILD_EXECUTABLE)

变量解析:

LOCAL_PATH:=$(call my-dir)
LOCAL_PATH表示此时位于工程目录的根目录中,(call my-dir)的功能由编译器提供,被用来返回当前目录的地址(这里的当前目录里包含Android.mk这个文件本身)。

include $(CLEAR_VARS)
CLEAR_VARS这个变量由编译器提供,并且指明了一个GNU Makefile文件,这个功能会清理掉所有以LOCAL_开头的内容(例如 LOCAL_MODULE、LOCAL_FILES、LOCAL_STATIC_LIBRARIES等),除了LOCAL_PATH。这句话是必须的,因为如果所有的变量都是全局的,所有的可控的编译文件都需要在一个单独的GNU中被解析并执行。

LOCAL_SRC_FILES变量必须包含一个C、C++或者java源文件的列表,这些会被编译并聚合到一个模块中。只要列出要传递给编译器的文件,因为编译系统自动计算依赖。注意源代码文件名称都是相对于 LOCAL_PATH的,你可以使用路径部分,例如:
LOCAL_SRC_FILES := foo.c toto/bar.c
Hello.c
文件之间可以用空格或Tab键进行分割,换行请用"",如果是追加源代码文件的话,请用LOCAL_SRC_FILES +=。
注意:可以LOCAL_SRC_FILES := $(call all-subdir-java-files)这种形式来包含local_path目录下的所有java文件。

LOCAL_MODULE 变量必须被定义,用来区分android.mk中的每一个模块。文件名必须是唯一的,不能有空格。注意,这里编译器会为你自动加上一些前缀和后缀,来保证文件是一致的。
BUILD_EXECUTABLE这个变量是由系统提供的,并且制定给GNU Makefile的脚本,它可以收集所有你定义的“include $(CLEAR_VARS)”中以LOCAL_开头的变量,并且决定哪些要被编译,哪些应该做的更加准确。表示将编译生成一个可执行文件。
我们同样也可以使用:
BUILD_SHARED_LIBRARY来生成一个动态库;
BUILD_STATIC_LIBRARY来生成一个静态的库;
BUILD_PACKAGE来生成一个APK;
LOCAL_OVERRIDES_PACKAGES此变量可以使其他的模块不加入编译,如源码中DeskClock的android.mk有LOCAL_OVERRIDES_PACKAGES := AlarmClock,使 AlarmClock不会加入到编译系统中,不会生成 AlarmClock.apk。

LOCAL_STATIC_LIBRARIES: 表示该模块需要使用哪些静态库,以便在编译时进行链接。
LOCAL_SHARED_LIBRARIES: 表示模块在运行时要依赖的共享库(动态库),在链接时就需要,以便在生成文件时嵌入其相应的信息。
注意:它不会附加列出的模块到编译图,也就是仍然需要在Application.mk 中把它们添加到程序要求的模块中。
LOCAL_LDLIBS: 编译模块时要使用的附加的链接器选项。这对于使用‘-l’前缀传递指定库的名字是有用的。
例如,LOCAL_LDLIBS := -lz表示告诉链接器生成的模块要在加载时刻链接到/system/lib/libz.so
可查看 docs/STABLE-APIS.TXT 获取使用 NDK发行版能链接到的开放的系统库列表。
LOCAL_LDLIBS :链接的库不产生依赖关系,一般用于不需要重新编译的库,如库不存在,则会报错找不到。且貌似只能链接那些存在于系统目录下本模块需要连接的库。如果某一个库既有动态库又有静态库,那么在默认情况下是链接的动态库而非静态库。
如:LOCAL_LDLIBS += -lm –lz –lc -lcutils –lutils –llog
如果需要指定链接库的路径则直接在后面写 -L再加路径即可
LOCAL_SHARED_LIBRARIES 会生成依赖关系,当库不存在时会去编译这个库。
LOCAL_LDFLAGS:这个编译变量传递给链接器一个一些额外的参数,比如想传递而外的库和库路径给ld,或者传递给ld linker的一些链接参数,-On,-EL{B}(大小端字节序),那么就要加到这个上面,如:
LOCAL_LDFLAGS += -L$(LOCAL_PATH)/lib/ -lHWrecog –EB{EL} –O{n} …
或者直接加上绝对路径库的全名:
LOCAL_LDFLAGS += $(LOCAL_PATH)/lib/libHWrecog.a –EB{EL} –O{n}

LOCAL_LDFLAGS +=external/test/test.so
include $(call all-subdir-makefiles)
它的作用就是包含所有子目录中的Android.mk文件
如果需要编译的模块比较多,我们可能会将对应的模块放置在相应的目录中,
这样,我们可以在每个目录中定义对应的Android.mk文件(类似于上面的写法),
最后,在根目录放置一个Android.mk文件,加入include $(call all-subdir-makefiles)

TARGET_ARCH指架构中CPU的名字已经被android开源代码明确指出了。这里的ARM包含了任何ARM-独立结构的架构,以及每个独立的CPU的版本。
TARGET_PLATFORM: Android.mk 解析的时候,目标 Android 平台的名字.
android-3 -> Official Android 1.5 system images
android-4 -> Official Android 1.6 system images
android-5 -> Official Android 2.0 system images
TARGET_ARCH_ABI: 暂时只支持两个 value,armeabi 和 armeabi-v7a
TARGET_ABI: 目标平台和 ABI 的组合

LOCAL_C_INCLUDES: 可选变量,表示头文件的搜索路径。默认的头文件的搜索路径是LOCAL_PATH目录。

LOCAL_MODULE_PATH 和 LOCAL_UNSTRIPPED_PATH
在 Android.mk 文件中, 还可以用LOCAL_MODULE_PATH 和LOCAL_UNSTRIPPED_PATH指定最后的目标安装路径.
不同的文件系统路径用以下的宏进行选择:
TARGET_ROOT_OUT:表示根文件系统。
TARGET_OUT:表示 system文件系统。
TARGET_OUT_DATA:表示 data文件系统。
用法如:LOCAL_MODULE_PATH :=$(TARGET_ROOT_OUT)
LOCAL_JNI_SHARED_LIBRARIES:定义了要包含的so库文件的名字,如果程序没有采用jni,不需要
LOCAL_JNI_SHARED_LIBRARIES := libxxx 这样在编译的时候,NDK自动会把这个libxxx打包进apk; 放在yourapk/lib/目录下

LOCAL_CFLAGS可选的编译器选项,在编译C代码文件的时候使用。这可能是有用的,指定一个附加的包含路径(相对于NDK的顶层目录),宏定义,或者编译选项。注意:不要在Android.mk中改变optimization/debugging级别,只要在Application.mk中指定合适的信息,就会自动地为你处理这个问题,在调试期间,会让NDK自动生成有用的数据文件。
LOCAL_CXXFLAGS与LOCAL_CFLAGS相同,针对C++源文件。
LOCAL_CPPFLAGS与LOCAL_CFLAGS相同,但是对C和C++sourcefiles都适用。

LOCAL_STATIC_JAVA_LIBRARIES可以用来引用第三方的jar包:

LOCAL_STATIC_JAVA_LIBRARIES := \
android-common \
guava

NDK提供的函数宏:
my-dir:返回当前 Android.mk 所在的目录的路径,相对于 NDK 编译系统的顶层。这是有用的,在 Android.mk 文件的开头如此定义:
LOCAL_PATH := $(call my-dir)
all-subdir-makefiles: 返回一个位于当前’my-dir’路径的子目录中的所有Android.mk的列表。
this-makefile: 返回当前Makefile 的路径(即这个函数调用的地方)
parent-makefile: 返回调用树中父 Makefile 路径。即包含当前Makefile的Makefile 路径。
grand-parent-makefile:返回调用树中父Makefile的父Makefile的路径

在Android.mk中,“:=”是赋值的意思;“+=”是追加的意思;“$”表示引用某变量的值。
Android.mk给变量赋值,同时用的“:=”和“=”,他们分别代表什么意思呢?
“:=” 的意思是,它右边赋得值如果是变量,只能使用在这条语句之前定义好的,而不能使用本条语句之后定义的变量;
“=”,当它的右边赋值是变量时,这个变量的定义在本条语句之前或之后都可以;

LOCAL_CERTIFICATE:在编译APK时用到,由它指定用哪个key签名,未指定的默认用testkey。

在源码的build/target/product/security目录中有四组默认签名可选:testkey platform shared media

TARGET_CPU_API:

APP_ABI: 生成制定架构的so,默认情况下之生成armeabi。

TARGET_CPU_API := all
APP_ABI := all
或者是
TARGET_CPU_API := armeabi armeabi-v7a x86 x86_64 arm64-v8a mips mips64 中的一种或多种
APP_ABI := armeabi armeabi-v7a x86 x86_64 arm64-v8a mips mips64 中的一种或多种

Android 预置apk 的Android.mk

include $(CLEAR_VARS)
LOCAL_MODULE := AAAA
LOCAL_SRC_FILES := AAAA/$(LOCAL_MODULE).apk
LOCAL_MODULE_CLASS := APPS
LOCAL_MODULE_TAGS := optional
LOCAL_CERTIFICATE := platform
LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
LOCAL_MULTILIB := 32
#Add for move apk to /system/priv-app
LOCAL_PREBUILT_JNI_LIBS :=  \
    AAAA/lib/armeabi-v7a/lib*.so \
    AAAA/lib/armeabi-v7a/lib*.so \
    AAAA/lib/armeabi-v7a/lib*.so
LOCAL_PRIVILEGED_MODULE := true
LOCAL_MODULE_DELETE_LIBS := true
include $(BUILD_PREBUILT)
LOCAL_MULTILIB := 可选值为 32/64/both/first

对于包含lib库文件的apk,还需要根据预置目标路径,在mk脚本中作不同的处理:
情况一:对于预置到data/app/目录下的apk,包括可恢复和不可恢复(即上一段 c) 和 d)), 一般lib库文件可以不用手动添加,apk在首次运行时,会自动将自身的lib库抽取安装到自身的根目录;
情况二:对于预置到system/app/ 和 system/priv-app 目录下的apk(即上一段 a) 和 b)),因为在android系统中,system分区是不允许应用执行写操作的,因此需要在Android.mk脚本中进行配置,手动添加lib库文件到编译环境,以便lib库文件在编译之后拷贝到对应编译后的apk目录下,否则apk执行时会因找不到lib库而报错;

<一>、首先根据 情况二 所述,添加lib库文件到编译环境
方法一 不从apk中解压lib库而直接添加

如下例,在Android.mk中添加并配置变量(注意路径对应):

LOCAL_PREBUILT_JNI_LIBS =
@lib/armeabi-v7a/libcryptox.so
@lib/armeabi-v7a/libfb.so
注意前面的 @符号,@标识符会将apk中的so抽离出来,拷贝到对应编译后的apk目录;注意,这个操作会把apk里面的so移除掉。

方法二 手动解压lib文件到当前apk的编译目录并添加

先解压当前apk内的lib文件夹到当前apk编译目录,同方法一在Android.mk中添加并配置变量(注意路径对应),如下例:

LOCAL_PREBUILT_JNI_LIBS =
lib/armeabi-v7a/libcryptox.so
lib/armeabi-v7a/libfb.so
若当前apk包含的lib库文件数量比较多时,上述代码可以通过修改为如下代码进行优化,优化的思路是用递归搜索来替代手工对lib库文件进行添加:

###清空临时变量JNI_LIBS
JNI_LIBS :=
###当前目录递归搜索
( f o r e a c h F I L E , (foreach FILE, (foreachFILE,(shell find $(LOCAL_PATH)/lib/ -name *.so), $(eval JNI_LIBS += $(FILE)))
###获取搜索文件目录集(相对目录)
LOCAL_PREBUILT_JNI_LIBS := $(subst ( L O C A L P A T H ) , , (LOCAL_PATH),, (LOCALPATH),,(JNI_LIBS))
或者解压apk把所有的lib全部添加

LOCAL_PREBUILT_JNI_LIBS :=
( p a t s u b s t (patsubst %,@%, (patsubst(shell unzip -l ( L O C A L P A T H ) / (LOCAL_PATH)/ (LOCALPATH)/(LOCAL_SRC_FILES) | awk ‘{print $$NF}’ | grep “lib/.*.so”))

变量赋值:
makefile中可以为一个变量赋值,然后再 c++ 文件中使用,类似:

makefile:

USE_MIDDLEWARE := 1
c++:

#if USE_MIDDLEWARE

#endif
具体赋值的方法:

= 是最基本的赋值
:= 是覆盖之前的值
?= 是如果没有被赋值过就赋予等号后面的值
+= 是添加等号后面的值
“=”赋值:make会将整个makefile展开后,再决定变量的值。也就是说,变量的值将会是整个makefile中最后被指定的值。如例:

x = foo
y = $(x) bar
x = ABC

在上例中,y的值将会是 ABC bar ,而不是 foo bar 。

“:=”

“:=”赋值:“:”表示变量的值决定于它在makefile中的位置,而不是整个makefile展开后的最终值。

x := foo
y := $(x) bar
x := abc

在上例中,y的值将会是 foo bar ,而不是 abc bar 。

Android常用:
http://blog.youkuaiyun.com/wh_19910525/article/details/7518190

http://blog.youkuaiyun.com/yangzhiloveyou/article/details/8627969

LOCAL_JARJAR_RULES:

LOCAL_JARJAR_RULES := jarjar-rules.txt

可以先看jarjar-rules.txt文件的内容:

rule org.bouncycastle.** com.android.@0

rule com.android.org.chromium.** com.test.android.org.chromium.@1

The build will change all org.bouncycastle to com.android.org.bouncycastle. Therefore, in your classes which are dependent on the library produced, the import statements should look like:
import com.android.org.bouncycastle…

change all com.android.org.chromium to com.test.android.org.chromium

LOCAL_AAPT_FLAGS

LOCAL_AAPT_FLAGS := $(android_webview_aapt_flags)
LOCAL_AAPT_FLAGS += --auto-add-overlay
LOCAL_AAPT_FLAGS += --extra-packages org.chromium.content
LOCAL_AAPT_FLAGS += --extra-packages org.chromium.ui
R资源生成别名:如果是com.android.test.R,会同时生成org.chromium.content.R和org.chromium.ui.R

LOCAL_RESOURCE_DIR

LOCAL_RESOURCE_DIR :=
$(res_overrides)
$(LOCAL_PATH)/res
$(android_webview_resources_dirs)

Makefile中打印变量

$(warning res_overrides = $(res_overrides))

LOCAL_PROGUARD_ENABLED

LOCAL_PROGUARD_ENABLED := full
LOCAL_PROGUARD_ENABLED := disabled

LOCAL_PROGUARD_FLAG_FILES

LOCAL_PROGUARD_FLAG_FILES := proguard.flags

proguard文件

引入第三方jar包:

LOCAL_PREBUILT_JAVA_LIBRARIES

LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES

LOCAL_STATIC_JAVA_LIBRARIES

include $(CLEAR_VARS)

表示在当前目录下的lib/iptv.jar进行预处理到android jar包的目录中去

#LOCAL_PREBUILT_JAVA_LIBRARIES := libiptv:lib/iptv.jar
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := \
libiptv:lib/iptv.jar

include $(BUILD_MULTI_PREBUILT)

需要在编译apk 中进行、并添加:
LOCAL_STATIC_JAVA_LIBRARIES := libiptv

PRODUCT_CHARACTERISTICS

标注具体产品类型,比如手机,平板电脑,TV等

具体可以参考:http://blog.youkuaiyun.com/heqiangflytosky/article/details/53419766

LOCAL_PREBUILT_JNI_LIBS

LOCAL_PREBUILT_JNI_LIBS = \
@lib/armeabi-v7a/libcryptox.so \
@lib/armeabi-v7a/libfb.so 

或者:

LOCAL_PREBUILT_JNI_LIBS = \
lib/armeabi-v7a/libcryptox.so \
lib/armeabi-v7a/libfb.so

注意前面的 @符号,@标识符会将apk中的so抽离出来,拷贝到对应编译后的apk目录

不带 @符号需要先解压当前apk内的lib文件夹到当前apk编译目录

常见错误及解决办法:
fatal error: string: No such file or directory

解决办法:增加Application.mk 写 APP_STL :=gnustl_static或gnustl_shared或stlport_shared或stlport_static

如果在Android源码中编译可以使用stlport库,并包含头文件external/stlport/stlport,bionic/libstdc++/include,bionic

error: ‘pthread_rwlock_t’ does not name a type
在Application.mk中添加改写application.mk文件,把版本改成9或更高,APP_PLATFORM := android-9 //对应2.3.1;
在Android API < 9时,采用android NDK编译代码是不支持pthread_rwlock_t结构体的。

[11:08:50:530]I/DEBUG   ( 1021): backtrace:
[11:08:50:531]I/DEBUG   ( 1021):     #00  pc 0001e4e8  /system/lib/libc.so
[11:08:50:546]I/DEBUG   ( 1021):     #01  pc 0001c510  /system/lib/libc.so (abort+4)
[11:08:50:547]I/DEBUG   ( 1021):     #02  pc 000121d1  /system/lib/libc.so
[11:08:50:557]I/DEBUG   ( 1021):     #03  pc 00010e81  /system/lib/libc.so (dlfree+1184)
[11:08:50:558]I/DEBUG   ( 1021):     #04  pc 0000d9bf  /system/lib/libc.so (free+10)
[11:08:50:570]I/DEBUG   ( 1021):     #05  pc 00003c8d  /system/bin/nmpmedia

遇到这种问题,在Android.mk中加上 LOCAL_CPPFLAGS+=-D_STLP_USE_NEWALLOC 试一下;

http://www.cnblogs.com/leaven/archive/2012/08/15/2640702.html

http://blog.youkuaiyun.com/dotphoenix/article/details/7160983

另外出现类似段错误的时候可以使用ndk的命令arm-eabi-addr2line来定位错误出现的位置;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值