I need a little help with Android makefiles.
There is one common module for 2 of my applications. I planned to have a makefile for common modulecommon.mk and include it in both my applications.
Like this:
app1:
=====
main.c
Android.mk
...
...
include ../common/common.mk
LOCAL_MODULE := app1
...
...
app2:
=====
main.c
Android.mk
...
...
include ../common/common.mk
LOCAL_MODULE := app2
...
...
common:
=======
common.mk
common.c
when I build from root directory using make app2, I am receiving multiple definition errors for all the functions that are apart of common module.
I came to a conclusion that the common.mk is getting included twice while the Android build system is searching for the right target(app2 in my case). Which is why the problem is occurring.
Now how do I control this? What is the standard way in Android?
A correct way should be to build a common library (shared or static) by using the BUILD_SHARED_LIBRARY or BUILD_STATIC_LIBRARY targets.
And then to add them into app1 and app2 just use the LOCAL_STATIC_LIBRARIES or LOCAL_SHARED_LIBRARIES to create a dependency between app1, app2 and common.
Check the Android.mk file syntax specification for more informations:
BUILD_SHARED_LIBRARY
Points to a build script that collects all the information about the module you provided in LOCAL_XXX variables and determines how to build a target shared library from the sources you listed. Note that you must have LOCAL_MODULE and LOCAL_SRC_FILES defined, at a minimum before including this file.
Example usage:
include $(BUILD_SHARED_LIBRARY)
Note that this will generate a file named lib$(LOCAL_MODULE).so
BUILD_STATIC_LIBRARY
A variant of BUILD_SHARED_LIBRARY that is used to build a target static library instead. Static libraries are not copied into your project/packages but can be used to build shared libraries (see LOCAL_STATIC_LIBRARIES and LOCAL_WHOLE_STATIC_LIBRARIES described below).
Example usage:
include $(BUILD_STATIC_LIBRARY)
Note that this will generate a file named lib$(LOCAL_MODULE).a
LOCAL_STATIC_LIBRARIES
The list of static libraries modules (built with BUILD_STATIC_LIBRARY) that should be linked to this module. This only makes sense in shared library modules.
LOCAL_SHARED_LIBRARIES
The list of shared libraries modules this module depends on at runtime. This is necessary at link time and to embed the corresponding information in the generated file.
In common.mk the variable which you are using for assigning C files use := instead of +=.
Whenever common.mk is called it will assign independent value of each module
Related
I'm struggling with this for several days now. At the moment i'm just testing it with a simple C++ project (1 .h & 1 .cpp file) and a minimalistic App including the ndk helloJNI sample code (which worked perfect easily):
Target
Import existing C/C++ files (project) to Android Studio
Approach
After trying out some of the (dozens) of different possibilities, i think/thought the following steps would be the best solution for my purpose:
Create the shared library (Calculator.so) from Visual Studios 2015 "Create shared library for Android" (or something) [successful]
Create jniLibs folder in src/main/ with its subfolders (x86 the relevant one in my case)
Add the Android.mk file in src/main/jniLibs which has to be placed there (?)
Include statement: System.loadLibrary("Calculator") without "lib" and ".so" in MainActivity
The library is listed in Android Studio in its folder jniLibs as like the Android.mk. Moreover if i build the apk, the library is successfully packed (verified by unzipping) and i dont get any errors.
BUT: how can i call the methods in the library? I tried the different solutions offered in other threads, but i think i missed something in my .mk or my steps described above.
Tried
Different #include <myLib> statements in native-lib.cpp, like s
Different Android.mk settings (but i'm new to make files so not even tutorials helped me much with my specific problem ::) )
Other locations for the libCalculator.so like in the subfolder x86
and many others - simply not reminding atm (wasntme)
Your help is highly appreciated!
Android.mk
LOCAL_PATH := $(call my-dir)
APP_ABI := x86
# library info
include $(CLEAR_VARS)
LOCAL_MODULE := Calculator
LOCAL_SRC_FILES := $(TARGET_ARCH_ABI)/Calculator.so
LOCAL_EXPORT_C_INCLUDES := ..../Visual Studio 2015/Projects/SO_Library/SO_Library
include $(BUILD_SHARED_LIBRARY)
There are lots of things, you can do in Android NDK. For example, Camera hardware is one of the heaviest hardware in Android OS. Detecting faces, things, giving effects and for thousands of features NDK is the best.
Some helps for your steps:
You can built and prebuilt shared(.so) and static(.a) libraries in Android Studio also. Not need Visual Studio.
Don't create jniLibs folder in main folder. When you build your project via gradle, it already creates this folder and put your target libraries. If you want prebuilt any libraries, put these libraries in main/jni/libs folder and prebuilt then with Android.mk.
Don't add the Android.mk file in jnilibs folder. Create this file in main/jni folder. Also Application.mk file.
Call your libraries, in any activity, where you need, in static method. Like this:
static { System.loadLibrary("my_library") }
Without "lib" and ".so" extensions.
When you want to call your native methods, just use "native" keyword. For example:
private native int nGetNumberFromNativeSide();
Just call this method, where you want, and get result. But for ndk building in gradle side, look at this answer. For building library in Android.mk, these sample lines maybe help you:
include $(CLEAR_VARS)
ifneq (,$(filter $(TARGET_ARCH_ABI), armeabi-v7a x86 arm64-v8a x86_64))
LOCAL_MODULE := my_library
LOCAL_SRC_FILES := $(LOCAL_SRC_LOCATION)/native1.cpp native2.cpp
include $(BUILD_SHARED_LIBRARY)
You can put name anything you want, but dont add lib and .so extensions. Ndk is already doing it.
I have already gave Android.mk example.
When you build Android.mk file, it locates your libraries appropriate folder. Like main/libs/x86/libmy_library.so.
I guess this answer will help you. If you have more questions, add to comment, i'll edit my answer and add answers.
libcocos2dcpp.so is located at path proj.android\libs\armeabi
1) I want to learn to modify how it looks after changing the name "libcocos2dcpp.so" to some "randomname.so"
(Intention being, not sure but it might help in protecting my game's source code if people won't know in which thing it is made, I mean cpp because libcocos2dcpp.so has cpp in its end)
2) Also, is this libcocos2dcpp.so created newly every time I build my code or does it remains same through its entire life time?
You can change your lib name by using LOCAL_MODULE_FILENAME in the Android.mk file . According to ANDROID-MK document under Android-NDK folder:
LOCAL_MODULE_FILENAME
This variable is optional, and allows you to redefine the name of
generated files. By default, module <foo> will always generate a
static library named lib<foo>.a or a shared library named lib<foo>.so,
which are standard Unix conventions.
You can override this by defining LOCAL_MODULE_FILENAME, For example:
LOCAL_MODULE := foo-version-1
LOCAL_MODULE_FILENAME := libfoo
NOTE: You should not put a path or file extension in your
LOCAL_MODULE_FILENAME, these will be handled automatically by the
build system.
You can just rename your lib file name as
LOCAL_MODULE := randomname
LOCAL_MODULE_FILENAME := librandomname
so the build system will automatically build the lib as librandomname.so.
And don't forget to change the code in Android Activity:
static {
System.loadLibrary("randomname");
}
I'm having trouble refactoring some make files into manageable modules.
Following is the structure I try to accomplish:
jni/Android.mk
jni/Application.mk
jni/libobj/Android.mk
jni/libpng/Android.mk
jni/libzip/Android.mk
jni/freetype/Android.mk
jni/ftgles/Android.mk
jni/qcar/Android.mk
jni/imagetargets/Android.mk
Note: I started from the Vuforia SDK ImageTargets example and added
some other libraries like reading OBJ, PNG and ZIP files. I've also
included the freetype and ftgles library.
I call the other make files from my the root Android.mk file
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
include jni/libobj/Android.mk
include jni/libpng/Android.mk
include jni/libzip/Android.mk
include jni/freetype/Android.mk
include jni/ftgles/Android.mk
include jni/qcar/Android.mk
include jni/imagetargets/Android.mk
You can see all make files in a gist on github.
The compiler gives following error:
Install : libFTGLES.so => libs/armeabi/libFTGLES.so Compile++
arm : ImageTargets <= ImageTargets.cpp
jni/imagetargets/ImageTargets.cpp:44:24: fatal error: libpng/png.h: No
such file or directory compilation terminated. make: *
[obj/local/armeabi/objs/ImageTargets/ImageTargets.o] Error 1
Any idea how to make the libpng (and other modules) headers available for the imagetargets module?
I think that specifying the path to the includes in each sub-makefile using LOCAL_EXPORT_C_INCLUDES would ensure that the headers are available when building the final module.
Check the documentation for this flag in the NDK documentation (available in your NDK directory), but from what I understand, it will do exactly what you're trying to do: automatically export the include path of each sub-module to the final module.
I have started developing a very simple Android application that consists of three parts:
the Java application itself
a pre-built shared library (we'll call it libfoo)
another shared library that uses the pre-built library (we'll call it libfoowrapper)
The file system looks something like this:
jni
Android.mk
libfoo.so
foowrapper.c
The Android.mk file contains the following contents:
LOCAL_PATH := $(call my-dir)
#==============================
include $(CLEAR_VARS)
LOCAL_MODULE := foo-prebuilt
LOCAL_SRC_FILES := libfoo.so
include $(PREBUILT_SHARED_LIBRARY)
#=========================
include $(CLEAR_VARS)
LOCAL_MODULE := foowrapper
LOCAL_SRC_FILES := foowrapper.c
LOCAL_SHARED_LIBRARIES := foo-prebuilt
include $(BUILD_SHARED_LIBRARY)
When I build the application in Eclipse, things seem to work fine - no errors are reported. However, when I upload the application to my Samsung Discover (running Android 4.0.4), I get the following error in the log:
03-05 21:20:27.859: E/AndroidRuntime(20324): Caused by: java.lang.UnsatisfiedLinkError: Cannot load library: link_image[1936]: 102 could not load needed library 'libfoo.so.0' for 'libfoowrapper.so' (load_library[1091]: Library 'libfoo.so.0' not found)
Why is the Dalvik looking for a .so.0 file instead of a .so file? What changes do I need to make to my app to get rid of this error?
At least in the Linux world, every shared library has a special name called the soname. The soname has the prefix lib, the name of the library, the phrase .so, followed by a period and a version number that is incremented whenever the interface changes (as a special exception, the lowest-level C libraries don't start with lib). A fully-qualified soname includes as a prefix the directory it's in; on a working system a fully-qualified soname is simply a symbolic link to the shared library's real name.
Every shared library also has a real name, which is the filename containing the actual library code. The real name adds to the soname a period, a minor number, another period, and the release number. The last period and release number are optional. The minor number and release number support configuration control by letting you know exactly what version(s) of the library are installed. Note that these numbers might not be the same as the numbers used to describe the library in documentation, although that does make things easier.
Reference: Linux Standard Base
Edit:
It seems this is not an uncommon problem, haven't seen any real solutions to it, but perhaps this will get you started to finding something that works for you.
Problem with LOCAL_SRC_FILES when using PREBUILT_SHARED_LIBRARY
https://groups.google.com/forum/#!topic/android-ndk/_UhNpRJlA1k
Creating non-versioned shared libraries for android
http://www.opengis.ch/2011/11/23/creating-non-versioned-shared-libraries-for-android/
Library 'libproj.so.0' not found
https://groups.google.com/forum/?fromgroups=#!topic/android-ndk/ai3tu0XXs88
I want to create a Player which uses Android system/lib/libmedia.so.
Directly use JNI to play a video.
In Android.mk, i add "-lmedia" for including the library, but i can't link this directly.
This is my process.
write a Cpp file which includes some header file in libmedia.so
add "-lmedia" in Android.mk of LOCAL_LDLIBS
such as..
LOCAL_LDLIBS -lmedia -lstagefright
use ndk-build to build .so
error occured!!
Does anybody have some answer to help???
libmedia.so and libsinstructionght.so are not part of the public API. This means that in theory, you should not rely on them. In practice, though, these libraries are present on all devices, but they are different.
You can extract this binary file from your device, or even from an emulator using command
adb pull /system/lib/libmedia.so C:/android-ndk/platforms/android-14/arch-arm/usr/lib
This will put ths file together with the public API so that using it with ndk-build is easier. On the other hand, you should be aware of fragmentation not lnly between different levels of Android, but also chipsets, manufacturers, and even models.
To handle this, I pull .so files from different devices into separate directories, and add one of them to the linker path, e.g.
LOCAL_LDLIBS += -Lc:/android/galaxys.4.1.2.system.lib
This instruction above can not resolve the big problem you are facing with your approach. libmedia.so is not intended to be linked to user apps. It assumes the context of a privileged user with access to protected devices, such as camera, codecs, and screen.
You can make full use of this library if you target a rooted device, or prepare a custom ROM. And know what you are doing, and how to avoid stealing essential resources from the system.
Otherwise there is very little gain in linking the media lib.
PREBUILT_SHARED_LIBRARY
Points to a build script used to specify a prebuilt shared library.
Unlike BUILD_SHARED_LIBRARY and BUILD_STATIC_LIBRARY, the value
of LOCAL_SRC_FILES must be a single path to a prebuilt shared
library (e.g. foo/libfoo.so), instead of a source file.
You can reference the prebuilt library in another module using
the LOCAL_PREBUILTS variable (see docs/PREBUILTS.html for more
information).
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := foo-prebuilt
LOCAL_SRC_FILES := libfoo.so
include $(PREBUILT_SHARED_LIBRARY)
Refrenced from NDK documentation.
PREBUILT_STATIC_LIBRARY
This is the same as PREBUILT_SHARED_LIBRARY, but for a static library
file instead. See docs/PREBUILTS.html for more.
Please read the NDK documentation for more details.