Change ndk-build output locations
Asked Answered
F

5

21

My app has the following structure

Android
|
|-> app
|    |
|    |-> build [1]
|    |-> src
|    |    |-> main
|    |    |     |-> assets
|    |    |     |-> java
|    |    |     |-> jni 
|    |    |     |     |-> Android.mk
|    |    |     |     |-> Application.mk
|    |    |     |
|    |    |     |-> jniLibs
|    |    |     |      |-> armeabi
|    |    |     |      |-> armeabi-v7a
|    |    |     |
|    |    |     |-> res
|    |    |     |-> AndroidManifest.xml
|
|-> build [2]

I am building my .so libraries with ndk-build command in a linux machine. I use it like:

<my_ndk_path>/ndk-build -C <my_project_path>/Android/app/src/main/

The build process works fine and output files are produced with no errors.

My problem is that the result files are not "directed to the proper position"

The libs generated at :

.app/src/main/libs/armeabi-v7a/libMyGeneratedLibrary.so
.app/src/main/libs/armeabi/libMyGeneratedLibrary.so

and the obj files at :

.app/src/main/obj/local/armeabi-v7a/libMyGeneratedLibrary.so
.app/src/main/obj/local/armeabi/libMyGeneratedLibrary.so

I would like the output to produced in different locations:

  1. The libs at jniLibs. ie. ./app/src/main/jniLibs/armeabi*
  2. The obj under one of the build folders. ie. build[1] or build[2].

Is there any possible way to achieve that by changing some parameter to the .mk files or to the build command?


Edit

TARGET_OUT does not seem to work in NDK r6b

Executing command ndk-build -C Android/app/src/main/ TARGET_OUT='Android/app/src/main/jniLibs/$(TARGET_ARCH_ABI)'

Warnings as the following appear for each generated file.

android-ndk-r6b/build/core/build-binary.mk:217: warning: overriding commands for target 'Android/app/src/main/jniLibs//objs/***/****.o'
android-ndk-r6b/build/core/build-binary.mk:217: warning: ignoring old commands for target 'Android/app/src/main/jniLibs//objs/***/****.o'
Flabby answered 16/6, 2015 at 10:32 Comment(0)
F
2

Edit (for anyone that step on this topic with newer NDK versions):

  • Use NDK_LIBS_OUT to change libs output (requires NDK r9 and above)
  • Use NDK_OUT to change obj output (requires NDK r7c and above)

Build command is is:

ndk-build NDK_LIBS_OUT=./jniLibs NDK_OUT=./obj

Previous answer (applicable in any case):

How I solve it. Not really elegant but at least it works.

Because my building mechanism is quite complicated so I had a couple of custom gradle tasks and scripts too, it doesn't really matter to me the single command for the build.

So I kept build command as is

<my_ndk_path>/ndk-build -C <my_project_path>/Android/app/src/main/

Add a the folder creation (-p don't generate error if it exists)

mkdir -p <my_project_path>/Android/app/src/main/jniLibs/

Then I move the .so files to the final location with the sync command.

rsync -avh --remove-source-files                        \
      <my_project_path>/Android/app/src/main/libs/*     \
      <my_project_path>/Android/app/src/main/jniLibs/

You can do something similar for the obj folder. I just modified my .gitignore so I left it as is.

Flabby answered 21/8, 2015 at 8:46 Comment(0)
G
35

You can use NDK_LIBS_OUT to change libs output and NDK_OUT to change obj output. Just like this : ndk-build NDK_LIBS_OUT=./jniLibs NDK_OUT=./obj

Goddart answered 7/7, 2015 at 9:57 Comment(6)
This does not really work for me. It looks like the these are ignored from the NDK. Maybe it is part of a later one as I have a pretty old version r6b.Flabby
NDK_OUT was added in revision 7c; NDK_LIBS_OUT was added in revision 9.Impendent
Where should NDK_LIBS_OUT be added, in Android.mk or Application.mk?Hatred
NDK_LIBS_OUT should be added as an argument to ndk-build callTailgate
So how do you add an argument to the ndk-build call? Gradle 3.2.1 keeps telling me that arguments is invalid.Fanchon
Anyway you can do that for include files? Something like NDK_LIBS_OUT for the lib/ directory and NDK_INCLUDES_OUT for the include/ directory?Ayeshaayin
S
5

If you need to build for all available architectures, please use argument:

    TARGET_OUT='<your_build_dir>/$(TARGET_ARCH_ABI)'

If just one target architecture is enough, then use argument:

    TARGET_OUT=<your_build_dir>
Soda answered 10/8, 2015 at 14:12 Comment(3)
This does not work for me either it the $(TARGET_ARCH_ABI) which I need does not take any effect, the lib is produced ones in the jniLibs folder and not inside the armeabi, armeabi-v7aFlabby
Could you copy&paste here your exact command line when using the above mentioned parameter? I'm curious as I used that myself succesfully couple of hours ago. Also, what is your NDK version?Soda
Sadly, its a pretty old version r6b. I tried this with many different ways and also tried to add TARGET_OUT := ... to Application.mk when it passes and not fails I get the warnings that I added to my original post.Flabby
L
3

The better and more simple way to specify out put locations is linking Gradle to your native library. After that, using buildStagingDirectory options in ndkBuild block to specify out put location:

android {
    externalNativeBuild {
        ndkBuild {
            // Tells Gradle to put outputs from external native
            // builds in the path specified below.
            buildStagingDirectory  "src/main/libs"
        }
    }
}

Then just Sync Gradle and build, done.

Lewendal answered 2/3, 2020 at 15:57 Comment(2)
The buildStagingDirectory specifies the path to external native build output directory, to replace the default <project_dir>/.cxx/. I agree that the official explanation above may be confusing, but this directory contains intermediate build files (logs, objects, etc.). The .so files go normally to <project_dir>/build directory. See the discussion.Publicly
Both cmake and ndkBuild sections seem to allow buildStagingDirectory option, thanks!Khalid
F
2

Edit (for anyone that step on this topic with newer NDK versions):

  • Use NDK_LIBS_OUT to change libs output (requires NDK r9 and above)
  • Use NDK_OUT to change obj output (requires NDK r7c and above)

Build command is is:

ndk-build NDK_LIBS_OUT=./jniLibs NDK_OUT=./obj

Previous answer (applicable in any case):

How I solve it. Not really elegant but at least it works.

Because my building mechanism is quite complicated so I had a couple of custom gradle tasks and scripts too, it doesn't really matter to me the single command for the build.

So I kept build command as is

<my_ndk_path>/ndk-build -C <my_project_path>/Android/app/src/main/

Add a the folder creation (-p don't generate error if it exists)

mkdir -p <my_project_path>/Android/app/src/main/jniLibs/

Then I move the .so files to the final location with the sync command.

rsync -avh --remove-source-files                        \
      <my_project_path>/Android/app/src/main/libs/*     \
      <my_project_path>/Android/app/src/main/jniLibs/

You can do something similar for the obj folder. I just modified my .gitignore so I left it as is.

Flabby answered 21/8, 2015 at 8:46 Comment(0)
I
0

The simpliest way is linking Android.mk file to Gradle, like this:

android {
    ...
    externalNativeBuild {
        ndkBuild {
            path file('src/main/jni/Android.mk')
        }
    }
}

Then just click on Sync Now and build the project

Integrand answered 8/1, 2021 at 19:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.