https://android.googlesource.com/platform/development/+/donut-release/ndk/docs/OVERVIEW.TXT
https://android.googlesource.com/platform/ndk/+/4e159d95ebf23b5f72bb707b0cb1518ef96b3d03/docs/ANDROID-MK.TXT
https://android.googlesource.com/platform/ndk/+/4e159d95ebf23b5f72bb707b0cb1518ef96b3d03/docs/APPLICATION-MK.TXT
http://hualang.iteye.com/blog/1149359
http://blog.csdn.net/smfwuxiao/article/details/8523479
- Android NDK Overview
- Introduction:
- The Android NDK is a set of tools that allows Android application developers
- to embed native machine code compiled from C and/or C++ source files into
- their application packages.
- IMPORTANT:
- The Android NDK can only be used to target Android system images
- running Cupcake (a.k.a 1.5) or later versions of the platform.
- 1.0 and 1.1 system images are specifically *not* supported due to
- subtle ABI and toolchain changes that happened for the 1.5 release.
- I. Android NDK Goals:
- ---------------------
- The Android VM allows your application‘s source code to call methods
- implemented in native code through the JNI. In a nutshell, this means that:
- - Your application‘s source code will declare one or more methods
- with the ‘native‘ keyword to indicate that they are implemented through
- native code. E.g.:
- native byte[] loadFile(String filePath);
- - You must provide a native shared library that contains the
- implementation of these methods, which will be packaged into your
- application‘s .apk. This library must be named according to standard
- Unix conventions as lib<something>.so, and shall contain a standard JNI
- entry point (more on this later). For example:
- libFileLoader.so
- - Your application must explicitely load the library. For example, to load
- it at application startup, simply add the following to its source code:
- static {
- System.loadLibrary("FileLoader");
- }
- Note that you should not use the ‘lib‘ prefix and ‘.so‘ suffix here.
- The Android NDK is a complement to the Android SDK that helps you to:
- - Generate JNI-compatible shared libraries that can run on the Android
- 1.5 platform (and later) running on ARM CPUs.
- - Copy the generated shared libraries to a proper location of your
- application project path, so they will be automatically added to your
- final (and signed) .apks
- - In later revisions of the NDK, we intend to provide tools that help
- debug your native code through a remote gdb connection and as much
- source/symbol information as possible.
- Moreover, the Android NDK provides:
- - A set of cross-toolchains (compilers, linkers, etc..) that can
- generate native ARM binaries on Linux, OS X and Windows (with Cygwin)
- - A set of system headers corresponding to the list of stable native APIs
- supported by the Android platform. This corresponds to definitions that
- are guaranteed to be supported in all later releases of the platform.
- They are documented in the file docs/STABLE-APIS.TXT
- IMPORTANT:
- Keep in mind that most of the native system libraries in Android system
- images are not frozen and might changed drastically, or even deleted,
- in later updates and releases of the platform.
- - A build system that allow developers to only write very short build files
- to describe which sources need to be compiled, and how. The build system
- deals with all the hairy toolchain/platform/CPU/ABI specifics. Moreover,
- later updates of the NDK can add support for more toolchains, platforms,
- system interfaces without requiring changes in the developer‘s build
- files (more on this later).
- II. Android NDK Non-Goals:
- --------------------------
- The NDK is *not* a good way to write generic native code that runs on Android
- devices. In particular, your applications should still be written in the Java
- programming language, handle Android system events appropriately to avoid the
- "Application Not Responding" dialog or deal with the Android application
- life-cycle.
- Note however that is is possible to write a sophisticated application in
- native code with a small "application wrapper" used to start/stop it
- appropriately.
- A good understanding of JNI is highly recommended, since many operations
- in this environment require specific actions from the developers, that are
- not necessarily common in typical native code. These include:
- - Not being able to directly access the content of VM objects through
- direct native pointers. E.g. you cannot safely get a pointer to a
- String object‘s 16-bit char array to iterate over it in a loop.
- - Requiring explicit reference management when the native code wants to
- keep handles to VM objects between JNI calls.
- The NDK only provides system headers for a very limited set of native
- APIs and libraries supported by the Android platform. While a typical
- Android system image includes many native shared libraries, these should
- be considered an implementation detail that might change drastically between
- updates and releases of the platform.
- If an Android system library is not explicitely supported by the NDK
- headers, then applications should not depend on it being available, or
- they risk breaking after the next over-the-air system update on various
- devices.
- Selected system libraries will gradually be added to the set of stable NDK
- APIs.
- III. NDK development in practice:
- ---------------------------------
- Here‘s a very rough overview of how you can develop native code with the
- Android NDK:
- 1/ Run build/host-setup.sh to configure the NDK
- 2/ Place your native sources under $PROJECT/jni/...
- 3/ Write $PROJECT/jni/Android.mk to describe your sources
- to the NDK build system
- 4/ Write apps/<myapp>/Application.mk to describe your application
- and the native sources it needs to the NDK build system
- 5/ Build your native code by running "make APP=<myapp>"
- in the top-level NDK directory.
- The last step will copy, in case of success, the stripped shared libraries
- your application needs to your application‘s root project directory. You
- will then need to generate your final .apk through the usual means.
- Now, for a few more details:
- III.1/ Configuring the NDK:
- - - - - - - - - - - - - - -
- After installing the NDK as described in docs/INSTALL.TXT, you should call
- the ‘build/host-setup.sh‘ script to configure your NDK.
- This script is used to probe your host system and verify a few pre-requisites.
- It will then generate a configuration file (e.g. out/host/config-host.mk) that
- is later used during NDK builds.
- In some cases, this might instruct you to download an archive containing
- prebuilt toolchain binaries for your development platform, the unzip it
- to the NDK root directory. The message should contain enough information
- to let you do that.
- If you forget this step, trying to build with the NDK will generate an
- error message telling you what to do.
- III.2/ Placing C and C++ sources:
- - - - - - - - - - - - - - - - - -
- You should place your native sources under the following directory:
- $PROJECT/jni/
- Where $PROJECT corresponds to the path of your Android application
- project.
- You are pretty free to organize the content of ‘jni‘ as you want,
- the directory names and structure here will not influence the final
- generated application packages, so you don‘t have to use pseudo-unique
- names like com.<mycompany>.<myproject> as is the case for application
- package names.
- Note that C and C++ sources are supported. The default C++ file extensions
- supported by the NDK is ‘.cpp‘, but other extensions can be handled as well
- (see docs/ANDROID-MK.TXT for details).
- It is possible to store your sources in a different location by adjusting
- your Android.mk file (see below).
- III.3/ Writing an Android.mk build script:
- - - - - - - - - - - - - - - - - - - - - - -
- An Android.mk file is a small build script that you write to describe your
- sources to the NDK build system. Its syntax is described in details in
- the file docs/ANDROID-MK.TXT.
- In a nutshell, the NDK groups your sources into "modules", where each module
- can be one of the following:
- - a static library
- - a shared library
- You can define several modules in a single Android.mk, or you can write
- several Android.mk files, each one defining a single module.
- Note that a single Android.mk might be parsed several times by the build
- system so don‘t assume that certain variables are not defined in them.
- By default, the NDK will look for the following build script:
- $PROJECT/jni/Android.mk
- If you want to define Android.mk files in sub-directories, you should
- include them explicitely in your top-level Android.mk. There is even
- a helper function to do that, i.e. use:
- include $(call all-subdir-makefiles)
- This will include all Android.mk files in sub-directories of the current
- build file‘s path.
- III.4/ Writing an Application.mk build file:
- - - - - - - - - - - - - - - - - - - - - - - -
- While an Android.mk file describes your modules to the build system, you
- need to write an Application.mk file to describe your application and the
- modules it requires. This file must be located in:
- $NDK/apps/<myapp>/Application.mk
- Where <myapp> is a short descriptive name for your application that will
- be used to invoke the NDK build (and not go into final APKs). The file is
- used to provide the following to the NDK build:
- - The location of your Android application‘s project path
- - The list of NDK modules that is required by your application.
- This should really be a list of ‘shared library‘ modules.
- - Optional information, like whether you want a release or debug
- build, specific C or C++ compiler flags and others.
- - Planned: the list of specific platforms/CPUs you want to explicitely
- target (currently only one is supported).
- The syntax of an Application.mk file is very simple and is described in
- docs/APPLICATION-MK.TXT
- You can define several Application.mk corresponding to different builds
- of the same application, for example:
- $NDK/apps/release/Application.mk
- $NDK/apps/debug/Application.mk
- III.5/ Invoke the NDK build system:
- - - - - - - - - - - - - - - - - - -
- On the command-line, go to the top-level NDK directory, then invoke the
- build system with:
- make APP=<myapp>
- Where ‘make‘ refers to GNU Make, and <myapp> is the name of one of the
- subdirectories of ‘$NDK/apps/‘
- This will try to build all modules with relevant options, the final
- shared libraries listed by your Application.mk and, in case of success,
- will copy stripped versions of the shared libraries to your application‘s
- project path. (Note that unstripped versions are kept for debugging
- purposes, there is no need to copy unstripped binaries to a device).
- IV. Debugging support:
- - - - - - - - - - - - -
- Debugging your native code with this initial release of the NDK is still
- very rough.
- Note that we plan to make this much easier in a later NDK release, all of
- this without changing your sources, Android.mk and Application.mk files.
- =========================
-
- Android.mk file syntax specification
- Introduction:
- -------------
- This document describes the syntax of Android.mk build file
- written to describe your C and C++ source files to the Android
- NDK. To understand what follows, it is assumed that you have
- read the docs/OVERVIEW.TXT file that explains their role and
- usage.
- Overview:
- ---------
- An Android.mk file is written to describe your sources to the
- build system. More specifically:
- - The file is really a tiny GNU Makefile fragment that will be
- parsed one or more times by the build system. As such, you
- should try to minimize the variables you declare there and
- do not assume that anything is not defined during parsing.
- - The file syntax is designed to allow you to group your
- sources into ‘modules‘. A module is one of the following:
- - a static library
- - a shared library
- Only shared libraries will be installed/copied to your
- application package. Static libraries can be used to generate
- shared libraries though.
- You can define one or more modules in each Android.mk file,
- and you can use the same source file in several modules.
- - The build system handles many details for you. For example, you
- don‘t need to list header files or explicit dependencies between
- generated files in your Android.mk. The NDK build system will
- compute these automatically for you.
- This also means that, when updating to newer releases of the NDK,
- you should be able to benefit from new toolchain/platform support
- without having to touch your Android.mk files.
- Note that the syntax is *very* close to the one used in Android.mk files
- distributed with the full open-source Android platform sources. While
- the build system implementation that uses them is different, this is
- an intentional design decision made to allow reuse of ‘external‘ libraries‘
- source code easier for application developers.
- Simple example:
- ---------------
- Before describing the syntax in details, let‘s consider a simple
- "hello world" example, i.e. the following files:
- sources/helloworld/helloworld.c
- sources/helloworld/Android.mk
- Where ‘helloworld.c‘ is the source of a simple JNI shared library
- that implements a native method that returns the "hello world"
- string.
- The corresponding Android.mk file will look like this:
- ---------- cut here ------------------
- LOCAL_PATH := $(call my-dir)
- include $(CLEAR_VARS)
- LOCAL_MODULE := helloworld
- LOCAL_SRC_FILES := helloworld.c
- include $(BUILD_SHARED_LIBRARY)
- ---------- cut here ------------------
- Now, let‘s explain these lines:
- LOCAL_PATH := $(call my-dir)
- An Android.mk file must begin with the definition of the LOCAL_PATH variable.
- It is used to locate source files in the development tree. In this example,
- the macro function ‘my-dir‘, provided by the build system, is used to return
- the path of the current directory (i.e. the directory containing the
- Android.mk file itself).
- include $(CLEAR_VARS)
- The CLEAR_VARS variable is provided by the build system and points to a
- special GNU Makefile that will clear many LOCAL_XXX variables for you
- (e.g. LOCAL_MODULE, LOCAL_SRC_FILES, LOCAL_STATIC_LIBRARIES, etc...),
- with the exception of LOCAL_PATH. This is needed because all build
- control files are parsed in a single GNU Make execution context where
- all variables are global.
- LOCAL_MODULE := helloworld
- The LOCAL_MODULE variable must be defined to identify each module you
- describe in your Android.mk. The name must be *unique* and not contain
- any spaces. Note that the build system will automatically add proper
- prefix and suffix to the corresponding generated file. In other words,
- a shared library module named ‘foo‘ will generate ‘libfoo.so‘.
- IMPORTANT NOTE:
- If you name your module ‘libfoo‘, the build system will not
- add another ‘lib‘ prefix and will generate libfoo.so as well.
- This is to support Android.mk files that originate from the
- Android platform sources, would you need to use these.
- LOCAL_SRC_FILES := helloworld.c
- The LOCAL_SRC_FILES variables must contain a list of C and/or C++ source
- files that will be built and assemble into a module. Note that you should
- not list header and included files here, because the build system will
- compute dependencies automatically for you; just list the source files
- that will be passed directly to a compiler, and you should be good.
- Note that the default extension for C++ source files is ‘.cpp‘. It is
- however possible to specify a different one by defining the variable
- LOCAL_DEFAULT_CPP_EXTENSION. Don‘t forget the initial dot (i.e. ‘.cxx‘
- will work, but not ‘cxx‘).
- include $(BUILD_SHARED_LIBRARY)
- The BUILD_SHARED_LIBRARY is a variable provided by the build system that
- points to a GNU Makefile script that is in charge of collecting all the
- information you defined in LOCAL_XXX variables since the latest
- ‘include $(CLEAR_VARS)‘ and determine what to build, and how to do it
- exactly. There is also BUILD_STATIC_LIBRARY to generate a static library.
- There are more complex examples under sources/samples, with commented
- Android.mk files that you can look at.
- Reference:
- ----------
- This is the list of variables you should either rely on or define in
- an Android.mk. You can define other variables for your own usage, but
- the NDK build system reserves the following variable names:
- - names that begin with LOCAL_ (e.g. LOCAL_MODULE)
- - names that begin with PRIVATE_, NDK_ or APP_ (used internally)
- - lower-case names (used internally, e.g. ‘my-dir‘)
- If you need to define your own convenience variables in an Android.mk
- file, we recommend using the MY_ prefix, for a trivial example:
- ---------- cut here ------------------
- MY_SOURCES := foo.c
- ifneq ($(MY_CONFIG_BAR),)
- MY_SOURCES += bar.c
- endif
- LOCAL_SRC_FILES += $(MY_SOURCES)
- ---------- cut here ------------------
- So, here we go:
- NDK-provided variables:
- - - - - - - - - - - - -
- These GNU Make variables are defined by the build system before
- your Android.mk file is parsed. Note that under certain circumstances
- the NDK might parse your Android.mk several times, each with different
- definition for some of these variables.
- CLEAR_VARS
- Points to a build script that undefines nearly all LOCAL_XXX variables
- listed in the "Module-description" section below. You must include
- the script before starting a new module, e.g.:
- include $(CLEAR_VARS)
- BUILD_SHARED_LIBRARY
- Points to a build script that collects all the information about the
- module you provided in LOCAL_XXX variables and determines how to build
- a target shared library from the sources you listed. Note that you
- must have LOCAL_MODULE and LOCAL_SRC_FILES defined, at a minimum before
- including this file. Example usage:
- include $(BUILD_SHARED_LIBRARY)
- note that this will generate a file named lib$(LOCAL_MODULE).so
- BUILD_STATIC_LIBRARY
- A variant of BUILD_SHARED_LIBRARY that is used to build a target static
- library instead. Static libraries are not copied into your
- project/packages but can be used to build shared libraries (see
- LOCAL_STATIC_LIBRARIES and LOCAL_STATIC_WHOLE_LIBRARIES described below).
- Example usage:
- include $(BUILD_STATIC_LIBRARY)
- Note that this will generate a file named lib$(LOCAL_MODULE).a
- TARGET_ARCH
- Name of the target CPU architecture as it is specified by the
- full Android open-source build. This is ‘arm‘ for any ARM-compatible
- build, independent of the CPU architecture revision.
- TARGET_PLATFORM
- Name of the target Android platform when this Android.mk is parsed.
- For now, only ‘android-1.5‘ is supported.
- TARGET_ARCH_ABI
- Name of the target CPU+ABI when this Android.mk is parsed.
- For now, only ‘arm‘ is supported, which really means the following:
- ARMv5TE or higher CPU, with ‘softfloat‘ floating point support
- Other target ABIs will be introduced in future releases of the NDK
- and will have a different name. Note that all ARM-based ABIs will
- have ‘TARGET_ARCH‘ defined to ‘arm‘, but may have different
- ‘TARGET_ARCH_ABI‘
- TARGET_ABI
- The concatenation of target platform and abi, it really is defined
- as $(TARGET_PLATFORM)-$(TARGET_ARCH_ABI) and is useful when you want
- to test against a specific target system image for a real device.
- By default, this will be ‘android-1.5-arm‘
- NDK-provided function macros:
- - - - - - - - - - - - - - - -
- The following are GNU Make ‘function‘ macros, and must be evaluated
- by using ‘$(call <function>)‘. They return textual information.
- my-dir
- Returns the path of the current Android.mk‘s directory, relative
- to the top of the NDK build system. This is useful to define
- LOCAL_PATH at the start of your Android.mk as with:
- LOCAL_PATH := $(call my-dir)
- all-subdir-makefiles
- Returns a list of Android.mk located in all sub-directories of
- the current ‘my-dir‘ path. For example, consider the following
- hierarchy:
- sources/foo/Android.mk
- sources/foo/lib1/Android.mk
- sources/foo/lib2/Android.mk
- If sources/foo/Android.mk contains the single line:
- include $(call all-subdir-makefiles)
- Then it will include automatically sources/foo/lib1/Android.mk and
- sources/foo/lib2/Android.mk
- This function can be used to provide deep-nested source directory
- hierarchies to the build system. Note that by default, the NDK
- will only look for files in sources/*/Android.mk
- this-makefile
- Returns the path of the current Makefile (i.e. where the function
- is called).
- parent-makefile
- Returns the path of the parent Makefile in the inclusion tree,
- i.e. the path of the Makefile that included the current one.
- grand-parent-makefile
- Guess what...
- Module-description variables:
- - - - - - - - - - - - - - - -
- The following variables are used to describe your module to the build
- system. You should define some of them between an ‘include $(CLEAR_VARS)‘
- and an ‘include $(BUILD_XXXXX)‘. As written previously, $(CLEAR_VARS) is
- a script that will undefine/clear all of these variables, unless explicitely
- noted in their description.
- LOCAL_PATH
- This variable is used to give the path of the current file.
- You MUST define it at the start of your Android.mk, which can
- be done with:
- LOCAL_PATH := $(call my-dir)
- This variable is *not* cleared by $(CLEAR_VARS) so only one
- definition per Android.mk is needed (in case you define several
- modules in a single file).
- LOCAL_MODULE
- This is the name of your module. It must be unique among all
- module names, and shall not contain any space. You MUST define
- it before including any $(BUILD_XXXX) script.
- The module name determines the name of generated files, e.g.
- lib<foo>.so for a shared library module named <foo>. However
- you should only refer to other modules with their ‘normal‘
- name (e.g. <foo>) in your NDK build files (either Android.mk
- or Application.mk)
- LOCAL_SRC_FILES
- This is a list of source files that will be built for your module.
- Only list the files that will be passed to a compiler, since the
- build system automatically computes dependencies for you.
- Note that source files names are all relative to LOCAL_PATH and
- you can use path components, e.g.:
- LOCAL_SRC_FILES := foo.c \
- toto/bar.c
- NOTE: Always use Unix-style forward slashes (/) in build files.
- Windows-style back-slashes will not be handled properly.
- LOCAL_CPP_EXTENSION
- This is an optional variable that can be defined to indicate
- the file extension of C++ source files. The default is ‘.cpp‘
- but you can change it. For example:
- LOCAL_CPP_EXTENSION := .cxx
- LOCAL_CFLAGS
- An optional set of compiler flags that will be passed when building
- C source files (*not* C++ sources).
- This can be useful to specify an additionnal include path
- (relative to the top of the NDK directory), macro definitions
- or compile options.
- IMPORTANT: Try not to change the optimization/debugging level in
- your Android.mk, this can be handled automatically for
- you by specifying the appropriate information in
- your Application.mk, and will let the NDK generate
- useful data files used during debugging.
- LOCAL_CXXFLAGS
- Same as LOCAL_CFLAGS for C++ source files
- LOCAL_CPPFLAGS
- Same as LOCAL_CFLAGS but used for both C and C++ source files
- LOCAL_STATIC_LIBRARIES
- The list of static libraries modules (built with BUILD_STATIC_LIBRARY)
- that should be linked to this module. This only makes sense in
- shared library modules.
- LOCAL_SHARED_LIBRARIES
- The list of shared libraries *modules* this module depends on at runtime.
- This is necessary at link time and to embed the corresponding information
- in the generated file.
- Note that this does not append the listed modules to the build graph,
- i.e. you should still add them to your application‘s required modules
- in your Application.mk
- ===================
-
- Application.mk file syntax specification
- Introduction:
- -------------
- This document describes the syntax of Application.mk build files
- written to describe the native modules required by your Android
- application. To understand what follows, it is assumed that you have
- read the docs/OVERVIEW.TXT file that explains their role and
- usage.
- Readers of this document should have read docs/OVERVIEW.TXT and
- docs/ANDROID-MK.TXT
- Overview:
- ---------
- The purpose of Application.mk is to describe which native
- ‘modules‘ (i.e. static/shared libraries) are needed by your
- application.
- Each Application.mk must be placed under a sub-directory of
- the top-level apps directory, e.g.:
- $NDK/apps/<myapp>/Application.mk
- Where <myapp> is a short name used to describe your ‘application‘
- to the NDK build system (this name doesn‘t go into your generated
- shared libraries or your final packages).
- The Application.mk is really a tiny GNU Makefile fragment that must
- define a few variables:
- APP_MODULES
- This variable is mandatory and lists all the native modules
- (described through Android.mk files) that your application
- requires.
- This must be a space-separated list of module names as they
- appear in the LOCAL_MODULE definitions of Android.mk files
- APP_PROJECT_PATH
- This variable is mandatory and should give the *absolute*
- path to your Application‘s project root directory. This is used
- to copy/install stripped versions of the generated JNI shared
- libraries to a specific location known to the APK-generating tools.
- APP_OPTIM
- This optional variable can be defined to either ‘release‘ or
- ‘debug‘. This is used to alter the optimization level when
- building your application‘s modules.
- A ‘release‘ mode is the default, and will generate highly
- optimized binaries. The ‘debug‘ mode will generate un-optimized
- binaries which are much easier to debug.
- Note that it is possible to debug both ‘release‘ and ‘debug‘
- binaries, but the ‘release‘ builds tend to provide less information
- during debugging sessions: some variables are optimized out and
- can‘t be inspected, code re-ordering can make stepping through
- the code difficult, stack traces may not be reliable, etc...
- APP_CFLAGS
- A set of C compiler flags passed when compiling any C source code
- of any of the modules. This can be used to change the build of a given
- module depending on the application that needs it, instead of modifying
- the Android.mk file itself.
- IMPORTANT WARNING: +++++++++++++++++++++++++++++++++++++++++++++++++++
- +
- + All paths in these flags should be relative to the top-level NDK
- + directory. For example, if you have the following setup:
- +
- + sources/foo/Android.mk
- + sources/bar/Android.mk
- +
- + To specify in foo/Android.mk that you want to add the path to the
- + ‘bar‘ sources during compilation, you should use:
- +
- + APP_CFLAGS += -Isources/bar
- +
- + Or alternatively:
- +
- + APP_CFLAGS += -I$(LOCAL_PATH)/../bar
- +
- + Using ‘-I../bar‘ will *NOT* work since it will be equivalent to
- + ‘-I$NDK_ROOT/../bar‘ instead.
- +
- +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- APP_CXXFLAGS
- Same as APP_CFLAGS for C++ sources.
- APP_CPPFLAGS
- Same as APP_CFLAGS but will be passed to both C and C++ sources
- A trivial Application.mk file would be:
- -------------- cut here -------------------------
- APP_MODULES := <list of modules>
- APP_PROJECT_PATH := <path to project>
- -------------- cut here -------------------------
- ============================
- Application.mk文件
简介:
-----------------------------
要将C\C++代码编译为SO文件,光有Android.mk文件还不行,还需要一个Application.mk文件。
本文档是描述你的Android应用程序中需要的本地模块的Application.mk的语法使用,要明白如下。Application.mk目的是描述在你的应用程序中所需要的模块(即静态库或动态库)。
Application.mk文件通常被放置在$PROJECT/jni/Application.mk下,$PROJECT指的是您的项目。
另一种方法是将其放在顶层的子目录下:
$NDK/apps目录下,例如:
$NDK/apps/<myapp>/Application.mk<myapp>是一个简称,用于描述你的NDK编译系统的应用程序(这个名字不会生成共享库或者最终的包)
下面是Application.mk中定义的几个变量。
APP_PROJECT_PATH
这个变量是强制性的,并且会给出应用程序工程的根目录的一个绝对路径。这是用来复制或者安装一个没有任何版本限制的JNI库,从而给APK生成工具一个详细的路径。APP_MODULES
这个变量是可选的,如果没有定义,NDK将由在Android.mk中声明的默认的模块编译,并且包含所有的子文件(makefile文件)
如果APP_MODULES定义了,它不许是一个空格分隔的模块列表,这个模块名字被定义在Android.mk文件中的LOCAL_MODULE中。注意NDK会自动计算模块的依赖注意:NDK在R4开始改变了这个变量的行为,再次之前:
- 在您的Application.mk中,该变量是强制的
- 必须明确列出所有需要的模块APP_OPTIM
这个变量是可选的,用来定义“release”或"debug"。在编译您的应用程序模块的时候,可以用来改变优先级。“release”模式是默认的,并且会生成高度优化的二进制代码。"debug"模式生成的是未优化的二进制代码,但可以检测出很多的BUG,可以用于调试。
注意:如果你的应用程序是可调试的(即,如果你的清单文件中设置了android:debuggable的属性是"true")。默认的是"debug"而不是"release"。这可以通过设置APP_OPTIM为"release"来将其覆盖。
注意:可以在"release"和"debug"模式下一起调试,但是"release"模式编译后将会提供更少的BUG信息。在我们清楚BUG的过程
中,有一些变量被优化了,或者根本就无法被检测出来,代码的重新排序会让这些带阿弥变得更加难以阅读,并且让这些轨迹更加不可靠。APP_CFLAGS
当编译模块中有任何C文件或者C++文件的时候,C编译器的信号就会被发出。这里可以在你的应用中需要这些模块时,进行编译的调整,这样就不许要直接更改Android.mk为文件本身了重要警告:+++++++++++++++++++++++++++++++++++++++++++++++ + +
+
+ 在这些编制中,所有的路径都需要于最顶层的NDK目录相对应。
+ 例如,如果您有以下设置:
+
+sources/foo/Android.mk
+sources/bar/ Android.mk
+ 编译过程中,若要在foo/Android.mk中指定你要添加的路径到bar源代码中,
+ 你应该使用
+ APP_CFLAGS += -Isources/bar
+ 或者交替:
+ APP_CFLAGS += -I $(LOCAL_PATH )/../bar
+
+ 使用‘-l../bar/‘将不会工作,以为它将等同于"-l$NDK_ROOT/../bar"
++++++++++++++++++++++++++++++++++++++++++++++++++ +++++++++++++++++++++
注意:在Android的NDK 1.5_r1,只适用于C源文件,而不适合C++。
这已得到纠正,以建立完整相匹配的Andr??oid系统。APP_CXXFLAGS
APP_CPPFLAGS的别名,已经考虑在将在未来的版本中废除了APP_CPPFLAGS
当编译的只有C++源文件的时候,可以通过这个C++编译器来设置注意:在Android NDK-1.5_r1中,这个标志可以应用于C和C++源文件中。并且得到了纠正,以建立完整的与系统相匹配的Android编译系统。你先可也可以使用APP_CFLAGS来应用于C或者C++源文件中。
建议使用APP_CFLAGSAPP_BUILD_SCRIPT
默认情况下,NDK编译系统会在$(APP_PROJECT_PATH)/jni目录下寻找名为Android.mk文件:
$(APP_PROJECT_PATH)/jni/Android.mk如果你想覆盖此行为,你可以定义APP_BUILD_SCRIPT来指定一个备用的编译脚本。一个非绝对路径总是被解释为相对于NDK的顶层的目录。
APP_ABI
默认情况下,NDK的编译系统回味"armeabi"ABI生成机器代码。喜爱哪个相当于一个基于CPU可以进行浮点运算的ARMv5TE。你可以使用APP_ABI来选择一个不同的ABI。比如:为了在ARMv7的设备上支持硬件FPU指令。可以使用
APP_ABI := armeabi-v7a或者为了支持IA-32指令集,可以使用
APP_ABI := x86或者为了同时支持这三种,可以使用
APP_ABI := armeabi armeabi-v7a x86APP_STL
默认情况下,NDK的编译系统为最小的C++运行时库(/system/lib/libstdc++.so)提供C++头文件。
然而,NDK的C++的实现,可以让你使用或着链接在自己的应用程序中。
例如:
APP_STL := stlport_static --> static STLport library
APP_STL := stlport_shared --> shared STLport library
APP_STL := system --> default C++ runtime library下面是一个Application.mk文件的示例:
APP_PROJECT_PATH := <path to project> -
=================================
-
NDK提供的共享库(Prebuilt)
- Android NDK r5 开始支持预编译库(动态库和静态库),即程序能使用库的预编译版本。
该特性可用于以下两方面:
1)向第三方NDK开发人员发布你的共享库而不用提供源码。
2)使用一个提前编译好的库(预编译库)来加速编译过程。本文说明该特性如何工作。
I. 声明一个预编译库的模块
对于Android编译工具而言,每个预编译库必须声明为一个独立的模块。这里举一个例子,假设 libfoo.so 文件与 Android.mk 位于同一个目录:
[plain] view plaincopy
- LOCAL_PATH := $(call my-dir)
- include $(CLEAR_VARS)
- LOCAL_MODULE := foo-prebuilt
- LOCAL_SRC_FILES := libfoo.so
- include $(PREBUILT_SHARED_LIBRARY)
按以下步骤声明这样一个模块:
1. 给该模块取一个名字(这里是 foo-prebuilt)。这个名字不需要与预编译库自身的名字相同。
2. 将 LOCAL_SRC_FILES 指定为你要提供的共享库的路径。通常,该路径是相对于 LOCAL_PATH 的路径。注意:必须保证共享库ABI的兼容性。
3. 如果你的库是共享库,则包含 PREBUILT_SHARED_LIBRARY 而不是 BUILD_SHARED_LIBRARY;如果是静态库,则包含 PREBUILT_STATIC_LIBRARY。预编译模块不需要编译。该预编译模块会被拷贝到 $PROJECT/obj/local 下面,还会被拷贝到 $PROJECT/libs/<abi> 下面(这里的库被strip过)。
II. 在其他模块中引用这个预编译库
在依赖该预编译库的模块对应的Android.mk中,将预编译库的名字(前面取的)加入到 LOCAL_STATIC_LIBRARIES 或 LOCAL_SHARED_LIBRARIES 声明中。例如,一个使用上面libfoo.so的简单例子如下:
[plain] view plaincopy
- include $(CLEAR_VARS)
- LOCAL_MODULE := foo-user
- LOCAL_SRC_FILES := foo-user.c
- LOCAL_SHARED_LIBRARIES := foo-prebuilt
- include $(BUILD_SHARED_LIBRARY)
III. 将预编译库的头文件导出
得到预编译库之后,一般需要它对应的头文件。例如前面的libfoo.so,它有对应的foo.h。编译依赖libfoo.so的模块时,需要将该
头文件和它的路径提供给NDK编译系统。一种简单方法是,前面在定义该预编译库的时候,使用LOCAL_EXPORT_C_INCLUDES
变量。例如,假设文件 foo.h 位于当前预编译模块所在目录的 include 子目录,则可以在预编译模块的Android.mk文件中编写如下:[plain] view plaincopy
- include $(CLEAR_VARS)
- LOCAL_MODULE := foo-prebuilt
- LOCAL_SRC_FILES := libfoo.so
- LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
- include $(PREBUILT_SHARED_LIBRARY)
这个 LOCAL_EXPORT_C_INCLUDES 定义确保了任何依赖这个预编译库的模块会自动在自己的 LOCAL_C_INCLUDES 变量中增加到这个预编译库的include目录的路径,从而能够找到其中的头文件。
IV. 调试预编译库
建议你在预编译库中保留调试信息。位于 $PROJECT/libs/<abi> 的版本都是不含调试信息的(被NDK编译系统执行strip过的),调试版的库才能用于 ndk-gdb。
V. 共享库ABI的选择
如前所述,共享库与目标系统的ABI兼容性至关重要。应检查一下 TARGET_ARCH_ABI 的值,可以是以下值:
armeabi 目标系统CPU是ARMv5TE或更高
armeabi-v7a 目标系统CPU是ARMv7或更高
x86 目标系统CPU是x86
注意,armeabi-v7a的CPU可以很好地执行armeabi的程序。
举一个例子,我们提供一个预编译库的两个版本,然后选择不同的ABI:[plain] view plaincopy
- include $(CLEAR_VARS)
- LOCAL_MODULE := foo-prebuilt
- LOCAL_SRC_FILES := $(TARGET_ARCH_ABI)/libfoo.so
- LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
- include $(PREBUILT_SHARED_LIBRARY)
这里假设要拷贝的预编译库所在的目录结构如下:
Android.mk --> 编译这个预编译库的Android.mk
armeabi/libfoo.so --> armeabi版本的共享库
armeabi-v7a/libfoo.so --> armeabi-v7a版本的共享库
include/foo.h --> 预编译库导出的头文件
注意:你不必提供armeabi-v7a版本,因为armeabi版本的共享库能够被armeabi-v7a的兼容,但是反过来就不行。