With NDK 10 releases, I used to use ndk-build to compile standalone binaries for many different ABIs and multiple API levels. These binaries were to be included in an app. However, I installed the NDK on a new development machine as described in this article. This resulted in a folder ndk-bundle within my Android SDK directory. I used to compile the code from a command line and then copy the binaries to the resources of my Android Studio project, but I could not figure out how to do this with NDK 13 so I tried to follow the tutorial to include my native code in the Android Studio project. However, almost all recent instructions assume that one wants to build a library, not a standalone binary, so I did not get far.
I would switch to CMake if I figured out how to get it to work. My native project has the following (simplified) structure:
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)
Application.mk
APP_ABI := all
APP_PLATFORM := android-21
my_tool
How can I compile this using either Android Studio or the NDK from the command line on our Windows 10 development machines?
Edit:
I am using this in build.gradle:
externalNativeBuild {
    ndkBuild {
        path "../native/Android.mk"
    }
}
Gradle creates a directory .externalNativeBuild which contains build configurations, but I cannot find out how to actually build the native code. No binaries are created when I run gradle.
I cannot find any information about gradle configuration for ndk-build.
I tried to follow your simplified structure as closely as possible.
Here is the file 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"
        }
    }
}
The file native/Android.mk is identical to yours:
LOCAL_PATH := $(call my-dir)/my_tool/src
include $(CLEAR_VARS)
LOCAL_MODULE    := my_tool
LOCAL_SRC_FILES := main.c
include $(BUILD_EXECUTABLE)
I also have the files native/main.c and a minimal app/src/main/AndroidManifest.xml:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
  package="my.tool" />
I did not touch the root build.gradle script generated by Android Studio wizard:
// 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
}
Now I can build the project and here is what I get:
$> 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 shows my main.c in the cpp folder in default view:

Update: to have the executable stripped and packaged in the APK, native/Android.mk must be changed:
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
Also, app/build.gradle needs some tweaking:
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']
        }
    }
}
This relies on the old hack which depends on undocumented behavior of NDK, and may break without notice on a future NDK upgrade.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With