First, build the system

(a) Android. Mk

LOCAL_PATH: Android.mk documents must begin with the definition of the LOCAL_PATH variable

CLEAR_VARS: Set to the location of the clear-vars.mk fragment. Include Makefile snippets to make clear LOCAL_ < NAME> variables other than LOCAL_PATH, such as LOCAL_MODULE and LOCAL_SRC_FILES; Because multiple build files and module definitions are parsed in a single build, LOCAL_< NAME> are global variables and clearing them can avoid conflicts.

Eg: Include $(CLEAR_VARS)

LOCAL_MOUDLE: used to give these modules a unique name:

Eg:LOCAL_MOUDLE : = hello-jni

The module namespaces are used to name the files generated by the build process, so the build system adds the appropriate prefixes and suffixes to the files.

Eg: libhello – jni. So

LOCAL_SRC_FILES: A list of source files used to create and assemble this module, which can contain multiple source file names separated by Spaces

Eg: LOCAL_SRC_FILES := hello-jni.c

1. Build shared libraries

BUILD_SHARED_LIBRARY: Set to the location where the build_shared_library.mk file is saved. This Makefile fragment contains the necessary procedures to build and assemble the source files into a shared library: include $(BUILD_SHARED_LIBRARY)

2. Build multiple shared libraries

Depending on the architecture of different applications, a single Android.mk document may produce multiple shared library modules. To achieve this, multiple modules need to be defined:

Eg:

LOCAL_PATH := $(call my-dir)

# module 1

include $(CLEAR_VARS)

LOCAL_MOUDLE := module1

LOCAL_SRC_FILES := module1.c

include $(BUILD_SHARED_LIBRARY)

# module 2

LOCAL_MODULE := module2

LOCAL_SRC_FILES := module2.c

include $(BUILD_SHARED_LIBRARY)

After parsing the Android.mk build document, the Android NDK build system generates two shared libraries libmodule1.so and libmodule2.so

3. Build static libraries

Static libraries are not available for Android applications and are not included in the application package, but can be used to build shared libraries.

Using static libraries in Android.mk:

LOCAL_PATH := $(call my-dir)

# Third-party AVI library

include $(CLEAR_VARS)

LOCAL_MODULE := avilib

LOCAL_SRC_PATH := avilib.c platform_posix.c

include $(BUILD_STATIC_LIBRARY)

# Native modules

include $(CLEAR_VARS)

LOCAL_MODULE := module

LOCAL_SRC_FILES := module.c

LOCAL_STATIC_LIBRARY := avilib

After a third-party code module produces a static library, the shared library can use the module by adding the LOCAL_STATIC_LIBRARY variable to its module name

include $(BUILD_SHARED_LIBRARY)

4. Share common modules with shared libraries

Static library can ensure the modularization of source code, but when static library and shared library are connected, static library becomes a part of the shared library, which is not conducive to the sharing of multiple shared libraries. In the case of multiple shared libraries, when multiple shared libraries are connected with a static library, multiple copies of the common module need to be repeatedly connected to different shared libraries, increasing the size of the application. In this case, instead of building a static library, common modules are set up as shared libraries, and dependent modules are dynamically linked to eliminate duplicate copies.

Eg:

LOCAL_PATH := $(call my-dir)

# Third-party AVI library

include $(CLEAR_VARS)

LOCAL_MODULE := avilib

LOCAL_SRC_FILES := avilib.c platform_posix.c

# Native Module 1

include $(CLEAR_VARS)

LOCAL_MODULE := module1

LOCAL_SRC_FILES := module1.c

LOCAL_SHARED_LIBRARIES := avilib

include $(BUILD_SHARED_LIBRARY)

# Native Module 2

include $(CLEAR_VARS)

LOCAL_MODULE := module2

LOCAL_SRC_FILES := module2.c

LOCAL_SHARED_LIBRARIES := avilib

include $(BUILD_SHARED_LIBRARY)

5. Share modules across multiple NDK projects

When using both static and relational libraries, you can share common modules between modules by following these steps:

(1) Move the source code of Avilib to the location outside the NDK project and set the path as AVI_Path

(2) As a shared module, Avilib needs its own Android.mk file, as shown below:

LOCAL_PATH := $(call my-dir)

# Third-party AVI library

include $(CLEAR_VARS)

LOCAL_MODULE := avilib

LOCAL_SRC_FILE := avilib.c platform_posix.c

include $(BUILD_SHARED_LIBRARY)

(3) It is now possible to remove the Avilib module from the android. mk file of the NDK project. In order to use this shared module, the section of the call function macro import-module with transcode/ Avilib as parameters is added at the end of the build document to avoid building system conflicts

# Native modules

include $(CLEAR_VARS)

LOCAL_MODULE := module

LOCAL_SRC_FILE := module.c

LOCAL_SHARED_LIBRARY := avilib

include $(BUILD_SHARED_LIBRARY)

$(call import-module,transcode/avilib)

(4) Import-Module function macros need to locate shared modules first, and then import into NDK projects. By default, the import-module function macro searches only the < Android NDK >/sources directory.

6. Use the Prebuilt library

Using shared modules requires the source code for shared modules, and the Android NDK build system simply includes these source files in the NDK project and builds them each time. The Prebuilt library is useful when:

(1) Release the module to others without wanting to release the source code

(2) Use pre-built versions of shared modules to speed up the build process

The Android. Mk file for the pre-built shared module is as follows:

LOCAL_PATH := $(call my-dir)

# Third party prebuild AVI library

include $(CLEAR_VARS)

LOCAL_MODULE := avilib

LOCAL_SRC_FILES := libavilib.so

include $(PREBUILT_SHARED_LIBRARY)

Instead of pointing to the source file, the LOCAL_SRC_FILES variable points to the location of the actual Prebuilt library relative to LOCAL_PATH

The PREBUILT_SHARED_LIBRARY variable points to the prebuilt-shared-library.mk Makefile fragment. He copied the Prebuilt library into the LIBS directory of the NDK project. By using the PREBUILT_SHARED_LIBRARY variable, static libraries can be used as Prebuilt libraries just like shared libraries, and NDK projects can use Prebuilt libraries just like regular shared libraries.

Eg: LOCAL_SHARED_LIBRARIES := avilib

7. Build a separate executable

In general quick testing, we tend to build separate executables so that the program can be executed directly rather than being loaded through a Java application.

Instead of importing the BUILD_SHARED_LIBRARY variable, the BUILD_EXECUTABLE variable should be imported into the android. mk file to build a standalone executable, as shown in the example code below:

# Standalone executable native module

include $(CLEAR_VARS)

LOCAL_MODULE := module

LOCAL_SRC_FILES := module.c

LOCAL_STATIC_LIBRARIES := avilib

include $(BUILD_EXECUTABLE)

The BUILD_EXECUTABLE variable points to the build-executable. Mk Makefile fragment that contains the necessary steps to generate a standalone executable on the Android platform. Standalone executables are placed under the liBS /< Machine Architecture > directory under the name of the module system.

8. Other component system variables

(1) Variables defined by the construction system include:

① TARGET_ARCH: the name of the target CPU structure, such as ARM

② TARGET_PLATFORM: specifies the name of the target Android platform, for example, Android-3

③ TARGET_ARCH_ABI: the name of the target CPU architecture and ABI, for example, armeabi-v7a

④ TARGET_ABI: the tandem of the target platform and ABI, for example, Android-3-armeabi-v7A

(2) Variables defined as module description are:

① LOCAL_MODULE_FILENAME: An optional variable used to redefine the name of the generated output file. By default, the build system uses the value of LOCAL_MODULE as the generated output file name, but the LOCAL_MODULE_FILENAME variable can override LOCAL_MODULE

② LOCAL_CPP_EXTENSION: the default C++ source file extension is. CPP

Eg: LOCAL_CPP_EXTENSION := .cpp .cxx

③ LOCAL_CPP_FEATURES: optional variable used to specify the specific C++ features on which the module depends, such as RTTI, exception, etc.

Eg: LOCAL_CPP_FEATURES := rtti

LOCAL_CFLAGS: A set of optional compiler flags that are passed to the compiler when compiling C/C++ source files.

Eg: LOCAL_CFLAGS := -DNDEBUG -DPORT=1234

⑤ LOCAL_CPP_FLAGSL: a set of optional compilation flags that are passed to the compiler when compiling only C++ source files.

⑥ LOCAL_WHOLE_STATIC_LIBRARIES: A variant of LOCAL_STATIC_LIBRARIES that specifies all static library content that should be included in the generated shared library.

⑦ LOCAL_LDLIBS: An optional list of link flags that will be passed to the linker when the target file is connected to generate an output file. It is primarily used to pass a list of system libraries to dynamically link rows.

Eg: To link to the Android NDK log library:

LOCAL_LDFKAGS := --llog

⑧ LOCAL_ALLOW_UNDEFINED_SYMBOLS: This parameter is optional. It cannot be used to check missing symbols in generated files. If not defined, the linker will generate an error message if symbols are missing.

⑨ LOCAL_ARM_MODE: This parameter is optional. It is an ARM machine architecture specific variable that specifies the ARM binary type to be generated. By default, the build system is generated using 16-bit instructions in thumb mode, but this variable can be set to specify 32-bit instructions for ARM.

Eg: LOCAL_ARM_MODE := arm

This variable changes the build system behavior of the entire module, with the **.arm** extension specifying that specific files are built only in ARM mode.

Eg: LOCAL_SRC_FILES := file1.c file2.c.arm

⑩ LOCAL_ARM_NEON: This parameter is optional. It is an ARM machine architecture specific variable. Used to specify the ARM advanced single-instruction stream multi-data stream inline function that should be used in source files

Eg: LOCAL_SRC_FILES := true

Similarly, you can use the **.neon** extension to specify that only specific files with neon inline functions are built

Eg: LOCAL_SRC_FILES := file1.c file2.c.neon

⑪ LOCAL_DISABLE_NO_EXECUTE: Optional variable used to disable the NX Bit security feature. NX Bit stands for Never Execute and is a technique used in cpus to separate areas of code from areas of storage.

Eg: LOCAL_DISABLE_NO_EXECUTE := true

⑫ LOCAL_EXPORT_CFLAGS: This variable records a set of compiler flags that are added to the LOCAL_CFLAGS definition of other modules that use this module through the LOCAL_STATIC_LIBRARIES variable or LOCAL_SHARED_LIBRARIES.

Passing LOCAL_EXPORT_CPPFLAGS: same as LOCAL_EXPORT_CFLAGS, but it is a C++ specific code compiler flag.

14. LOCAL_EXPORT_LDFLAGS: The same as LOCAL_EXPORT_CFLAGS, but used as the linker flag

⑮ LOCAL_EXPORT_C_INCLUDES: This variable runs the set of record paths that are added to the LOCAL_C_INCLUDES definition using the module through the LOCAL_STATIC_LIBRARIES variable or LOCAL_SHARED_LIBRARIES.

⑯ persons LOCAL_SHORT_COMMANDS: This variable should be set to true for large resources or separate static/shared libraries

⑰ Persons LOCAL_FILTER_ASM: This variable defines applications used to filter assembly files from the LOCAL_SRC_FILES variable.

9. Other build system function macros

① All-subdir-makefiles: Returns the list of Android.mk build files in all subdirectories of the current directory. For example, all android. mk files in subdirectories can be included in the build by calling the following command:

Eg: include $(call all-subdir-makefiles)

② this-makefile: returns the path to the current Android.mk build file

③ parent-makefile: Returns the path to the parent Android.mk build file that contains the current build file

④ grand-parent-makefile: the same as parent-makefile but used for the grandfather directory

Define new variables

Variable names prefixed with **LOCAL_ and NDK_ are reserved for the Android NDK build system. It is recommended that developers define variables prefixed with MY_**.

Eg: MY_SRC_FILES := avilib.c platform_posix.c

LOCAL_SRC_FILES := $(addprefix avilib/, $(MY_SRC_FILES))

11. Conditional operation

The Android.mk build file can also contain conditional operations on these variables. For example, to include a different set of source files in each architecture, the code would look like this:

ifeq ($(TARGET_ARCH), arm)

LOCAL_SRC_FILES += armonly.c

else

LOCAL_SRC_FILES += generic.c

endif

(2) Application. Mk

Application.mk is an optional build file for the Android NDK build system and, like Android.mk, it is placed in the JNI directory. Android.mk is also a GNU Makefile fragment. His purpose is to describe which modules are required by the application; It also defines common variables for all modules. Here are the variables supported by the application.mk build file:

1.APP_MODULES

The Android NDK build system builds all modules declared in the Android.mk file. This variable overrides the above behavior and provides a whitespace separated list of modules that need to be built.

2,APP_OPTIM

This variable can be set to release or DEBUG to change the optimization level of the generated binaries. By default, release mode is used and the generated binaries are highly optimized. This variable can be set to debug mode to generate unoptimized binaries that are easier to debug.

3,APP_CLAGS

This variable lists compiler flags that are passed to the compiler when compiling any module’s C/C++ source files.

4,APP_CPPFLAGS

This variable lists compiler flags that are passed to the compiler when compiling any module’s C++ source files.

5,APP_BUILD_SCRIPT

By default, the Android NDK build system looks for the Android.mk build file in the jNI subdirectory of the project. You can use this variable to change the above behavior and use a different build file.

6,APP_ABI

By default, the Android NDK build system generates binaries for the Armeabi ABI. Using this variable, you can generate binaries for other ABIs.

Eg: APP_ABI := mips

Set up multiple ABIs:

Eg: APP_ABI := armeabi mips

Generate binaries for all ABI support:

Eg: APP_ABI := all

7,APP_STL

By default, the Android NDK uses the minimum STL library, also known as the System library. With this variable, you can specify different STL libraries.

Eg: APP_STL := stlport_shared

Eight,APP_GNUSTL_FORCE_CPP_FEATURES

Similar to the LOCAL_CPP_EXTNESIONS variable, this variable indicates that all modules are dependent on specific C++ features. Such as RTTI, Exception, etc.

9,APP_SHORT_COMMANDS:

Similar to the LOCAL_SHORT_COMMANDS variable, which allows the build system to use shorter commands in projects with a large number of source files.

2. Use the NDK-build script

1. Ndk-build should normally be executed in the main project directory. The -c argument can be used to specify the location of the NDK project on the command line, so that the NDK-build script can start at any location.

ndk-build -C /path/to/the/project

2. The Android NDK build system will not rebuild the target if the source file has not been modified. The -b argument forces a rebuild of all code

ndk-build -B

3. Clean the generated binary files and target files

ndk-build clean

4. Speed up construction

ndk-build -j 4

3. Troubleshooting the construction system

1. Enable the internal status log function of Android NDK

ndk-build NDK_LOG = 1

2. Display only build commands

ndk-build V = 1