我正在尝试将原生代码添加到我的应用中。我拥有../main/jni
中的所有内容,就像我的Eclipse项目中一样。我已将ndk.dir=...
添加到local.properties
。我还没有做任何其他事情(我不确定还有什么需要,所以如果我错过了什么让我知道)。当我尝试构建时,我收到此错误:
Execution failed for task ':app:compileDebugNdk'.
> com.android.ide.common.internal.LoggedErrorException: Failed to run command:
/Users/me/android-ndk-r8e/ndk-build NDK_PROJECT_PATH=null
APP_BUILD_SCRIPT=/Users/me/Project/app/build/ndk/debug/Android.mk APP_PLATFORM=android-19
NDK_OUT=/Users/me/Project/app/build/ndk/debug/obj
NDK_LIBS_OUT=/Users/me/Project/app/build/ndk/debug/lib APP_ABI=all
Error Code:
2
Output:
make: *** No rule to make target `/Users/me/Project/webapp/build/ndk/debug//Users/me/Project/app/src/main/jni/jni_part.cpp',
needed by `/Users/me/Project/app/build/ndk/debug/obj/local/armeabi-v7a/objs/webapp//Users/me/Project/app/src/main/jni/jni_part.o'.
Stop.
我需要做什么?
Android.mk:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# OpenCV
OPENCV_CAMERA_MODULES:=on
OPENCV_INSTALL_MODULES:=on
include .../OpenCV-2.4.5-android-sdk/sdk/native/jni/OpenCV.mk
LOCAL_MODULE := native_part
LOCAL_SRC_FILES := jni_part.cpp
LOCAL_LDLIBS += -llog -ldl
include $(BUILD_SHARED_LIBRARY)
Application.mk:
APP_STL := gnustl_static
APP_CPPFLAGS := -frtti -fexceptions
APP_ABI := armeabi armeabi-v7a
APP_PLATFORM := android-8
答案 0 :(得分:116)
在试图避免实验并坦率地厌倦了NDK及其所有hackery时,我很高兴Gradle Build Tools的2.2.x出现了,现在它正常运行。关键是externalNativeBuild
并将ndkBuild
路径参数指向Android.mk
或将ndkBuild
更改为cmake
,并将路径参数指向CMakeLists.txt
构建脚本。
android {
compileSdkVersion 19
buildToolsVersion "25.0.2"
defaultConfig {
minSdkVersion 19
targetSdkVersion 19
ndk {
abiFilters 'armeabi', 'armeabi-v7a', 'x86'
}
externalNativeBuild {
cmake {
cppFlags '-std=c++11'
arguments '-DANDROID_TOOLCHAIN=clang',
'-DANDROID_PLATFORM=android-19',
'-DANDROID_STL=gnustl_static',
'-DANDROID_ARM_NEON=TRUE',
'-DANDROID_CPP_FEATURES=exceptions rtti'
}
}
}
externalNativeBuild {
cmake {
path 'src/main/jni/CMakeLists.txt'
}
//ndkBuild {
// path 'src/main/jni/Android.mk'
//}
}
}
有关详细信息,请查看Google's page on adding native code。
正确设置后,您可以./gradlew installDebug
然后离开。您还需要注意NDK正在转向clang,因为Android NDK现在不推荐使用gcc。
其他答案确实指出了阻止自动创建Android.mk
文件的正确方法,但是它们无法更好地与Android Studio集成。我已经添加了从源代码实际清理和构建的功能,而无需转到命令行。您的local.properties
文件需要ndk.dir=/path/to/ndk
apply plugin: 'com.android.application'
android {
compileSdkVersion 14
buildToolsVersion "20.0.0"
defaultConfig {
applicationId "com.example.application"
minSdkVersion 14
targetSdkVersion 14
ndk {
moduleName "YourModuleName"
}
}
sourceSets.main {
jni.srcDirs = [] // This prevents the auto generation of Android.mk
jniLibs.srcDir 'src/main/libs' // This is not necessary unless you have precompiled libraries in your project.
}
task buildNative(type: Exec, description: 'Compile JNI source via NDK') {
def ndkDir = android.ndkDirectory
commandLine "$ndkDir/ndk-build",
'-C', file('src/main/jni').absolutePath, // Change src/main/jni the relative path to your jni source
'-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",
'-C', file('src/main/jni').absolutePath, // Change src/main/jni the relative path to your jni source
'clean'
}
clean.dependsOn 'cleanNative'
tasks.withType(JavaCompile) {
compileTask -> compileTask.dependsOn buildNative
}
}
dependencies {
compile 'com.android.support:support-v4:20.0.0'
}
src/main/jni
目录假定项目的标准布局。它应该是从build.gradle
文件位置到jni
目录的相对位置。
同时检查此Stack Overflow answer。
您的gradle版本和常规设置非常重要。如果您有一个较旧的项目,我强烈建议您使用最新的Android Studio创建一个新项目,并查看Google认为标准项目的内容。另外,使用gradlew
。这可以保护开发人员免受gradle版本不匹配的影响。最后,必须正确配置gradle插件。
你问这个gradle插件的最新版本是什么? Check the tools page并相应地修改版本。
// Top-level build file where you can add configuration options common to all sub-projects/modules.
// Running 'gradle wrapper' will generate gradlew - Getting gradle wrapper working and using it will save you a lot of pain.
task wrapper(type: Wrapper) {
gradleVersion = '2.2'
}
// Look Google doesn't use Maven Central, they use jcenter now.
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.2.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
jcenter()
}
}
确保gradle wrapper
生成gradlew
文件和gradle/wrapper
子目录。这是一个很大的问题。
这已多次出现,但android.ndkDirectory
是在1.1之后获取文件夹的正确方法。 Migrating Gradle Projects to version 1.0.0。如果你使用插件的实验版或古代版,你的里程可能会有所不同。
答案 1 :(得分:72)
gradle通过生成另一个包含源的绝对路径的Android.mk文件来支持ndk编译。 NDK支持自OSX上的r9以及Windows上的r9c以来的绝对路径,因此您需要将NDK升级到r9 +。
由于Gradle的NDK支持是初步的,您可能会遇到其他麻烦。如果是这样,您可以通过设置:
从gradle中取消激活ndk编译sourceSets.main {
jni.srcDirs = []
jniLibs.srcDir 'src/main/libs'
}
能够自己调用ndk-build并集成libs /.
中的lib 不过,你有什么问题为x86编译吗?我发现你没有把它包含在你的APP_ABI中。答案 2 :(得分:7)
在我的情况下,我在Windows上并按照上面的Cameron的回答只有在使用ndk-build的全名 ndk-build.cmd 时才有效。我必须清理并重建项目,然后重新启动模拟器才能使应用程序正常工作(实际上我是从NDK将示例HelloJni导入Android Studio)。但是,请确保 NDK的路径不包含空格。
最后,我的build.gradle完整列出如下:
apply plugin: 'com.android.application'
android {
compileSdkVersion 21
buildToolsVersion "21.1.2"
defaultConfig {
applicationId "com.example.hellojni"
minSdkVersion 4
targetSdkVersion 4
ndk {
moduleName "hello-jni"
}
testApplicationId "com.example.hellojni.tests"
testInstrumentationRunner "android.test.InstrumentationTestRunner"
}
sourceSets.main {
jni.srcDirs = [] // This prevents the auto generation of Android.mk
// sourceSets.main.jni.srcDirs = []
jniLibs.srcDir 'src/main/libs' // This is not necessary unless you have precompiled libraries in your project.
}
task buildNative(type: Exec, description: 'Compile JNI source via NDK') {
def ndkDir = android.plugin.ndkFolder
commandLine "$ndkDir/ndk-build.cmd",
'-C', file('src/main/jni').absolutePath, // Change src/main/jni the relative path to your jni source
'-j', Runtime.runtime.availableProcessors(),
'all',
'NDK_DEBUG=1'
}
task cleanNative(type: Exec, description: 'Clean JNI object files') {
def ndkDir = android.plugin.ndkFolder
commandLine "$ndkDir/ndk-build.cmd",
'-C', file('src/main/jni').absolutePath, // Change src/main/jni the relative path to your jni source
'clean'
}
clean.dependsOn 'cleanNative'
tasks.withType(JavaCompile) {
compileTask -> compileTask.dependsOn buildNative
}
}
dependencies {
compile 'com.android.support:support-v4:21.0.3'
}
答案 3 :(得分:5)
我在OSX上的问题是gradle版本。 Gradle忽略了我的Android.mk。 因此,为了覆盖此选项,并使用我的make,我已经输入了这一行:
sourceSets.main.jni.srcDirs = []
android
内的build.gradle
标记内的
。
我浪费了很多时间在这上面!
答案 4 :(得分:5)
Android Studio 2.2能够使用ndk-build和cMake。虽然,我们必须等到2.2.3才能获得Application.mk支持。我已经尝试过了,它可以工作......但是,我的变量没有出现在调试器中。我仍然可以通过命令行查询它们。
你需要做这样的事情:
externalNativeBuild{
ndkBuild{
path "Android.mk"
}
}
defaultConfig {
externalNativeBuild{
ndkBuild {
arguments "NDK_APPLICATION_MK:=Application.mk"
cFlags "-DTEST_C_FLAG1" "-DTEST_C_FLAG2"
cppFlags "-DTEST_CPP_FLAG2" "-DTEST_CPP_FLAG2"
abiFilters "armeabi-v7a", "armeabi"
}
}
}
请参阅http://tools.android.com/tech-docs/external-c-builds
NB: externalNativeBuild
内defaultConfig
的额外嵌套是Android Studio 2.2 Preview 5(2016年7月8日)引入的重大变化。请参阅上面链接中的发行说明。
答案 5 :(得分:1)
在模块build.gradle中,在任务字段中,除非我使用:
,否则会出现错误def ndkDir = android.plugin.ndkFolder
我看到人们使用
def ndkDir = plugins.getPlugin('com.android.library').sdkHandler.getNdkFolder()
和
[2015-06-26 20:37:36 +0000] [11] [ERROR] Exception in worker process:
Traceback (most recent call last):
File "/app/.heroku/python/lib/python2.7/site-packages/gunicorn/arbiter.py", line 507, in spawn_worker
worker.init_process()
File "/app/.heroku/python/lib/python2.7/site-packages/gunicorn/workers/base.py", line 118, in init_process
self.wsgi = self.app.wsgi()
self.callable = self.load()
File "/app/.heroku/python/lib/python2.7/site-packages/gunicorn/app/base.py", line 67, in wsgi
File "/app/.heroku/python/lib/python2.7/site-packages/gunicorn/app/wsgiapp.py", line 65, in load
return self.load_wsgiapp()
File "/app/.heroku/python/lib/python2.7/site-packages/gunicorn/app/wsgiapp.py", line 52, in load_wsgiapp
return util.import_app(self.app_uri)
File "/app/.heroku/python/lib/python2.7/site-packages/gunicorn/util.py", line 355, in import_app
__import__(module)
File "/app/prompt/wsgi.py", line 4, in <module>
from whitenoise.django import DjangoWhiteNoise
File "/app/.heroku/python/lib/python2.7/site-packages/whitenoise/django.py", line 14, in <module>
from django.contrib.staticfiles.storage import staticfiles_storage
File "/app/.heroku/python/lib/python2.7/site-packages/django/contrib/staticfiles/storage.py", line 12, in <module>
from django.core.cache import (
File "/app/.heroku/python/lib/python2.7/site-packages/django/core/cache/__init__.py", line 34, in <module>
if DEFAULT_CACHE_ALIAS not in settings.CACHES:
File "/app/.heroku/python/lib/python2.7/site-packages/django/conf/__init__.py", line 48, in __getattr__
File "/app/.heroku/python/lib/python2.7/site-packages/django/conf/__init__.py", line 42, in _setup
self._setup(name)
% (desc, ENVIRONMENT_VARIABLE))
ImproperlyConfigured: Requested setting CACHES, but settings are not configured. You must either define the environment variable DJANGO_SETTINGS_MODULE or call settings.configure() before accessing settings.
worker.init_process()
但直到我将其更改为我实际导入的插件时,这些都没有工作。