I tried to add a prebuilt APK to my Android build. The APK contains several shared libraries (*.so files). It compiles without problem, but I still get an error from the app indicating that the libraries cannot be found.
Why could this be?
Here is the android.mk code:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := apkwithso
LOCAL_SRC_FILES := $(LOCAL_MODULE).apk
LOCAL_REQUIRED_MODULES := libx liby libz
LOCAL_MODULE_CLASS := APPS
LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
LOCAL_CERTIFICATE := PRESIGNED
include $(BUILD_PREBUILT)
libx, y, z are my libx.so, liby.so, and libz.so
I also tried to copy the .so manually from the APK to the out lib directories but it didn't work.
I am compiling with Android 4.1.2 for Galaxy Nexus Maguro.
I've had this problem myself, the reason is that when APK files are included in a build they are essentially bypassing the installation process. This installation process is the point at which any shared libraries are extracted from the apk and put in the appropriate place, ergo if that never happens the libraries will not be available. This is because packages that are built from source during the AOSP build either have their prebuilt shared libraries included during that build process or their libraries are also built from source, and in either case those libraries are put in the appropriate place.
For this reason in addition to the apk module itself you should add the following in the same .mk file:
include $(CLEAR_VARS)
LOCAL_MODULE := libapkwithso
LOCAL_SRC_FILES := lib/libapkwithso.so # or wherever your so is
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_SUFFIX := .so
LOCAL_MODULE_CLASS := SHARED_LIBRARIES
include $(BUILD_PREBUILT)
Then add:
LOCAL_REQUIRED_MODULES := libapkwithso
BUILD_PREBUILT calls prebuild.mk script. The description of this script is the following:
Standard rules for copying files that are prebuilt
It does not tell that the application will be installed. So I think that is why your application cannot find the libraries.
The solution is to extract libraries from the package and copy them separately from the application. The details how to do this you can find here.
Files can also be be specified in aospSource:destinationOnImage format like this in the device-partial.mk when adding a custom vendor directory:
PRODUCT_COPY_FILES += \
vendor/your-custom-vendor/your-device/proprietary/libx.so:system/lib/libx.so
You can add pretty much anything you like here (other than .apk files), and it will be copied to your image.
My Instructions is not about your error! But it may be helpful for similar error
If you try to copy prebuilt apk using:
PRODUCT_COPY_FILES += $(LOCAL_PATH)/prebuilt/filename.apk
and you getting this error:
Prebuilt apk found in PRODUCT_COPY_FILES: ... , use BUILD_PREBUILT instead!. Stop.
You can remove this check my modify the file build/core/MakeFile and comment this lines:
define check-product-copy-files
$(if $(filter %.apk, $(call word-colon, 2, $(1))),$(error \
Prebuilt apk found in PRODUCT_COPY_FILES: $(1), use BUILD_PREBUILT instead!))
endef
by inserting # before each line
Too add multiple libraries to one apk one additional section (as in answer of Justin Buser) should be added for each separate library.
Related
I've made a couple attempts to add a single shared object library to an Android 10 build by adapting older instructions here and here.
I added a directory containing the library under /device/vendor/name/ and an Android.mk file using the two-target example.
They have all lead back to the same error:
build/make/core/base_rules.mk:480: error: writing to readonly directory: "system/lib64/libjni_latinimegoogle.so"
Is there a correct/accepted way to do this for 10? Thanks
edit: Android.mk file contents
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libjni_latinimegoogle
LOCAL_MODULE_SUFFIX := .so
LOCAL_MODULE_CLASS := SHARED_LIBRARIES
LOCAL_MODULE_TAGS := optional
LOCAL_PRELINK_MODULE := false
ifdef TARGET_2ND_ARCH
LOCAL_MULTILIB := both
LOCAL_MODULE_PATH_64 := system/lib64
LOCAL_SRC_FILES_64 := system/lib64/libjni_latinimegoogle.so
LOCAL_MODULE_PATH_32 := system/lib
LOCAL_SRC_FILES_32 := system/lib/libjni_latinimegoogle.so
else
LOCAL_MODULE_PATH := system/lib64
LOCAL_SRC_FILES := system/lib64/libjni_latinimegoogle.so
endif
include $(BUILD_PREBUILT)
The problem is with using kati.
This occurs when you try to generate build output outside of out/. Or, in the case of the kernel, if you use absolute paths for the build target. The kernel part is not in your focus, but someone might need this information.
Therefore, your LOCAL_MODULE_PATH is pointing to invalid location.
The correct way is to specify in the device makefile. The goal was to add gesture typing to a LineageOS 17.1 build - using the Pixel 3XL crosshatch as an example:
in vendor/google/crosshatch/crosshatch-vendor.mk under PRODUCT_COPY_FILES, add the row to copy the .so library similar to the ones around it, under lib64 (or lib for 32 bit device builds):
PRODUCT_COPY_FILES += \
...
vendor/google/crosshatch/proprietary/lib64/libjni_latinimegoogle.so:$(TARGET_COPY_OUT_SYSTEM)/lib64/libjni_latinimegoogle.so \
...
TARGET_COPY_OUT_SYSTEM will direct it to the system partition vs PRODUCT, SYSTEM_EXT, or VENDOR which are also options.
Finally make sure to add the .so file where it needs to be copied from locally, under vendor/google/crosshatch/proprietary/lib64
Gesture typing will be enabled in the next build. This is also working with LineageOS 18.1
I have an APK that contains java code and some .so files. I have built the APK in Android Studio and now this APK needs to be part of /system/app/ folder on my custom ROM.
Java code + .so = APK
To include it in system/app/, I am having the below build script in Android.mk file and calling it from device.mk file.
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := utility
LOCAL_MODULE_CLASS := APPS
LOCAL_CERTIFICATE := platform
LOCAL_SRC_FILES := utility.apk
include $(BUILD_PREBUILT)
After building the image, I find my APK crashing, and the log says "Cannot link executable" and all .so files seeems to be missing.
However, the APK works if I use adb install utility.apk.
Can someone tell me what is that I am missing in the buildscript that is causing .so files not being available.
P.S.: I searched inside /data/data/com.org.utility/, /system/lib/ folders, but no .so files were found.
But if I use adb install, .so files are found inside /data/data/com.org.utility/lib/x86/ folder.
I don't remember in L or M, there is a bug in the build system.
The so in the apk which is built into system/app or system/priv-app cannot release into the system. But the third party app can release there libs by PackageManagerService.
One solution:
1. Released the so in the apk manually.
2. Add so related to the Android.mk, for example:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := test
LOCAL_SRC_FILES := libtest.so
include $(PREBUILT_SHARED_LIBRARY)
Add this module name to PRODUC_PACKAGES micro.
These so in your app will be built to your system/lib or lib64.
Good luck.
I have an NDK project where I build the shared libraries using the cross-compiler and standard gnu make utils. That is done with a separate script. But for the purpose of using the libraries in my project, I would like my Android.mk process to call my script to generate the shared library if it hasn't already been built, and then have Android.mk wrap it using the PREBUILT_SHARED_LIBRARY process.
Currently, if I run my script offline to generate libmy_so.so, then the following makefile will work. However, if I don't run the script explicitly first, I get the following error:
Android NDK: ERROR:/path_to_project/Android.mk:my_module: LOCAL_SRC_FILES points to a missing file
and my script is never called, so the make process is failing before even trying to resolve the dependency.
include $(CLEAR_VARS)
LOCAL_MODULE := my_module
LOCAL_SRC_FILES := libmy_so.so
LOCAL_EXPORT_CFLAGS := # some stuff
LOCAL_EXPORT_LDLIBS := # some stuff
$(LOCAL_PATH)/libmy_so.so:
echo "generate file"
$(shell run_script_that_creates_libmy_so.so)
include $(PREBUILT_SHARED_LIBRARY)
Is there a clean solution to this? I am even ok with running the script automatically as a preprocessing step (I can always have my script quietly exit if the file exists already), but I have not found an incantation that allows the LOCAL_SRC_FILES variable to point to a non-existent file. I have considered placing a dummy libmy_so.so to start, but that is an ugly hack.
Found a hack -- better way?
I found a hack. The makefile prebuilt-library.mk in the NDK contains the following lines:
ifndef prebuilt
$(call __ndk_info,ERROR:$(LOCAL_MAKEFILE):$(LOCAL_MODULE): LOCAL_SRC_FILES points to a missing file)
$(call __ndk_info,Check that $(prebuilt_path) exists, or that its path is correct)
$(call __ndk_error,Aborting)
#endif
I created a copy of this file (and prebuilt-shared-library.mk to which I reference my copy of prebuilt-library.mk) and commented those lines out to stop the error. Then the trick is to make some target that is evaluated first depend on the file I want to generate. After digging through the .mk scripts in the NDK, I found that libraries serves the purpose. By adding libraries: $(LOCAL_PATH)/libmy_so.so to Android.mk, it will finally do what I want.
include $(CLEAR_VARS)
LOCAL_MODULE := my_module
LOCAL_SRC_FILES := libmy_so.so
LOCAL_EXPORT_CFLAGS := # some stuff
LOCAL_EXPORT_LDLIBS := # some stuff
$(LOCAL_PATH)/libmy_so.so:
echo "generate file"
$(shell run_script_that_creates_libmy_so.so)
libraries: $(LOCAL_PATH)/libmy_so.so
include /path/to/my/mk/files/prebuilt-shared-library.mk
This is obviously less than ideal as I would like to make sure my makefiles mature with newer versions of the NDK, but it does the trick. Still interested in more elegant solutions.
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.
I am trying to build a custom rom using android custom build project. I want to add one android application to it in which there is one external jar. But whenever I run 'mm' (i.e make) in /package/apps/myApp it gives error 41 in which it is not able to recognize classes and functions from that external jar. Although eclipse is recognizing that jar and app is running perfect in eclipse but 'mm' is not able to compile it. What should i do?
Any help is greatly appreciated.
Refer to the Android.mk file inside the Calculator app. It uses external jars.
I am also pasting a sample mk file that i used for my own app. You can use it:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_TAGS := tests
LOCAL_STATIC_JAVA_LIBRARIES := libguava libgcm android-support-v4
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_SDK_VERSION := current
LOCAL_PACKAGE_NAME := SampleApp
include $(BUILD_PACKAGE)
include $(CLEAR_VARS)
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := libguava:guava-11.0.jar libgcm:gcm.jar
include $(BUILD_MULTI_PREBUILT)
include $(call all-makefiles-under,$(LOCAL_PATH)
libguava and libgcm are just two namespaces(You can use your own names) for the two jars:guava-11.0.jar and gcm.jar(I have used these jars in my project) respectively. I have kept the jars inside the project folder. If you have kept the jars inside libs folder use libguava:libs/guava-11.0.jar.Also, don't use mm. Use make, but don't do make clean before it else it will remove the entire build directory and start from scratch(take a lot of time) Please accept as solution if it works....Thanks