使用NDK 10版本,我曾经使用ndk-build
为许多不同的ABI和多个API级别编译独立的二进制文件。这些二进制文件将包含在一个应用程序中。但是,我在新开发机器上安装了NDK described in this article。这导致我的Android SDK目录中有一个文件夹ndk-bundle
。我曾经从命令行编译代码,然后将二进制文件复制到我的Android Studio项目的资源中,但我无法弄清楚如何使用NDK 13执行此操作,因此我尝试按照the tutorial to include my native code in the Android Studio project进行操作。但是,几乎所有最近的指令都假设一个人想要构建一个库,而不是一个独立的二进制文件,所以我没有走得太远。
如果我弄清楚如何让它工作,我会切换到CMake。我的本机项目具有以下(简化)结构:
天然
Android.mk
LOCAL_PATH := $(call my-dir)/my_tool/src
include $(CLEAR_VARS)
LOCAL_MODULE := my_tool
LOCAL_SRC_FILES := main.c
include $(BUILD_EXECUTABLE)
Application.mk
APP_ABI := all
APP_PLATFORM := android-21
my_tool
如何在Windows 10开发机器上使用Android Studio或NDK从命令行编译?
修改
我在build.gradle中使用它:
externalNativeBuild {
ndkBuild {
path "../native/Android.mk"
}
}
Gradle创建一个包含构建配置的目录.externalNativeBuild
,但我无法找到如何实际构建本机代码。我运行gradle时没有创建二进制文件。
我无法找到有关ndk-build
的gradle配置的任何信息。
答案 0 :(得分:4)
我试图尽可能地遵循您的简化结构。
以下是 app / build.gradle 文件:
apply plugin: 'com.android.library'
android {
compileSdkVersion 24
buildToolsVersion "25.0.1"
defaultConfig {
minSdkVersion 21
targetSdkVersion 24
externalNativeBuild {
ndkBuild {
targets "my_tool"
abiFilters "armeabi-v7a"
}
}
}
externalNativeBuild {
ndkBuild {
path "../native/Android.mk"
}
}
}
native / Android.mk 文件与您的文件相同:
LOCAL_PATH := $(call my-dir)/my_tool/src
include $(CLEAR_VARS)
LOCAL_MODULE := my_tool
LOCAL_SRC_FILES := main.c
include $(BUILD_EXECUTABLE)
我还有 native / main.c 文件和最小的 app / src / main / AndroidManifest.xml :
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="my.tool" />
我没有触及Android Studio向导生成的根 build.gradle 脚本:
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.0-alpha3'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
现在我可以构建项目了,这就是我得到的:
$> file ./app/build/intermediates/ndkBuild/debug/obj/local/armeabi-v7a/my_tool
ELF 32-bit LSB shared object, ARM, version 1 (SYSV), dynamically linked (uses shared libs), not stripped
Android Studio在默认视图中的 cpp 文件夹中显示 main.c :
更新:要将可执行文件剥离并打包在APK中,必须更改 native / Android.mk :
LOCAL_PATH := $(call my-dir)/my_tool/src
install: LIB_PATH := $(call my-dir)/libs
include $(CLEAR_VARS)
LOCAL_MODULE := my_tool
LOCAL_SRC_FILES := main.c
include $(BUILD_EXECUTABLE)
install: $(LOCAL_INSTALLED)
-mkdir $(LIB_PATH)
-rm -r $(LIB_PATH)
mv $< $(<:my_tool=lib-my_tool-.so)
mv $(realpath $(dir $<)..) $(LIB_PATH)
.PHONY: install
此外, app / build.gradle 需要进行一些调整:
apply plugin: 'com.android.application'
android {
compileSdkVersion 24
buildToolsVersion "25.0.1"
defaultConfig {
minSdkVersion 21
targetSdkVersion 24
externalNativeBuild {
ndkBuild {
targets "my_tool"
abiFilters "armeabi-v7a"
arguments 'V=1', 'install'
}
}
}
externalNativeBuild {
ndkBuild {
path "../native/Android.mk"
}
}
sourceSets {
main {
jniLibs.srcDirs = ['../native/libs']
}
}
}
这取决于old hack,这取决于NDK的未记录行为,并且可能在未来NDK升级时中断而不另行通知。
答案 1 :(得分:2)
如果你所做的只是改变NDK版本,那么我相信这非常简单,而且我们错过了一些简单的东西。我认为您需要更新PATH环境变量以指向新的ndk-bundle
路径并尝试再次运行ndk-build
。
根据我的经验,我无法让Cmake for Android生成可执行文件(独立二进制文件)或静态库作为最终输出。因为我希望最终输出是可执行文件,所以我不得不切换回使用NDK而忘记Cmake。
<强>更新强>
这是使用Android Studio和NDK构建C ++可执行文件的方法。这是没有使用CMake,即使你没有JNI代码也是如此。
应用程序/的build.gradle
sourceSets.main {
// Do not run default ndkbuild
jni.srcDirs = []
// Place where .so libs are available
jniLibs.srcDir 'src/main/libs'
}
task buildNative(type: Exec, description: 'Compile JNI source via NDK') {
def ndkDir = android.ndkDirectory
commandLine "$ndkDir/ndk-build.cmd", 'V=1',
'-C', file('src/main/jni').absolutePath,
'-j', Runtime.runtime.availableProcessors(),
'all',
'NDK_DEBUG=1'
}
task cleanNative(type: Exec, description: 'Clean JNI object files') {
def ndkDir = android.ndkDirectory
commandLine "$ndkDir/ndk-build.cmd",
'-C', file('src/main/jni').absolutePath,
'clean'
}
目录结构
您需要一个名为app/src/main/jni
的文件夹。如您所见,上面的gradle代码只是针对该目录调用ndk-build
。以下是我建议您设置目录的方法:
JNI
Android.mk
LOCAL_PATH := $(call my-dir)
include $(call all-subdir-makefiles)
Application.mk
APP_ABI := all
APP_PLATFORM := android-21
天然
Android.mk
include $(CLEAR_VARS)
LOCAL_C_INCLUDES := my_tool/src
LOCAL_PATH := $(call my-dir)
LOCAL_MODULE := my_tool
LOCAL_SRC_FILES := my_tool/src/main.c
include $(BUILD_EXECUTABLE)
建筑
要构建,您可以从ndk-build
目录运行app/src/main/jni
,也可以从项目的根目录运行gradle buildNative
。你可以看到,在我上面显示的gradle代码中,有一个名为buildNative
的任务,因此它将成为执行的gradle代码。
顶级Android.mk
文件有助于您在app/src/main/jni
下添加要构建的更多模块,它会遍历该目录中的所有子目录并调用任何其他Android.mk
个文件它找到了。