`
mfcai
  • 浏览: 409119 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

深入了解android平台的jni(二)

阅读更多
Android.mk是Android提供的一种makefile文件,用来指定诸如编译生成so库名、引用的头文件目录、需要编译的.c/.cpp文件和.a静态库文件等。要掌握jni,就必须熟练掌握Android.mk的语法规范。

一、Android.mk文件的用途
一个android子项目中会存在一个或多个Android.mk文件
1、单一的Android.mk文件
直接参考NDK的sample目录下的hello-jni项目,在这个项目中只有一个Android.mk文件
2、多个Android.mk文件
如果需要编译的模块比较多,我们可能会将对应的模块放置在相应的目录中,
这样,我们可以在每个目录中定义对应的Android.mk文件(类似于上面的写法),
最后,在根目录放置一个Android.mk文件,内容如下:
include $(call all-subdir-makefiles)
只需要这一行就可以了,它的作用就是包含所有子目录中的Android.mk文件
3、多个模块共用一个Android.mk
这个文件允许你将源文件组织成模块,这个模块中含有:
  -静态库(.a文件)
  -动态库(.so文件)
只有共享库才能被安装/复制到您的应用软件(APK)包中
include $(BUILD_STATIC_LIBRARY),编译出的是静态库
include $(BUILD_SHARED_LIBRARY),编译出的是动态库



二、自定义变量
以下是在 Android.mk中依赖或定义的变量列表,可以定义其他变量为自己使用,但是NDK编译系统保留下列变量名:
-以 LOCAL_开头的名字(例如 LOCAL_MODULE)
-以 PRIVATE_, NDK_ 或 APP_开头的名字(内部使用)
-小写名字(内部使用,例如‘my-dir’)
  如果为了方便在 Android.mk 中定义自己的变量,建议使用 MY_前缀,一个小例子:
MY_SOURCES := foo.c
ifneq ($(MY_CONFIG_BAR),)
MY_SOURCES += bar.c
endif
LOCAL_SRC_FILES += $(MY_SOURCES)
注意:‘:=’是赋值的意思;'+='是追加的意思;‘$’表示引用某变量的值。



三、GNU Make系统变量
  这些 GNU Make变量在你的 Android.mk 文件解析之前,就由编译系统定义好了。注意在某些情况下,NDK可能分析 Android.mk 几次,每一次某些变量的定义会有不同。
  (1)CLEAR_VARS:  指向一个编译脚本,几乎所有未定义的 LOCAL_XXX 变量都在"Module-description"节中列出。必须在开始一个新模块之前包含这个脚本:include$(CLEAR_VARS),用于重置除LOCAL_PATH变量外的,所有LOCAL_XXX系列变量。
  (2)BUILD_SHARED_LIBRARY:  指向编译脚本,根据所有的在 LOCAL_XXX 变量把列出的源代码文件编译成一个共享库。
       注意,必须至少在包含这个文件之前定义 LOCAL_MODULE 和 LOCAL_SRC_FILES。
  (3)BUILD_STATIC_LIBRARY:  一个 BUILD_SHARED_LIBRARY 变量用于编译一个静态库。静态库不会复制到的APK包中,但是能够用于编译共享库。
       示例:include $(BUILD_STATIC_LIBRARY)
       注意,这将会生成一个名为 lib$(LOCAL_MODULE).a 的文件
  (4)TARGET_ARCH: 目标 CPU平台的名字
  (5)TARGET_PLATFORM: Android.mk 解析的时候,目标 Android 平台的名字.详情可考/development/ndk/docs/stable- apis.txt.
       android-3 -> Official Android 1.5 system images
       android-4 -> Official Android 1.6 system images
       android-5 -> Official Android 2.0 system images
  (6)TARGET_ARCH_ABI:  暂时只支持两个 value,armeabi 和 armeabi-v7a。。
  (7)TARGET_ABI: 目标平台和 ABI 的组合,

                              
四、模块描述变量
  下面的变量用于向编译系统描述你的模块。应该定义在'include  $(CLEAR_VARS)'和'include $(BUILD_XXXXX)'之间。$(CLEAR_VARS)是一个脚本,清除所有这些变量。
  (1)LOCAL_PATH:  这个变量用于给出当前文件的路径。
       必须在 Android.mk 的开头定义,可以这样使用:LOCAL_PATH := $(call my-dir)
       如当前目录下有个文件夹名称 src,则可以这样写 $(call src),那么就会得到 src 目录的完整路径
       这个变量不会被$(CLEAR_VARS)清除,因此每个 Android.mk 只需要定义一次(即使在一个文件中定义了几个模块的情况下)。
  (2)LOCAL_MODULE: 这是模块的名字,它必须是唯一的,而且不能包含空格。
       必须在包含任一的$(BUILD_XXXX)脚本之前定义它。模块的名字决定了生成文件的名字。
  (3)LOCAL_SRC_FILES:  这是要编译的源代码文件列表。
       只要列出要传递给编译器的文件,因为编译系统自动计算依赖。注意源代码文件名称都是相对于 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文件。
  (4)LOCAL_C_INCLUDES:  可选变量,表示头文件的搜索路径。
        默认的头文件的搜索路径是LOCAL_PATH目录。
  (5)LOCAL_STATIC_LIBRARIES: 表示该模块需要使用哪些静态库,以便在编译时进行链接。
  (6)LOCAL_SHARED_LIBRARIES:  表示模块在运行时要依赖的共享库(动态库),在链接时就需要,以便在生成文件时嵌入其相应的信息。
       注意:它不会附加列出的模块到编译图,也就是仍然需要在Application.mk 中把它们添加到程序要求的模块中。
  (7)LOCAL_LDLIBS:  编译模块时要使用的附加的链接器选项。这对于使用‘-l’前缀传递指定库的名字是有用的。
       例如,LOCAL_LDLIBS := -lz表示告诉链接器生成的模块要在加载时刻链接到/system/lib/libz.so
       可查看 docs/STABLE-APIS.TXT 获取使用 NDK发行版能链接到的开放的系统库列表。
   (8)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_MODULE_PATH 和LOCAL_UNSTRIPPED_PATH的区别,暂时还不清楚。
   (9)LOCAL_JNI_SHARED_LIBRARIES:定义了要包含的so库文件的名字,如果程序没有采用jni,不需要
        LOCAL_JNI_SHARED_LIBRARIES := libxxx 这样在编译的时候,NDK自动会把这个libxxx打包进apk; 放在youapk/lib/目录下



五、NDK提供的函数宏
GNU Make函数宏,必须通过使用'$(call  )'来调用,返回值是文本化的信息。
   (1)my-dir:返回当前 Android.mk 所在的目录的路径,相对于 NDK 编译系统的顶层。这是有用的,在 Android.mk 文件的开头如此定义:
        LOCAL_PATH := $(call my-dir)
   (2)all-subdir-makefiles: 返回一个位于当前'my-dir'路径的子目录中的所有Android.mk的列表。
       例如,某一子项目的目录层次如下:
            src/foo/Android.mk
            src/foo/lib1/Android.mk
            src/foo/lib2/Android.mk
      如果 src/foo/Android.mk 包含一行:
           include $(call all-subdir-makefiles)
      那么它就会自动包含 src/foo/lib1/Android.mk 和 src/foo/lib2/Android.mk。
      这项功能用于向编译系统提供深层次嵌套的代码目录层次。
      注意,在默认情况下,NDK 将会只搜索在 src/*/Android.mk 中的文件。
   (3)this-makefile:  返回当前Makefile 的路径(即这个函数调用的地方)
   (4)parent-makefile:  返回调用树中父 Makefile 路径。即包含当前Makefile的Makefile 路径。
   (5)grand-parent-makefile:返回调用树中父Makefile的父Makefile的路径



六、 Android.mk示例
#编译静态库
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE = libhellos
LOCAL_CFLAGS = $(L_CFLAGS)
LOCAL_SRC_FILES = hellos.c
LOCAL_C_INCLUDES = $(INCLUDES)
LOCAL_SHARED_LIBRARIES := libcutils
LOCAL_COPY_HEADERS_TO := libhellos
LOCAL_COPY_HEADERS := hellos.h
include $(BUILD_STATIC_LIBRARY)

#编译动态库
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE = libhellod
LOCAL_CFLAGS = $(L_CFLAGS)
LOCAL_SRC_FILES = hellod.c
LOCAL_C_INCLUDES = $(INCLUDES)
LOCAL_SHARED_LIBRARIES := libcutils
LOCAL_COPY_HEADERS_TO := libhellod
LOCAL_COPY_HEADERS := hellod.h
include $(BUILD_SHARED_LIBRARY)

#使用静态库
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := hellos
LOCAL_STATIC_LIBRARIES := libhellos
LOCAL_SHARED_LIBRARIES :=
LOCAL_LDLIBS += -ldl
LOCAL_CFLAGS := $(L_CFLAGS)
LOCAL_SRC_FILES := mains.c
LOCAL_C_INCLUDES := $(INCLUDES)
include $(BUILD_EXECUTABLE)

#使用动态库
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := hellod
LOCAL_MODULE_TAGS := debug
LOCAL_SHARED_LIBRARIES := libc libcutils libhellod
LOCAL_LDLIBS += -ldl
LOCAL_CFLAGS := $(L_CFLAGS)
LOCAL_SRC_FILES := maind.c
LOCAL_C_INCLUDES := $(INCLUDES)
include $(BUILD_EXECUTABLE)


本文欢迎转载,转载请注明作者与出处
作者:流星
出处:http://blog.sina.com.cn/staratsky
分享到:
评论

相关推荐

    android通过JNI访问硬件LED

    在Android系统中,Java Native Interface (JNI) 是一个关键组件,允许Java代码与其他语言(如C++或C)编写的代码进行交互...开发者可以通过学习和实践这个项目,深入了解Android系统的底层工作原理以及JNI的使用技巧。

    android studio jni demo

    Android Studio JNI Demo是一个关于在Android开发环境中使用Java Native Interface(JNI)的实例教程。JNI是Android平台中用于在...通过实践这个Demo,开发者可以深入了解JNI的工作原理,并掌握其在实际项目中的应用。

    Android 深入研究JNI详解

    在深入了解JNI(Java Native Interface)之前,我们需要明确一点:Android应用程序的主要部分是基于Java开发的,并且这些Java类会被编译成Dex格式的字节码,然后在Dalvik虚拟机上运行。这种设计模式为Android应用...

    Android--JNI-Device.zip_Android jni_android_jni_jni android

    9. **总结**:这个教程资料“Android--JNI-Device.zip”对于希望深入了解Android硬件驱动开发的开发者来说非常有价值,它将帮助开发者学习如何利用JNI高效地与设备驱动进行交互,提高应用程序的性能和功能。

    Android 6.0 AS平台 JNI 实验

    Android 6.0 平台上使用Android Studio (AS) 进行JNI开发是一个常见的实践,JNI(Java Native Interface)允许Java代码与其他编程语言(如C++)进行交互,以利用其性能优势或调用特定库。这个实验将带你了解如何在...

    android通过JNI控制LED

    在本文中,我们将深入探讨如何通过JNI在Android平台上控制硬件LED(Light Emitting Diode)。LED控制通常用于设备的状态指示或者实现特定的交互效果。 首先,我们需要了解JNI的基本概念。JNI提供了一个框架,使得...

    android-JNI

    因此,了解JNI可以提升开发者在不同平台间的代码复用能力。 通过阅读博客“android-JNI”,我们可以期待作者可能分享了如何创建和管理本地方法、解决常见的JNI问题、提高代码效率、以及如何将JNI应用于实际项目中的...

    android-jni&底层调用开发讲解

    本教程将深入讲解Android的JNI与底层C代码调用的开发过程。 首先,我们要了解JNI的基本概念。JNI是Java平台标准的一部分,它提供了一种方式,使得Java代码能够调用本地(非Java)代码,反之亦然。这使得开发者可以...

    hello-jni.rar_ android jni_android hello jni_android jni hellojn

    了解了基本的JNI开发流程后,可以深入研究更多高级主题,如多线程支持、错误处理、资源管理等。此外,NDK还提供了对C++11、OpenMP、Android Hal层接口等功能的支持,使得原生开发更具扩展性。 总结,Android NDK和...

    android jni调用demo

    通过分析这个项目,开发者可以了解如何在实际项目中使用JNI,以及如何在Android Studio中集成NDK开发环境。这个过程对于深入学习Android的系统级编程和性能优化至关重要。 总的来说,Android的JNI调用是将Java和C/...

    android_jni操作指南.pdf

    整个过程需要程序员熟悉Java编程语言,对C或C++也要有一定的了解,以及对Android开发环境有所掌握。这些知识点对于初学者来说是一次从Java跨到C/C++的旅程,而熟悉这些操作对于开发性能要求更高的Android应用是必不...

    android下一个jni方式实现的音频播放

    通过这个示例,开发者不仅可以学习如何在Android中使用JNI进行音频播放,还可以了解Android音频系统的底层工作原理,这对于开发高质量的音乐应用或游戏至关重要。同时,它也是一个实践NDK编程、提高跨平台能力的良好...

    Android下JNI和HAL技术

    同时,了解Android的系统层次结构和组件之间的关系对于成功开发JNI和HAL应用至关重要。 总的来说,JNI和HAL技术是Android系统中不可或缺的组成部分,它们为开发者提供了一种方式来实现Java应用程序与系统底层的交互...

    Android_Jni 简单调用

    首先,让我们了解Android Studio中的CMake集成。自从Android Studio 3.0引入了CMake支持以来,开发者可以直接在Android Studio项目中编写和管理C/C++代码。CMake是一个跨平台的构建系统,可以生成针对不同平台的...

    android studio jni 环境demo

    本教程将深入探讨如何在Android Studio中设置JNI环境,并通过一个"Hello, World!"的简单示例来讲解其基本用法。 首先,我们需要创建一个新的Android Studio项目。打开Android Studio,选择"Start a new Android ...

    android使用jni技术

    本教程将深入探讨如何在Android应用中使用JNI技术。 首先,我们需要理解JNI的工作原理。JNI提供了一种方式,使得Java代码可以调用本地(非Java)函数,同时本地代码也可以调用Java方法。这通常是通过创建本地方法...

    Android Hello JNI

    总结一下,Android Hello JNI教程旨在帮助开发者了解和实践JNI的基本使用。通过这个例子,你可以学习到如何设置项目结构,编写本地方法,以及如何在Java和C/C++之间进行通信。这对于那些希望利用C/C++优化Android...

    webrtc-android-jni

    WebRTC(全称Web Real-Time Communication)是一种开源项目,由Google维护,旨在提供浏览器和移动应用程序之间的...通过深入研究和使用这些内容,开发者可以深入了解WebRTC的工作原理,以及如何利用JNI来提升性能和效率。

    android的JNI获得签名及AES加密方法

    在这个主题中,我们将深入探讨如何在Android的JNI层获取签名以及实现AES加密。 首先,让我们了解如何在JNI中获取签名。在Android应用中,签名主要用于验证应用的身份,确保其来源可靠。在JNI中获取签名,通常是为了...

Global site tag (gtag.js) - Google Analytics