Компилировать отдельные файлы с NDK 13
с выпусками NDK 10 я использовал ndk-build
для компиляции автономных двоичных файлов для многих различных ABIs и нескольких уровней API. Эти файлы должны быть включены в приложение. Тем не менее, я установил NDK на новую машину разработки как описанные в этой статье. Это привело к папке ndk-bundle
в моем каталоге Android SDK. Я использовал для компиляции кода из командной строки, а затем скопировать двоичные файлы на ресурсы моего проекта Android Studio, но я не мог понять как это сделать с NDK 13, поэтому я попытался следовать учебник для включения моего собственного кода в проект Android Studio. Однако почти все последние инструкции предполагают, что нужно построить библиотеку, а не автономный двоичный файл, поэтому я не ушел далеко.
Я бы переключился на CMake, если бы понял, как заставить его работать. Мой родной проект имеет следующее (упрощенный) структура:
-
уроженца
-
Android.МК
LOCAL_PATH := $(call my-dir)/my_tool/src include $(CLEAR_VARS) LOCAL_MODULE := my_tool LOCAL_SRC_FILES := main.c include $(BUILD_EXECUTABLE)
-
применение.МК
APP_ABI := all APP_PLATFORM := android-21
-
my_tool
- src
- main.c
- src
-
как я могу скомпилировать это с помощью Android Studio или NDK из командной строки в нашей разработке Windows 10 машины?
Edit:
Я использую это в build.Gradle в:
externalNativeBuild {
ndkBuild {
path "../native/Android.mk"
}
}
Gradle создает каталог .externalNativeBuild
который содержит конфигурации сборки, но я не могу узнать, как на самом деле построить собственный код. При запуске gradle двоичные файлы не создаются.
Я не могу найти любой информация о конфигурации gradle для ndk-build
.
2 ответов
Я старался следовать вашей упрощенной структуре как можно ближе.
вот файл 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"
}
}
}
файл родной / Android.МК идентично вашему:
LOCAL_PATH := $(call my-dir)/my_tool/src
include $(CLEAR_VARS)
LOCAL_MODULE := my_tool
LOCAL_SRC_FILES := main.c
include $(BUILD_EXECUTABLE)
у меня также есть файлы уроженца/главная.c и минимальный app / src / main / AndroidManifest.в XML:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="my.tool" />
Я не трогал корень построить.Gradle в скрипт, созданный Мастер Android Studio:
// 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 показывает мой main.c на cpp папка в представлении по умолчанию:
обновление: иметь исполняемый раздели и упаковываются в APK, уроженца/Андроид.МК надо менять:
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']
}
}
}
это зависит от старый Хак который зависит от недокументированного поведения NDK и может сломаться без уведомления о будущем обновлении NDK.
если все, что вы делаете, это изменение версий NDK, то я считаю, что это довольно просто, и что нам не хватает чего-то простого. Я думаю, что вам нужно обновить переменную среды PATH, чтобы указать на новый ndk-bundle
путь и попробуйте запустить ndk-build
снова.
по моему опыту, я не мог получить Cmake для Android для создания исполняемого файла (автономный двоичный файл) или статической библиотеки в качестве окончательного вывода. Поскольку я хотел, чтобы конечный результат был исполняемым, мне пришлось переключитесь обратно на использование NDK и забудьте о Cmake.
обновление
вот как создать исполняемый файл c++ с помощью Android Studio и NDK. Это без использования CMake, и это даже если у вас нет кода JNI.
app / 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.МК
LOCAL_PATH := $(call my-dir) include $(call all-subdir-makefiles)
-
применение.МК
APP_ABI := all APP_PLATFORM := android-21
-
уроженца
- my_tool
- src
- main.c
- src
-
Android.МК
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)
- my_tool
-
здание
для build, вы можете либо запустить ndk-build
С или gradle buildNative
из корневого каталога проекта. Вы можете видеть, что в коде gradle, который я показал выше, есть задача с именем buildNative
, так что это код gradle, который будет выполнен.
топ-уровня Android.mk
файл помогает в том случае, если вы когда-либо добавляете больше модулей, которые будут построены под app/src/main/jni
, он пересекает все подкаталоги в этом каталоге и вызывает любой другой Android.mk
файлы, которые он находит.