I am using the Android NDK to build a shared library. I have include a snippet from my Android.mk file that is causing me a few issues.
LOCAL_PATH := $(call my-dir)
..#other module here
..#other module here
include $(CLEAR_VARS)
LOCAL_MODULE := spatialite
LOCAL_C_INCLUDES := ../../../projects/externalappsdk/include
LOCAL_SRC_FILES := sqlite3.c \
spatialite.c
include $(BUILD_SHARED_LIBRARY)
My spatialite.c file includes some header files that are located in a folder that is external to the application project folder. I have included that folder in LOCAL_C_INCLUDES as shown above, but on running ndk-build, it still cannot locate these includes. What is the correct way of allowing the ndk-build command to identify where these includes are located. Any help will be greatly appreaciated.
UPDATE:
I wanted to add that spatialite itself need not be visible to the Java layer. I will thereafter be building another module which uses spatialite. I am not sure if this makes a difference to the way I declare the module on the Android.mk file.
The compiler output is shown below:
jni/spatialite.c:102:20: fatal error: geos_c.h: No such file or directory
#include
The .h file that is being imported in spatialite.c is located at C:/projects/externalappsdk/include. The spatialite.c and Android.mk are located at C:/mobile/myandroidproject/jni/
The include directive within my spatialite.c file is shown below:
#ifndef OMIT_GEOS /* including GEOS */
#include <geos_c.h>
#endif
ANSWER:
I managed to get this working using help from the answers provided by Chris which I have accepted. However, I had to make one change to the Android.mk file as is shown below:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := spatialite
LOCAL_C_INCLUDES := ../../projects/externalappsdk/include
LOCAL_SRC_FILES := sqlite3.c \
spatialite.c
include $(BUILD_SHARED_LIBRARY)
Note, that the LOCAL_C_INCLUDES goes two levels back instead of three.
Without a
LOCAL_PATH := $(call my-dir)
At the top of the Android.mk, I was unable to build a replica of your project as described, however the error was different than your report - without that directive the compiler was searching for the C source files in an NDK system directory rather in the jni/ folder.
$ cd mobile/myandroidproject/jni
$ ndk-build
Compile thumb : spatialite <= spatialite.c
SharedLibrary : libspatialite.so
Install : libspatialite.so => libs/armeabi/libspatialite.so
File: ./mobile/myandroidproject/jni/Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := spatialite
LOCAL_C_INCLUDES := ../../../projects/externalappsdk/include
LOCAL_SRC_FILES := sqlite3.c \
spatialite.c
include $(BUILD_SHARED_LIBRARY)
File: ./mobile/myandroidproject/jni/spatialite.c
#include <geos_c.h>
File: ./mobile/myandroidproject/jni/sqlite3.c
//empty file
File: ./projects/externalappsdk/include/geos_c.h
//empty file
At minimum you should add the LOCAL_PATH line to your Android.mk
If that does not solve the problem, then please update your question with any differences between your project structure and my recreation of it.
Use LOCAL_EXPORT_C_INCLUDE_DIRS instead of LOCAL_C_INCLUDES
Related
I found similar posts but often the answer are not really correct and anyways seems to be not working for me.
I have an Android application created with Android Studio which includes java-websocket library. Now, I want to build this application inside AOSP thus I created a folder for the jar library with its own Android.mk and another folder which contains the application (with Android Studio structure) which contains its own Android.mk (modified in order to find AndroidManifest, res, java, AIDL files)
At first I had some troubles due to some incorrect parameter in the Android.mk for the jar file. Now the jar file seems to be correctly recognized and the intermediates are exported to out/ folder.
The problem now is during the build of the application since the classes exposed by the jar seems to be not available ending up in:
error: cannot find symbol WebSocket
and similar errors for any reference to the jar content.
The JAR folder contains: Android.mk Java-WebSocket-1.3.0.jar
And this is the Android.mk content
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := JavaWebSocket
LOCAL_MODULE_TAGS := optional
$(warning Going to build $(LOCAL_MODULE))
LOCAL_SRC_FILES := Java-WebSocket-1.3.0.jar
LOCAL_MODULE_CLASS := JAVA_LIBRARIES
LOCAL_MODULE_SUFFIX := $(COMMON_JAVA_PACKAGE_SUFFIX)
include $(BUILD_PREBUILT)
The application folder contains: Android.mk aidl_files app gradle build.gradle ..
(basically the Android Studio project plus the Android.mk and a folder containing AIDL (which I'll move outside later)
And this is the Android.mk file content:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_PACKAGE_NAME := MyApplication
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := JavaWebSocket
LOCAL_PROGUARD_ENABLED := disabled
LOCAL_MODULE_TAGS := optional
LOCAL_CERTIFICATE := platform
LOCAL_SRC_FILES := $(call all-java-files-under, app/src/main/java) \
aidl_files/my_aidl_file.aidl
LOCAL_AIDL_INCLUDES := $(LOCAL_PATH)/aidl_files
LOCAL_RESOURCE_DIR += $(LOCAL_PATH)/app/src/main/res
LOCAL_MANIFEST_FILE := app/src/main/AndroidManifest.xml
LOCAL_PRIVATE_PLATFORM_APIS := true
LOCAL_STATIC_ANDROID_LIBRARIES += \
androidx.appcompat_appcompat
include $(BUILD_PACKAGE)
I tried to merge all the informations I found in StackOverflow so far without success.
Is there any other LOCAL_something that I should set?
I have some cpp files in a directory (10 cpp files and ten relatives .h files corresponding to 10 classes).
I would like to create my own library with them (let call it libTest.a) in order to put it on an android project using NDK.
I have already :
C++ code
Create and configure the android project with NDK, so basically I have an Android.mk and a cpp file into the jni folder
I spent about 10 hours on the web trying to find someone who can explain how to compile its own lib.a
I found a lot about "how can I put a .a in an android project using ndk" but nothing about how to create a makefile, a config file or whatever in order to correctly compile and make a lib compatible with android.
The one who will give me some advices will made my day!
Thanks a lot
(My Android.mk below)
LOCAL_PATH := $(call my-dir)
# static library info
LOCAL_MODULE := libTest
LOCAL_SRC_FILES := ../prebuild/libTest.a
LOCAL_EXPORT_C_INCLUDES := ../prebuild/include
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_C_INCLUDES += ../prebuild/include
LOCAL_MODULE := mlaudioengine
LOCAL_SRC_FILES := mlaudioengine.cpp
LOCAL_STATIC_LIBRARIES := libTest
include $(BUILD_SHARED_LIBRARY)
In Android in the Application i want to import one android.mk file into another Android.mk file in the Application
for this i have used in one Andorid.mk file which is to be imported into another module of same project
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := EDSDKModule
LOCAL_SRC_FILES :=libEDSDK.a
LOCAL_ARM_MODE := arm
TARGET_PLATFORM:=android-8
TARGET_ARCH_ABI:=armeabi
TARGET_ABI:=$(TARGET_PLATFORM)-$(TARGET_ARCH_ABI)
include $(PREBUILT_STATIC_LIBRARY)
and main Andorid.mk file is written is
include C:\my_module\Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := EDSK
LOCAL_MODULE_FILENAME := foo
LOCAL_SRC_FILES := sample.c
LOCAL_STATIC_LIBRARIES := EDSDKModule
include $(BUILD_SHARED_LIBRARY)
LOCAL_ARM_MODE := arm
TARGET_PLATFORM:=android-8
TARGET_ARCH_ABI:=armeabi
TARGET_ABI:=$(TARGET_PLATFORM)-$(TARGET_ARCH_ABI)
$(call import-module,EDSDKModule)
but i have got this error on building project using Android-NDk i.e
please suggest some solutions on how to import one module into another module of android.mk file in a project
I am guessing the problem is here :
$NDK_MODULE_PATH\C:\Final FOlder\final c\Mysetup\newworks\SimpleApp\jni\path1\Android.mk:
/*here i have given directory path of android.mk file */
Possible mistakes :
Try to get rid of the empty spaces in the path :
C:\Final FOlder\final c\
to something like this :
C:\FInal_Folder\final_c\myotherdir\xyz.mk
If you are using a absolute path like :
C:\mypath\myotherdir\xyz.mk
then you NEED NOT prefix it with $NDK_MODULE_PATH. Just use the above absolute path itself, which is C:\mypath\myotherdir\xyz.mk
You need an include keyword infront of your above include statement :
# comment : including my mk file here
include C:\mypath\myotherdir\xyz.mk
Get rid of the : in the end of your include statement
So you have to do something like :
include C:\mypath\myotherdir\xyz.mk
OR
If you have the mk file in NDK LOCAL FOLDER then
include $NDK_MODULE_PATH\mylocaldir\xyz.mk
Hope this helps. CHeers!
Here I used this Android.mk file in jni/ folder.
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# Here we give our module name and source file(s)
LOCAL_MODULE := offlineDownload
LOCAL_SRC_FILES := offline_download.c
LOCAL_SHARED_LIBRARIES :=../lib/libpackext.so.1.0
LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog
include $(BUILD_SHARED_LIBRARY)
And make one lib folder in project directory and put my prebuilt .so library and make one Android.mk file which contains following
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := packext
LOCAL_SRC_FILES := libpackext.so.1.0
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../include
include $(PREBUILT_SHARED_LIBRARY)
And when i use ndk-build -B command than i got undefined reference to packageExtraction. Here I use my prebuilt library functions means I can't link my prebuilt shared library to my offlinedownload library.
So any body please help me to solved out this issue.
Here is a complete Android.mk file for using a 3rd party shared library.
The library (libffmpeg.so) is placed in the jni folder.
Its "LOCAL_EXPORT_C_INCLUDES" specifies where the header files are kept for the library.
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := ffmpeg
LOCAL_SRC_FILES := libffmpeg.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/../../ffmpeg/libs/arm-linux-androideabi4.7_1/include
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := ffmpegandroid
LOCAL_SRC_FILES := ffmpegandroid.c
LOCAL_SHARED_LIBRARIES := ffmpeg
include $(BUILD_SHARED_LIBRARY)
If you wanted to support multiple architectures then you could specify:
APP_ABI := armeabi armeabi-v7a x86 mips
in your jni/Application.mk and change the LOCAL_SRC_FILES to something like:
LOCAL_SRC_FILES := $(TARGET_ARCH_ABI)/libffmpeg.so
and place a libffmpeg.so at jni/armeabi/libffmpeg.so, jni/armeabi-v7a/libffmpeg.so etc ..
Android NDK official hello-libs CMake example
https://github.com/googlesamples/android-ndk/tree/840858984e1bb8a7fab37c1b7c571efbe7d6eb75/hello-libs
Just worked for me on Ubuntu 17.10 host, Android Studio 3, Android SDK 26, NDK 15.2. so I strongly recommend that you base your project on it.
The shared library is called libgperf, the key code parts are:
hello-libs/app/src/main/cpp/CMakeLists.txt:
// -L
add_library(lib_gperf SHARED IMPORTED)
set_target_properties(lib_gperf PROPERTIES IMPORTED_LOCATION
${distribution_DIR}/gperf/lib/${ANDROID_ABI}/libgperf.so)
// -I
target_include_directories(hello-libs PRIVATE
${distribution_DIR}/gperf/include)
// -lgperf
target_link_libraries(hello-libs
lib_gperf)
on C++ code, use: #include <gperf.h>
header location: hello-libs/distribution/gperf/include/gperf.h
lib location: distribution/gperf/lib/arm64-v8a/libgperf.so
app/build.gradle:
android {
sourceSets {
main {
// let gradle pack the shared library into apk
jniLibs.srcDirs = ['../distribution/gperf/lib']
Then, if you look under /data/app on the device, libgperf.so will be there as well.
If you only support some architectures, see: Gradle Build NDK target only ARM
The example git tracks the prebuilt shared libraries, but it also contains the build system to actually build them as well: https://github.com/googlesamples/android-ndk/tree/840858984e1bb8a7fab37c1b7c571efbe7d6eb75/hello-libs/gen-libs
You have to do either one of the following:
Cut and paste everything except LOCAL_PATH := $(call my-dir) from your second Android.mk into your first.
Put the following in the end of your first Android.mk:
$(call import-module,packext)
Also make sure that you set your NDK_MODULE_PATH environment variable to a path where the Android.mk-file defining the module packext can be found.
You also have to change the LOCAL_SHARED_LIBRARIES in the same way mgiza said in the first answer. I suppose the packageExtraction that you got undefined reference to is in your prebuilt library so unless you have other linking problems this should solve the issue.
Have a look at the ndk documentation for prebuilts:
android-ndk/docs/PREBUILTS.html
You have to change
LOCAL_SHARED_LIBRARIES :=../lib/libpackext.so.1.0
to
LOCAL_SHARED_LIBRARIES := packext
Be sure that your folder containing the Android.mk for the packext module is named packext and can be found in in your NDK_MODULE_PATH.
I'm having a problem using Make's wildcard function in my Android.mk build file.
My other makefiles use a line like this one to specify "All .c files in this folder":
CFILES := $(wildcard *.c)
In my Android.mk file I tried this:
LOCAL_SRC_FILES := $(wildcard *.c)
However, this has the same affect as not including any files at all.
If I include the files manually the build works as I'd expect.
I'm wondering if maybe the current working directory isn't my project path at the time this statement is evaluated? If so, can I use a combination of $(call my-dir) and the wildcard function to get the list I want?
Here's what I've used in the past for doing this:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := mylibrary
LOCAL_SRC_FILES := $(wildcard $(LOCAL_PATH)/*.c)
include $(BUILD_STATIC_LIBRARY)
'my-dir' is a macro provided by the build system and returns the path of the directory containing the Android.mk file.
If your definition of "this directory" is "the directory containing this makefile", then
$(wildcard $(dir $(lastword $(MAKEFILE_LIST)))*.c)
ought to work.
(caveat: I don't know from Android)