这一节,我们介绍怎么使用NDK编译C语言源文件。
首先我们从以下页面下载一下最新的ndk
https://developer.android.google.cn/ndk/downloads/
截止到目前为止,NDK的最新版本是r20b,下载下来后,解压到任意文件夹。
比如,我解压后的路径是D:\android-ndk-r20b。
然后需要将D:\android-ndk-r20b\build目录加入PATH环境变量。
加入环境变量后,打开控制台,输入:ndk-build -v
如果能看到以下输出,说明环境变量配置成功:
C:\Users\zy>ndk-build -v
GNU Make 3.81
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
This program built for i686-w64-mingw32
ndk的下载,也可以参考以下链接,直接在android studio中下载。
https://developer.android.google.cn/studio/projects/install-ndk#specific-version
下面我们来新建一个hello-ndk的项目,目录结构如下:
hello-ndk是我们的项目根目录,hello-ndk目录下有一个jni文件夹,jni文件夹下面有Android.mk和main.c两个文件。
Android.mk的文件内容如下:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := hello-ndk
LOCAL_SRC_FILES := main.c
include $(BUILD_SHARED_LIBRARY)
main.c可以是一个空文件。
下面我们打开控件台,输入以下内容,cd到hello-ndk目录,输入ndk-build命令,开始编译,详细过程如下图所示:
编译成功后,我们打开hello-ndk\libs目录查看,发现有四个文件夹,每个文件夹下面都有一个名为libhello-ndk.so的文件。
libhello-ndk.so就是我们所需要的共享库。
下面我们讲解一下ndk-build编译的过程。
当我们在命令行输入ndk-build后,他会在当前目录下寻找jni文件夹,找到jni文件夹后,他会在jni文件夹下寻找文件Android.mk,找到Android.mk后,根据Android.mk所指定的编译脚本来进行编译。
所以,要想编译成功,我们的工程目录下必需要有一个名字jni的文件夹,jni文件下面必需要有一个名为Android.mk的文件。
下面我们来讲解一下Android.mk中每行代码的意思。
LOCAL_MODULE := hello-ndk
LOCAL_MODULE用于指定当前模块的名字,这个名字有两个作用:
1.影响生成的SO的名字。
2.如果Android.mk文件中有多个模块,我们可以通让名字,让模块之间相互引用。
LOCAL_SRC_FILES := main.c
LOCAL_SRC_FILES用于指定我们要编译的源文件列表,如果有多个源文件,每个源文件件之间以空格或者Tab分开,比如:
LOCAL_SRC_FILES := main.c test1.c test2.c
源文件必须在同一行指定,不能换行。
如果源文件太多一行放不下,或者为了清晰,可以像下面这么做:
LOCAL_SRC_FILES := main.c \
test1.c \
test2.c
反斜杠后紧跟回车的意思是,我这一行还没完,把下一行的内容连到当前行。
LOCAL_PATH := $(call my-dir)
LOCAL_PATH用于指定LOCAL_SRC_FILES变量中所指定的这些源文件的相对路径,一般情况下,LOCAL_SRC_FILES中所指定的都是相对路径,相对于谁呢?相对于LOCAL_PATH。
$(call my-dir)是获得Android.mk文件所在的目录,也就是jni目录。
所以我们刚刚指定的LOCAL_SRC_FILES的文件都是相对于jni目录的。
如果我们把LOCAL_PATH的值修改为D:,再调用ndk-build编译会发生什么情况呢?
LOCAL_PATH := D:
D:\ndk-demo\hello-ndk>ndk-build
Android NDK: APP_PLATFORM not set. Defaulting to minimum supported version
android-16.
make: *** No rule to make target `D:/main.c', needed by `obj/local/arm64-v8a/
objs/hello-ndk/main.o'. Stop.
编译时发生了错误,因为找不到源文件D:/main.c。
要解决这个错误除了个以修正LOCAL_PATH的值外,还可以直接指定绝对路径:
LOCAL_SRC_FILES := D:\ndk-demo\hello-ndk\jni\main.c
当然一般很少有人会指定绝对路径,这里只是做个实验。
include $(BUILD_SHARED_LIBRARY)
这一名话标明我们这个模块是一个动态库,如果是动态库,最终会在工程目录下生成一系列的后缀名为.so的文件。
除了生成动态库外,我们也可以用include $(BUILD_STATIC_LIBRARY)成静态库。
修改一下Android.mk的内容:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := hello-ndk
LOCAL_SRC_FILES := main.c
include $(BUILD_STATIC_LIBRARY)
控制台输入ndk-build重新编译一下:
D:\ndk-demo\hello-ndk>ndk-build
Android NDK: APP_PLATFORM not set. Defaulting to minimum supported version android-16.
[arm64-v8a] Compile : hello-ndk <= main.c
[arm64-v8a] StaticLibrary : libhello-ndk.a
[armeabi-v7a] Compile thumb : hello-ndk <= main.c
[armeabi-v7a] StaticLibrary : libhello-ndk.a
[x86] Compile : hello-ndk <= main.c
[x86] StaticLibrary : libhello-ndk.a
[x86_64] Compile : hello-ndk <= main.c
[x86_64] StaticLibrary : libhello-ndk.a
文件管理器查看obj\local目录:
这四个目录,每个目录下面都有一个libhello-ndk.a的文件。
除了动态库和静态库,我们还可以生成可执行文件。
修改Android.mk如下:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := hello-ndk
LOCAL_SRC_FILES := main.c
include $(BUILD_EXECUTABLE)
控制台输入ndk-build
D:\ndk-demo\hello-ndk>ndk-build
Android NDK: APP_PLATFORM not set. Defaulting to minimum supported version android-16.
[arm64-v8a] Compile : hello-ndk <= main.c
[arm64-v8a] Executable : hello-ndk
D:/android-ndk-r20b/build//../toolchains/llvm/prebuilt/windows-x86_64/bin/../sysroot/usr/lib/aarch64-linux-android/21\crtbegin_dynamic.o: In function `_start_main':
crtbegin.c:(.text+0x38): undefined reference to `main'
crtbegin.c:(.text+0x3c): undefined reference to `main'
clang++: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [obj/local/arm64-v8a/hello-ndk] Error 1
报错了,说找不到main函数。我们在main.c中添加以下内容:
int main(){
return 0;
}
控制台输入ndk-build编译:
D:\ndk-demo\hello-ndk>ndk-build
Android NDK: APP_PLATFORM not set. Defaulting to minimum supported version android-16.
[arm64-v8a] Compile : hello-ndk <= main.c
[arm64-v8a] Executable : hello-ndk
[arm64-v8a] Install : hello-ndk => libs/arm64-v8a/hello-ndk
[armeabi-v7a] Compile thumb : hello-ndk <= main.c
[armeabi-v7a] Executable : hello-ndk
[armeabi-v7a] Install : hello-ndk => libs/armeabi-v7a/hello-ndk
[x86] Compile : hello-ndk <= main.c
[x86] Executable : hello-ndk
[x86] Install : hello-ndk => libs/x86/hello-ndk
[x86_64] Compile : hello-ndk <= main.c
[x86_64] Executable : hello-ndk
[x86_64] Install : hello-ndk => libs/x86_64/hello-ndk
查看libs目录:
这个四个目录,第个目录下都有一个可执行文件hello-ndk
include $(CLEAR_VARS)
这一句的作用是清除除了LOCAL_PATH以外,其他所有以LOCAL_开头的变量的值,比如LOCAL_SRC_FILES,LOCAL_MODULE的值。
更重要的作用是,这一句标志着一个新的模块的开始,每个模块必须以这句话开头,因为新开始了一个模块,新的模块会重新定义LOCAL_XXX的变量,为了避免不必要的bug,上一个模块的LOCAL_XXX的变量的值都应该清除,如果模块不以这句话开头,在编译的时候会报错。
下在我们来看一个多模块的例子:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := hello-ndk
LOCAL_SRC_FILES := main.c
include $(BUILD_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := hello-jni
LOCAL_SRC_FILES := main.c
include $(BUILD_SHARED_LIBRARY)
上面的Android.mk定义了两个模块,hello-ndk和hello-jni,虽然两个模块LOCAL_SRC_FILES都是main.c,但这确实是两个模块。
在控制台输入ndk-build编译:
D:\ndk-demo\hello-ndk>ndk-build
Android NDK: APP_PLATFORM not set. Defaulting to minimum supported version android-16.
[arm64-v8a] Compile : hello-jni <= main.c
[arm64-v8a] SharedLibrary : libhello-jni.so
[arm64-v8a] Install : libhello-jni.so => libs/arm64-v8a/libhello-jni.so
[arm64-v8a] Compile : hello-ndk <= main.c
[arm64-v8a] SharedLibrary : libhello-ndk.so
[arm64-v8a] Install : libhello-ndk.so => libs/arm64-v8a/libhello-ndk.so
[armeabi-v7a] Compile thumb : hello-jni <= main.c
[armeabi-v7a] SharedLibrary : libhello-jni.so
[armeabi-v7a] Install : libhello-jni.so => libs/armeabi-v7a/libhello-jni.so
[armeabi-v7a] Compile thumb : hello-ndk <= main.c
[armeabi-v7a] SharedLibrary : libhello-ndk.so
[armeabi-v7a] Install : libhello-ndk.so => libs/armeabi-v7a/libhello-ndk.so
[x86] Compile : hello-jni <= main.c
[x86] SharedLibrary : libhello-jni.so
[x86] Install : libhello-jni.so => libs/x86/libhello-jni.so
[x86] Compile : hello-ndk <= main.c
[x86] SharedLibrary : libhello-ndk.so
[x86] Install : libhello-ndk.so => libs/x86/libhello-ndk.so
[x86_64] Compile : hello-jni <= main.c
[x86_64] SharedLibrary : libhello-jni.so
[x86_64] Install : libhello-jni.so => libs/x86_64/libhello-jni.so
[x86_64] Compile : hello-ndk <= main.c
[x86_64] SharedLibrary : libhello-ndk.so
[x86_64] Install : libhello-ndk.so => libs/x86_64/libhello-ndk.so
输出多了很多,主要多了libhello-jni.so的生成,打开文件管理器,查看libs\ameabi-v7a目录
该目录下不仅有libhello-ndk.so还有libhello-jni.so
下面我们总结一下Android.mk的结构:
1.一般情况下,每个Android.mk都以LOCAL_PATH := $(call my-dir)开头
2.一般情况下,每个模块都以include $(CLEAR_VARS)开头,以include
(
B
U
I
L
D
S
H
A
R
E
D
L
I
B
R
A
R
Y
)
或
者
(BUILD_SHARED_LIBRARY)或者
(BUILDSHAREDLIBRARY)或者(BUILD_STATIC_LIBRARY)或者include $(BUILD_EXECUTABLE)结尾。
3.中间定义的LOCAL_XXX变量,这些变量的顺序无所谓,哪个在前,哪个在后都可以
下面我们再还看一个ndk-build的其他用法。
ndk-build -C <project>
除了cd到项目目录(jni文件夹的父目录),调用ndk-build外,我们还要以像下面这么做。
在任意目录,调用ndk-build -C D:\ndk-demo\hello-ndk,效果也是一样的。
也就是说我们也要通过-C参数指定项目目录,如果没有指定,则ndk-build默认以当前目录做为项目目录。
ndk-build clean
这个写代码的应该都知道,其作用相当于删除obj文件夹和libs文件夹。
默认情况下,ndk-build都是增量编译,如果你的源文件编译过,在没有修改过源文件的情况下,下一次执行ndk-build的时候,为了节省编译时候,你的源文件不会重新编译。
调用了ndk-build clean以后再调用ndk-build所有的文件都会被重新编译。
ndk-build -B
强制执行完整的重新编译,其实就是先ndk-build clean再ndk-build
ndk-build V=1
在编译时会有更详细的输出,显示编译和链接命令,像下面这样。
D:\ndk-demo\hello-ndk>ndk-build V=1
Android NDK: APP_PLATFORM not set. Defaulting to minimum supported version android-16.
del /f/q .\libs\arm64-v8a\libhello-ndk.so .\libs\armeabi-v7a\libhello-ndk.so .\libs\x86\libhello-ndk.so .\libs\x86_64\libhello-ndk.so >NUL 2>NUL
[arm64-v8a] Compile : hello-jni <= main.c
del /f/q .\obj\local\arm64-v8a\objs\hello-jni\main.o >NUL 2>NUL
D:/android-ndk-r20b/build//../toolchains/llvm/prebuilt/windows-x86_64/bin/clang.exe -MMD -MP -MF ./obj/local/arm64-v8a/objs/hello-jni/main.o.d -target aarch64-none-linux-android21 -fdata-sections -ffunction-sections -fstack-protector-strong -funwind-tables -no-canonical-prefixes --sysroot D:/android-ndk-r20b/build//../toolchains/llvm/prebuilt/windows-x86_64/sysroot -g -Wno-invalid-command-line-argument -Wno-unused-command-line-argument -fno-addrsig -fpic -O2 -DNDEBUG -Ijni -DANDROID -Wa,--noexecstack -Wformat -Werror=format-security -c jni/main.c -o ./obj/local/arm64-v8a/objs/hello-jni/main.o
[arm64-v8a] SharedLibrary : libhello-jni.so
D:/android-ndk-r20b/build//../toolchains/llvm/prebuilt/windows-x86_64/bin/clang++.exe -Wl,-soname,libhello-jni.so -shared ./obj/local/arm64-v8a/objs/hello-jni/main.o -lgcc -Wl,--exclude-libs,libgcc.a -latomic -Wl,--exclude-libs,libatomic.a -target aarch64-none-linux-android21 -no-canonical-prefixes -Wl,--build-id -stdlib=libstdc++ -Wl,--no-undefined -Wl,-z,noexecstack -Wl,--warn-shared-textrel -Wl,--fatal-warnings -lc -lm -o ./obj/local/arm64-v8a/libhello-jni.so
[arm64-v8a] Install : libhello-jni.so => libs/arm64-v8a/libhello-jni.so
copy /b/y ".\obj\local\arm64-v8a\libhello-jni.so" ".\libs\arm64-v8a\libhello-jni.so" > NUL
D:/android-ndk-r20b/build//../toolchains/llvm/prebuilt/windows-x86_64/bin/aarch64-linux-android-strip --strip-unneeded ./libs/arm64-v8a/libhello-jni.so
[arm64-v8a] Compile : hello-ndk <= main.c
del /f/q .\obj\local\arm64-v8a\objs\hello-ndk\main.o >NUL 2>NUL
D:/android-ndk-r20b/build//../toolchains/llvm/prebuilt/windows-x86_64/bin/clang.exe -MMD -MP -MF ./obj/local/arm64-v8a/objs/hello-ndk/main.o.d -target aarch64-none-linux-android21 -fdata-sections -ffunction-sections -fstack-protector-strong -funwind-tables -no-canonical-prefixes --sysroot D:/android-ndk-r20b/build//../toolchains/llvm/prebuilt/windows-x86_64/sysroot -g -Wno-invalid-command-line-argument -Wno-unused-command-line-argument -fno-addrsig -fpic -O2 -DNDEBUG -Ijni -DANDROID -Wa,--noexecstack -Wformat -Werror=format-security -c jni/main.c -o ./obj/local/arm64-v8a/objs/hello-ndk/main.o
[arm64-v8a] SharedLibrary : libhello-ndk.so
D:/android-ndk-r20b/build//../toolchains/llvm/prebuilt/windows-x86_64/bin/clang++.exe -Wl,-soname,libhello-ndk.so -shared ./obj/local/arm64-v8a/objs/hello-ndk/main.o -lgcc -Wl,--exclude-libs,libgcc.a -latomic -Wl,--exclude-libs,libatomic.a -target aarch64-none-linux-android21 -no-canonical-prefixes -Wl,--build-id -stdlib=libstdc++ -Wl,--no-undefined -Wl,-z,noexecstack -Wl,--warn-shared-textrel -Wl,--fatal-warnings -lc -lm -o ./obj/local/arm64-v8a/libhello-ndk.so
[arm64-v8a] Install : libhello-ndk.so => libs/arm64-v8a/libhello-ndk.so
copy /b/y ".\obj\local\arm64-v8a\libhello-ndk.so" ".\libs\arm64-v8a\libhello-ndk.so" > NUL
D:/android-ndk-r20b/build//../toolchains/llvm/prebuilt/windows-x86_64/bin/aarch64-linux-android-strip --strip-unneeded ./libs/arm64-v8a/libhello-ndk.so
[armeabi-v7a] Compile thumb : hello-jni <= main.c
del /f/q .\obj\local\armeabi-v7a\objs\hello-jni\main.o >NUL 2>NUL
D:/android-ndk-r20b/build//../toolchains/llvm/prebuilt/windows-x86_64/bin/clang.exe -MMD -MP -MF ./obj/local/armeabi-v7a/objs/hello-jni/main.o.d -target armv7-none-linux-androideabi16 -fdata-sections -ffunction-sections -fstack-protector-strong -funwind-tables -no-canonical-prefixes --sysroot D:/android-ndk-r20b/build//../toolchains/llvm/prebuilt/windows-x86_64/sysroot -g -Wno-invalid-command-line-argument -Wno-unused-command-line-argument -fno-addrsig -fpic -march=armv7-a -mthumb -Oz -DNDEBUG -Ijni -DANDROID -Wa,--noexecstack -Wformat -Werror=format-security -c jni/main.c -o ./obj/local/armeabi-v7a/objs/hello-jni/main.o
[armeabi-v7a] SharedLibrary : libhello-jni.so
D:/android-ndk-r20b/build//../toolchains/llvm/prebuilt/windows-x86_64/bin/clang++.exe -Wl,-soname,libhello-jni.so -shared ./obj/local/armeabi-v7a/objs/hello-jni/main.o -lgcc -Wl,--exclude-libs,libgcc.a -latomic -Wl,--exclude-libs,libatomic.a -target armv7-none-linux-androideabi16 -no-canonical-prefixes -Wl,--build-id -stdlib=libstdc++ -Wl,--no-undefined -Wl,-z,noexecstack -Wl,--warn-shared-textrel -Wl,--fatal-warnings -lc -lm -o ./obj/local/armeabi-v7a/libhello-jni.so
[armeabi-v7a] Install : libhello-jni.so => libs/armeabi-v7a/libhello-jni.so
copy /b/y ".\obj\local\armeabi-v7a\libhello-jni.so" ".\libs\armeabi-v7a\libhello-jni.so" > NUL
D:/android-ndk-r20b/build//../toolchains/llvm/prebuilt/windows-x86_64/bin/arm-linux-androideabi-strip --strip-unneeded ./libs/armeabi-v7a/libhello-jni.so
[armeabi-v7a] Compile thumb : hello-ndk <= main.c
del /f/q .\obj\local\armeabi-v7a\objs\hello-ndk\main.o >NUL 2>NUL
D:/android-ndk-r20b/build//../toolchains/llvm/prebuilt/windows-x86_64/bin/clang.exe -MMD -MP -MF ./obj/local/armeabi-v7a/objs/hello-ndk/main.o.d -target armv7-none-linux-androideabi16 -fdata-sections -ffunction-sections -fstack-protector-strong -funwind-tables -no-canonical-prefixes --sysroot D:/android-ndk-r20b/build//../toolchains/llvm/prebuilt/windows-x86_64/sysroot -g -Wno-invalid-command-line-argument -Wno-unused-command-line-argument -fno-addrsig -fpic -march=armv7-a -mthumb -Oz -DNDEBUG -Ijni -DANDROID -Wa,--noexecstack -Wformat -Werror=format-security -c jni/main.c -o ./obj/local/armeabi-v7a/objs/hello-ndk/main.o
[armeabi-v7a] SharedLibrary : libhello-ndk.so
D:/android-ndk-r20b/build//../toolchains/llvm/prebuilt/windows-x86_64/bin/clang++.exe -Wl,-soname,libhello-ndk.so -shared ./obj/local/armeabi-v7a/objs/hello-ndk/main.o -lgcc -Wl,--exclude-libs,libgcc.a -latomic -Wl,--exclude-libs,libatomic.a -target armv7-none-linux-androideabi16 -no-canonical-prefixes -Wl,--build-id -stdlib=libstdc++ -Wl,--no-undefined -Wl,-z,noexecstack -Wl,--warn-shared-textrel -Wl,--fatal-warnings -lc -lm -o ./obj/local/armeabi-v7a/libhello-ndk.so
[armeabi-v7a] Install : libhello-ndk.so => libs/armeabi-v7a/libhello-ndk.so
copy /b/y ".\obj\local\armeabi-v7a\libhello-ndk.so" ".\libs\armeabi-v7a\libhello-ndk.so" > NUL
D:/android-ndk-r20b/build//../toolchains/llvm/prebuilt/windows-x86_64/bin/arm-linux-androideabi-strip --strip-unneeded ./libs/armeabi-v7a/libhello-ndk.so
[x86] Compile : hello-jni <= main.c
del /f/q .\obj\local\x86\objs\hello-jni\main.o >NUL 2>NUL
D:/android-ndk-r20b/build//../toolchains/llvm/prebuilt/windows-x86_64/bin/clang.exe -MMD -MP -MF ./obj/local/x86/objs/hello-jni/main.o.d -target i686-none-linux-android16 -fdata-sections -ffunction-sections -fstack-protector-strong -funwind-tables -no-canonical-prefixes --sysroot D:/android-ndk-r20b/build//../toolchains/llvm/prebuilt/windows-x86_64/sysroot -g -Wno-invalid-command-line-argument -Wno-unused-command-line-argument -fno-addrsig -fPIC -O2 -DNDEBUG -Ijni -DANDROID -Wa,--noexecstack -Wformat -Werror=format-security -mstackrealign -c jni/main.c -o ./obj/local/x86/objs/hello-jni/main.o
[x86] SharedLibrary : libhello-jni.so
D:/android-ndk-r20b/build//../toolchains/llvm/prebuilt/windows-x86_64/bin/clang++.exe -Wl,-soname,libhello-jni.so -shared ./obj/local/x86/objs/hello-jni/main.o -lgcc -Wl,--exclude-libs,libgcc.a -latomic -Wl,--exclude-libs,libatomic.a -target i686-none-linux-android16 -no-canonical-prefixes -Wl,--build-id -stdlib=libstdc++ -Wl,--no-undefined -Wl,-z,noexecstack -Wl,--warn-shared-textrel -Wl,--fatal-warnings -lc -lm -o ./obj/local/x86/libhello-jni.so
[x86] Install : libhello-jni.so => libs/x86/libhello-jni.so
copy /b/y ".\obj\local\x86\libhello-jni.so" ".\libs\x86\libhello-jni.so" > NUL
D:/android-ndk-r20b/build//../toolchains/llvm/prebuilt/windows-x86_64/bin/i686-linux-android-strip --strip-unneeded ./libs/x86/libhello-jni.so [x86] Compile : hello-ndk <= main.c
del /f/q .\obj\local\x86\objs\hello-ndk\main.o >NUL 2>NUL
D:/android-ndk-r20b/build//../toolchains/llvm/prebuilt/windows-x86_64/bin/clang.exe -MMD -MP -MF ./obj/local/x86/objs/hello-ndk/main.o.d -target i686-none-linux-android16 -fdata-sections -ffunction-sections -fstack-protector-strong -funwind-tables -no-canonical-prefixes --sysroot D:/android-ndk-r20b/build//../toolchains/llvm/prebuilt/windows-x86_64/sysroot -g -Wno-invalid-command-line-argument -Wno-unused-command-line-argument -fno-addrsig -fPIC -O2 -DNDEBUG -Ijni -DANDROID -Wa,--noexecstack -Wformat -Werror=format-security -mstackrealign -c jni/main.c -o ./obj/local/x86/objs/hello-ndk/main.o
[x86] SharedLibrary : libhello-ndk.so
D:/android-ndk-r20b/build//../toolchains/llvm/prebuilt/windows-x86_64/bin/clang++.exe -Wl,-soname,libhello-ndk.so -shared ./obj/local/x86/objs/hello-ndk/main.o -lgcc -Wl,--exclude-libs,libgcc.a -latomic -Wl,--exclude-libs,libatomic.a -target i686-none-linux-android16 -no-canonical-prefixes -Wl,--build-id -stdlib=libstdc++ -Wl,--no-undefined -Wl,-z,noexecstack -Wl,--warn-shared-textrel -Wl,--fatal-warnings -lc -lm -o ./obj/local/x86/libhello-ndk.so
[x86] Install : libhello-ndk.so => libs/x86/libhello-ndk.so
copy /b/y ".\obj\local\x86\libhello-ndk.so" ".\libs\x86\libhello-ndk.so" > NUL
D:/android-ndk-r20b/build//../toolchains/llvm/prebuilt/windows-x86_64/bin/i686-linux-android-strip --strip-unneeded ./libs/x86/libhello-ndk.so
[x86_64] Compile : hello-jni <= main.c
del /f/q .\obj\local\x86_64\objs\hello-jni\main.o >NUL 2>NUL
D:/android-ndk-r20b/build//../toolchains/llvm/prebuilt/windows-x86_64/bin/clang.exe -MMD -MP -MF ./obj/local/x86_64/objs/hello-jni/main.o.d -target x86_64-none-linux-android21 -fdata-sections -ffunction-sections -fstack-protector-strong -funwind-tables -no-canonical-prefixes --sysroot D:/android-ndk-r20b/build//../toolchains/llvm/prebuilt/windows-x86_64/sysroot -g -Wno-invalid-command-line-argument -Wno-unused-command-line-argument -fno-addrsig -fPIC -O2 -DNDEBUG -Ijni -DANDROID -Wa,--noexecstack -Wformat -Werror=format-security -c jni/main.c -o ./obj/local/x86_64/objs/hello-jni/main.o[x86_64] SharedLibrary : libhello-jni.so D:/android-ndk-r20b/build//../toolchains/llvm/prebuilt/windows-x86_64/bin/clang++.exe -Wl,-soname,libhello-jni.so -shared ./obj/local/x86_64/objs/hello-jni/main.o -lgcc -Wl,--exclude-libs,libgcc.a -latomic -Wl,--exclude-libs,libatomic.a -target x86_64-none-linux-android21 -no-canonical-prefixes -Wl,--build-id -stdlib=libstdc++ -Wl,--no-undefined -Wl,-z,noexecstack -Wl,--warn-shared-textrel -Wl,--fatal-warnings -lc -lm -o ./obj/local/x86_64/libhello-jni.so
[x86_64] Install : libhello-jni.so => libs/x86_64/libhello-jni.so
copy /b/y ".\obj\local\x86_64\libhello-jni.so" ".\libs\x86_64\libhello-jni.so" > NUL
D:/android-ndk-r20b/build//../toolchains/llvm/prebuilt/windows-x86_64/bin/x86_64-linux-android-strip --strip-unneeded ./libs/x86_64/libhello-jni.so
[x86_64] Compile : hello-ndk <= main.c
del /f/q .\obj\local\x86_64\objs\hello-ndk\main.o >NUL 2>NUL
D:/android-ndk-r20b/build//../toolchains/llvm/prebuilt/windows-x86_64/bin/clang.exe -MMD -MP -MF ./obj/local/x86_64/objs/hello-ndk/main.o.d -target x86_64-none-linux-android21 -fdata-sections -ffunction-sections -fstack-protector-strong -funwind-tables -no-canonical-prefixes --sysroot D:/android-ndk-r20b/build//../toolchains/llvm/prebuilt/windows-x86_64/sysroot -g -Wno-invalid-command-line-argument -Wno-unused-command-line-argument -fno-addrsig -fPIC -O2 -DNDEBUG -Ijni -DANDROID -Wa,--noexecstack -Wformat -Werror=format-security -c jni/main.c -o ./obj/local/x86_64/objs/hello-ndk/main.o[x86_64] SharedLibrary : libhello-ndk.so
D:/android-ndk-r20b/build//../toolchains/llvm/prebuilt/windows-x86_64/bin/clang++.exe -Wl,-soname,libhello-ndk.so -shared ./obj/local/x86_64/objs/hello-ndk/main.o -lgcc -Wl,--exclude-libs,libgcc.a -latomic -Wl,--exclude-libs,libatomic.a -target x86_64-none-linux-android21 -no-canonical-prefixes -Wl,--build-id -stdlib=libstdc++ -Wl,--no-undefined -Wl,-z,noexecstack -Wl,--warn-shared-textrel -Wl,--fatal-warnings -lc -lm -o ./obj/local/x86_64/libhello-ndk.so
[x86_64] Install : libhello-ndk.so => libs/x86_64/libhello-ndk.so
copy /b/y ".\obj\local\x86_64\libhello-ndk.so" ".\libs\x86_64\libhello-ndk.so" > NUL
D:/android-ndk-r20b/build//../toolchains/llvm/prebuilt/windows-x86_64/bin/x86_64-linux-android-strip --strip-unneeded ./libs/x86_64/libhello-ndk.so
最后再说一个文档上没有但很有用的,默认情况下,ndk-build都是单线程编译。如果你的源文件较多,那编译可能会有点儿慢,可以通过传递-j参数开启多线程编译,比如像下面这样:
ndk-build -j32
开启32个线程进行编译,编译速度杠杠的。
最后,执行ndk-build,其实相当于执行:
$GNUMAKE -f /build/core/build-local.mk
build-local.mk会将我们的Android.mk包含进去,所以除了-j32外,gnu make有什么参数,都可以加在ndk-build里面