Newbie in Android NDK: definition in Android.mk - android

I am new in Android NDK. I know in every jni/ folder, there is Android.mk file, seems it always start with:
LOCAL_PATH := $(call my-dir)
It defines the LOCAL_PATH, but if translate it to a human-readable launguage, what is this path? Is the LOCAL_PATH points to the jni/ folder or is it the project root ?
For example, I imported an Android project which uses NDK, I checked its Android.mk file, it has something like following:
LOCAL_PATH := $(call my-dir)
...
MY_PLUGINS := XXX YYY ZZZ
MY_PATH := $(LOCAL_PATH)/other/something
Question 1, what does LOCAL_PATH := $(call my-dir) mean, what is the path it points to?
Question 2, Where can I find those MY_PLUGINS, I mean the XXX , YYY and ZZZ, at least I am not able to see it in the project I imported.
Question 3, Where can I find something defined by MYPATH ? I don't see it in project either.
P.S.: (I tried to find it under jni/other/something , but there isn't such file). By the way, what is the name of the script language used in Android.mk ?

Your best resource here is probably the NDK documentation itself. It is (unfortunately) not hosted on the web, but it is distributed with the NDK. Check the android-ndk-rX/documentation.html file in the NDK you downloaded.
Question 1: from the Android.mk File part of the doc:
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).
Question 2 and 3: these variables are not "usual" variables in an Android.mk file. They are user-defined variables, and without more details on the project you're using, it's hard to tell much about it. For all I know, MY_PATH should indeed point to jni/other/something.
Concerning your P.S., I don't think the Android.mk file is written in any particular known language: it's a custom language that has some similarities with Makefile.
Hope this helps a little!

Q - 1
Android.mk file must begin with LOCAL_PATH variable initialization.
LOCAL_PATH contains the "path to the Android.mk make file", in most case it would be present working directory.
$(call my-dir) is calling macro function "my-dir", defined in /build/core/definitions.mk, you can check the definition of the macro, It finds the directory for ndk-build script to start working.
Q - 2
Android.mk allows users to define local variables and "MY_PLUGINS" is a local variable containing list of plugins, "XXX YYY ZZZ" is list of the plugins he/she might be using within the Android.mk file.
Following are the restrictions on defining a local variable
Names that begin with LOCAL_ (e.g. LOCAL_MODULE)
Names that begin with PRIVATE_, NDK_ or APP_ (used internally)
Lower-case names (used internally, e.g. my-dir)
It is advised to use MY_ prefix for local variable definition
Q - 3
Again MY_PATH is a local variable which contains absolute path to the "/something/other" folder, now this path could contain "XXX YYY ZZZ" plugins or some other useful stuff.
Hope this helps

Related

How to use prebuilt c++ library for android ndk project

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?

Replacing some files before packaging system folder to system.img

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

Android NDK: code under sub-directory isn't built at all

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)

Android.mk relative or absolute paths?

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

How can I specify a file to be copied in an Android.mk file

Is there a macro or command to copy files? I'd like a 3rd party library (libThirdParty.so) to be copied to the output directory (lib). This is the contents of my Android.mk file
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := ndkFoo
LOCAL_SRC_FILES := ndkFoo.c
LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog
include $(BUILD_SHARED_LIBRARY)
I have a build step I added for one of my .cpp files that's generated; you could do something similar.
Note that I was told that what I was doing was Not Supported by Google, so use at your own risk. I've been using something like the code below for more than a year, though. Here's a rough idea of what it would look like:
LOCAL_PATH:= $(call my-dir)
# this was important for some cases; can't remember if it's important here, but I don't want to steer you wrong if it isn't
REAL_LOCAL_PATH:=$(LOCAL_PATH)
include $(CLEAR_VARS)
LOCAL_MODULE := ndkFoo
# again, I'm being paranoid here
REAL_LOCAL_MODULE := $(LOCAL_MODULE)
LOCAL_SRC_FILES := ndkFoo.c
$(REAL_LOCAL_PATH)/obj/local/armeabi/$(REAL_LOCAL_MODULE).so : $(REAL_LOCAL_PATH)/libs/armeabi/libThirdParty.so
$(REAL_LOCAL_PATH)/libs/armeabi/libThirdParty.so : $(PATH_TO_LIB_THIRD_PARTY)/libThirdParty.so
cp $(PATH_TO_LIB_THIRD_PARTY)/libThirdParty.so $(REAL_LOCAL_PATH)/libs/armeabi/libThirdParty.so
LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog
include $(BUILD_SHARED_LIBRARY)
Note you'll need to define PATH_TO_LIB_THIRD_PARTY.
ALSO note that copy-and-paste may or may not work. Makefiles are notoriously picky about indents. I'd make sure that the "cp" line has a real tab indent, and that nothing else is indented. If "cp" doesn't work, then make may be delegating to CMD, and you can try "copy" instead.
Good luck.
I know this thread is old, but found it while searching for something myself.
From the PowerVR SDK, Android.mk file.
You can create folders and copy files.
PVRSDKDIR := $(LOCAL_PATH)
ASSETDIR := $(PVRSDKDIR)/TrainingCourse/IntroducingPOD/OGLES2/Build/Android/assets
$(ASSETDIR):
-mkdir $(ASSETDIR)
$(ASSETDIR)/tex_base.pvr: $(ASSETDIR) $(PVRSDKDIR)/TrainingCourse/IntroducingPOD/OGLES2/tex_base.pvr
cp "$(PVRSDKDIR)/TrainingCourse/IntroducingPOD/OGLES2/tex_base.pvr" "$(ASSETDIR)/"
Google has a feature that is exactly intended for your use case: PREBUILT_SHARED_LIBRARY
If you check the documentation in the docs directory included in the NDK, you will find ANDROID-MK.html which mentions this feature briefly, and PREBUILTS.html which completely documents the feature. You can specify the source and destination directories, and you can specify a new name for the file when it is copied.
There is also PREBUILD_STATIC_LIBRARY which does the same thing for a static library.
It might be possible to trick it into copying arbitrary files... the above features are implemented by files called, respectively, prebuilt-shared-library.mk and prebuilt-static-library.mk. Inside, they define an extension that must be on the file (respectively .so and .a). You could probably make another .mk file that defined some other extension to enable copying some other kind of file. But we have only needed to copy libraries and we haven't experimented with trying to trick the build system.
P.S. This blog posting is interesting. It refers to BUILD_PREBUILT, which doesn't exist in my copy of the NDK. I wonder if this blog posting refers to an earlier version of the NDK, which had BUILD_PREBUILT to copy any kind of file (with no check for a required extension).
http://karthiksden.blogspot.com/2011/03/copying-data-files-using-androidmk.html

Categories

Resources