I'm trying to build a project using the android ndk (on Windows), and I'm having some issues specifically with the source files (LOCAL_SRC_FILES in the Android.mk)
I'm trying to use relative paths to a parent folder such as
LOCAL_SRC_FILES := ../../../src/main.cpp
And when running ndk_build.cmd, it outputs the following error:
Compile++ thumb : GTP <= main.cpp
The system cannot find the file specified.
make: *** [obj/local/armeabi/objs/GTP/__/__/__/src/.o] Error 1
So I tried using absolute paths:
LOCAL_SRC_FILES := D:/Path/To/src/main.cpp
Unfortunately this doesn't work because the : causes issues on windows
Is there any way I can specify source files in a relative directory (or absolute)? The reason I am asking is because I want to avoid making a symbolic link to the src folder if possible.
According to ndk documentation it is recommended to use relative paths and the following macro (Android.mk uses syntax of make files):
LOCAL_PATH := $(call my-dir)
An Android.mk file must begin with the definition of the LOCAL_PATH variable.
It is used to locate source files in the development tree. In this example,
the macro function 'my-dir', provided by the build system, is used to return
the path of the current directory (i.e. the directory containing the
Android.mk file itself).
So you can replace your LOCAL_SRC_FILES with something similar to:
LOCAL_SRC_FILES := $(LOCAL_PATH)/../../../src/main.cpp
The easiest way to work with source files spread across many directories, is to compile separate static libraries for each directory or group of directories. In NDK, these libraries are called "modules". For each module, you specify LOCAL_SRC_PATH in Android.mk. LOCAL_SRC_FILES are relative to this path. The caveat is that LOCAL_C_INCLUDES etc. are relative to project root directory (usually, the one above the jni directory).
You can have many Android.mk files in your project, but you can build many modules with single Android.mk.
Try this:
LOCAL_PATH:=$(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := YOUR_SRC_IN_LIB_JNI
Related
I am a android NDK newbie, I am trying to follow the documentation at https://developer.android.com/ndk/guides/prebuilts and I found it is unclear on how to setup the code.
So to declare a prebuilt library, it shows the first step:
Give the module a name. This name does not need to be the same as that
of the prebuilt library, itself.
Question 1: What does this mean by giving the module a name? rename the module folder? is this the folder usually called jni/? does it matter where this folder should be?
Question 2: If I don't find this jni/ folder, should I just add one by creating a new folder or right clicked on my project in android studio to add new module? I did the right click thing and there is no such module for native c++ libs.
the second step:
In the module's Android.mk file, assign to LOCAL_SRC_FILES ...
Question 3: Should I create the 1Android.mk` file by myself? if it is a must, why not have it generated automatically?
I then tried to follow the documentation at https://developer.android.com/studio/projects/add-native-code#new-project but there is no such Android.mk file created...
Anyway, in the Android.mk file it has something like this:
include $(CLEAR_VARS)
LOCAL_MODULE := foo-user
LOCAL_SRC_FILES := foo-user.c
LOCAL_SHARED_LIBRARIES := foo-prebuilt
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_SHARED_LIBRARY)
include $(BUILD_SHARED_LIBRARY)
Question 4: On the documentation page, where variables like PREBUILT_SHARED_LIBRARY BUILD_SHARED_LIBRARY is defined? can these path can be any place in the system as long I define it with full path?
Question 5: for LOCAL_PATH, I understand it is the local path where the Android.mk file locates, does that mean 1) the system will find this file automatically, 2) I can only have one folder with Android.mk if I want to use native libs?
As the title is self-explanatory, I'd want to replace some files in system/bin/ and system/lib/ right before when the system.img is being generated.
To be more exact, I've got some prebuilt .so files which shuold be copied over the existing ones. For example libart.so. Please note that replacing art/ (source code of art) with the modified art source code is not an option.
To do this, which mk file should I investigate and put my replacing code into?
You may follow the same structure as the one proposed in this other question, but use this macro:
PRODUCT_COPY_FILES += \
device/common/my_bin.bin:cache/my_bin.bin \
device/common/my_so.so:system/art/my_so.so
This works as follows:
The file is copied from left to(:) right.
When the image is generated, in this case cache or system, it would be generated with the files contained in those folders.
As we have copied our files to that destination, when system.img is generated, our file will be contained.
Also, the order in which this files are copied, matters. For instance if you are copying a file that already exists, hence, you want it replaced. (As your libart.so), you would need YOUR call to that copy to be done before the default one.
For this, I recommend doing:
source build/envsetup.sh
lunch <<device>>
mgrep libart.so -> This does a grep through mk files, so you can see where the default copy is done.
Insert $(info whatever) calls in desired mk files to trace where is a good spot to add your PRODUCT_COPY_FILES.
It's not easy to answer where to add it. I have never modified libart.so myself, but I have copied many files this way and it works like a charm.
I hope it works for your case as well.
A quick dirty way to this:
Copy desired files to out(..)/system/lib or wherever after system.img has been built
make snod
Other way is using Android.mk. Create a new dir in device tree eg libart-prebuilt. Put here your lib, then create an Android.mk file with content
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libart-prebuilt
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_PATH := $(TARGET_OUT)/lib
LOCAL_MODULE_STEM := libart
LOCAL_MODULE_SUFFIX := $(TARGET_SHLIB_SUFFIX)
LOCAL_SRC_FILES := libart.so
LOCAL_MODULE_CLASS := SHARED_LIBRARIES
include $(BUILD_PREBUILT)
Now just add libart-prebuilt to PRODUCT_PACKAGES in your device.mk
Also there's an option to add binary .so library as a product package, using PREBUILT_SHARED_LIBRARY option in .mk file: Include prebuilt shared library in Android AOSP or BUILD_PREBUILT https://stackoverflow.com/a/25682674/1028256
I have added ndk plugin in Eclipse.
I have imported a NDK project in Eclipse.
But projects requires external .h file from the system, so I have added that folder where .h files files resides by
right click on project-> c/C++ General->Paths and symbols->then click on
include and then click add and given path of that folder
also checked all configurations and all languages.
still when I build the project from Command prompt by moving to path where my project is , then ndk-build I am getting for .h file no such file or directory error.
How can I resolve this issue??
Please help...
Please refer to documentation of LOCAL_C_INCLUDES variable
what you did to add the reference the external headers was only for eclipse, so it correctly resolves all the symbols and files references.
You also need to properly add a reference to these .h inside your ndk configuration files, ie inside Android.mk.
Use LOCAL_C_INCLUDES := path/to/headers in your module, like in this sample Android.mk file:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := main.c
LOCAL_MODULE := mymodule
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../includes
include $(BUILD_SHARED_LIBRARY)
If your .h files are part of a prebuilt module your own module depends on, use LOCAL_EXPORT_C_INCLUDES inside the prebuilt module instead of LOCAL_C_INCLUDES inside yours.
In my Android NDK project, I have the following structure:
jni/
Android.mk
... (more source files)
new-lib/
Android.mk
... (more source files)
In the top level Android.mk I have include $(call all-subdir-makefiles) as the last line. I suppose now all the native codes including those under new-lib/ should get built when run ndk-build.
But when I run ndk-build command under project root path, only the top level native codes get built, the native code in subdir new-lib/ isn't built at all. Why?
I only work with one Android.mk in which I define all include folders, but I think here you'll find what you need. For what I understand, you need to make sure you are using the LOCAL_PATH in all your Android.mk files like this:
LOCAL_PATH := $(call my-dir)
I have a series of existing libraries which I need to re-use in an Android application. The layout is similar to:
\Libraries\libOne
\Libraries\libTwo [Static library]
\Libraries\libThree
\Applications\MyApplication\ [Application]
libTwo depends on libOne, and libThree depends on libTwo. How can I get the build system to build all of the libraries in the correct order? I'm trying to use Eclipse, but if necessary I can use the command line.
All of these libraries will eventually be referenced by a Java application (and use JNI to interact with them). Any clues on how I setup the Android.mk / Application.mk files?
I've tried using BUILD_STATIC_LIBRARY for libTwo, but it doesn't actually output any files! I was expecting a libTwo.a file, but nothing gets compiled or built.
Do I write one Android.mk in the application? Or an Android.mk for each project?
OK, now I see your edit, and this makes it possible to answer the specific question.
You must have at least one Android.mk file for your application if you want to use Android NDK to build your native library/ies. This is not a requirement, though. It is OK to build it though Cmake, or a "standalone toolchain" with "traditional" makefiles, or with a MS Visual Studio plugin, or any other way. It is the result that matters. The result is a shared object built with a compatible compiler for a bionic runtime.
It makes goode sense to put the library in ${project_root}/libs/armeabi/ directory (for ARM v6 compatible devices, other subdirectories for x86, MIPS, arm v7a) to allow the APK builder pack it correctly, to allow app installer to unpack the correct version (compatible with the device processor) into /data/data/${package_name}/lib directory on the device, and finally to be able to use System.loadLibrary(short_name) to use it from Java. But it is also quite possible to pack the so file differently, unpack it manually, and load it from any place on the device file system (provided your app has permission to write and read this file).
But if we filter out exotic cases, it is much more comfortable to have an Android.mk in the ${project_root}/jni directory. In terms of ndk-build command, each library is a separate MODULE, but all three may be defined in one Android.mk file. On the other hand, if your libraries are isolated (e.g. come from separate 3rd parties), you will probably prefer to create three Android.mk files. Luckily, ndk-build is nothing but a wrapper around gnu make, and the simple include statement in Android.mk works as in any other makefiles.
In summary, your case is probably covered by a simple Applications/MyApplication/ [Application]/jni/Android.mk file:
include ../../Libraries/libOne/Android.mk
include ../../Libraries/libTwo/Android.mk
include ../../Libraries/libThree/Android.mk
I don't know what dependency you have between libOne and libTwo, but for libOne the file Libraries/libOne/Android.mk will look like
LOCAL_PATH = $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libOne
LOCAL_SRC_FILES := first.c
include $(BUILD_STATIC_LIBRARY)
and Libraries/libThree/Android.mk
LOCAL_PATH = $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libThree
LOCAL_SRC_FILES := third.c
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../libOne $(LOCAL_PATH)/../libTwo
LOCAL_STATIC_LIBRARIES := libOne libTwo
include $(BUILD_SHARED_LIBRARY)
You should run ndk-build from Applications/MyApplication/ [Application] directory - either from command prompt, or through Eclipse ADT plugin.
update the same may be expressed by one Android.mk file in jni directory:
LOCAL_PATH = ../../Libraries/libOne
include $(CLEAR_VARS)
LOCAL_MODULE := libOne
LOCAL_SRC_FILES := first.c
include $(BUILD_STATIC_LIBRARY)
LOCAL_PATH = ../../Libraries/libThree
include $(CLEAR_VARS)
LOCAL_MODULE := libThree
LOCAL_SRC_FILES := third.c
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../libOne $(LOCAL_PATH)/../libTwo
LOCAL_STATIC_LIBRARIES := libOne libTwo
include $(BUILD_SHARED_LIBRARY)
There is an android section in the projects' properties, where you can edit the library dependencies. It can only be used, if libOne libTwo and libThree are marked as libraries, in their properties panel.