Compile standalone binaries with NDK 13

With the release of NDK 10, I used ndk-build to compile stand-alone binaries for many different ABIs and several API levels. These binaries should have been included in the application. However, I installed NDK on a new development machine as described in this article . This led to the creation of the ndk-bundle folder in my Android SDK directory. I used to compile the code from the command line and then copied 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 own code in the Android Studio project . However, almost all of the latest instructions assume that you want to create a library, not a separate binary, so I have not gotten far.

I would switch to CMake if I understood how to make it 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

      • CSI
        • main.c

How can I compile this using Android Studio or NDK from the command line on our Windows 10 development machines?

Edit:

I use this in build.gradle:

 externalNativeBuild { ndkBuild { path "../native/Android.mk" } } 

Gradle creates the .externalNativeBuild directory, which contains the assembly configurations, but I cannot .externalNativeBuild out how to actually build my own code. When you start gradle, no binaries are created.

I cannot find gradle configuration information for ndk-build .

+6
source share
2 answers

I tried to follow your simplified structure as close as possible.

Here is the app / build.gradle file :

 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 native / Android.mk file 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 native / main.c files and the minimal application /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 created by the 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 create a 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 the default view:

enter image description here

Update : in order to remove the executable file and pack it in the APK, you need to change the 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 

In addition, 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'] } } } 

It depends on the old hack , which depends on the undocumented behavior of the NDK and may be interrupted without warning when updating the NDK in the future.

+4
source

If all you do is change the NDK versions, I find it pretty simple and that we missed something simple. I think you need to update the PATH environment variable to point to the new ndk-bundle path and run ndk-build again.

From my experience, I could not get Cmake for Android to release an executable (stand-alone binary) or a static library as the final output. Since I wanted the end result to be executable, I had to switch back to using NDK and forget about Cmake.

Update

Here's how to create a C ++ executable using Android Studio and NDK. This is without using CMake, and this is even if you don't have JNI code.

application / 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' } 

Directory structure

You need to have a folder named app/src/main/jni . As you can see, the gradle code above just calls ndk-build in this directory. Here, as I recommend you set up your directories:

  • Jni

    • Android.mk

       LOCAL_PATH := $(call my-dir) include $(call all-subdir-makefiles) 
    • Application.mk

       APP_ABI := all APP_PLATFORM := android-21 
    • Native

      • my_tool
        • CSI
          • main.c
      • 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) 

Construction

To build, you can run ndk-build from the app/src/main/jni or run gradle buildNative from the project root directory. You can see that in the gradle code I showed above, there is a task called buildNative , so the gradle code to be executed.

The top-level Android.mk file helps you to ever add more modules to be built in app/src/main/jni , it moves all the subdirectories in this directory and calls any other Android.mk files found.

+2
source

Source: https://habr.com/ru/post/1013054/


All Articles