Компилировать отдельные файлы с 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 файлы, которые он находит.
 
            