How to compile a static library using the Android NDK? - android

I'm trying to compile a static library to use on Android but I can't figure out how to compile it. The library uses standard libraries (stdio.h etc...) and libxml2.
I am trying to compile using arm-eabi-gcc but I get the following error:
/cygdrive/c/android-ndk-r4/build/platforms/android-8/arch-x86/usr/include/asm/posix_types.h:15:28: error: posix_types_64.h: No such file or directory
How do I get this to work?

As I understand it, the correct method is to use ndk-build and not invoking the compiler directly.
In Android.mk you need to specify a module for each static library you want to compile, and then specify that your shared library should use it.
Example of a modified Android.mk file of the hello-jni sample project:
LOCAL_PATH := $(call my-dir)
# Define vars for library that will be build statically.
include $(CLEAR_VARS)
LOCAL_MODULE := <module_name>
LOCAL_C_INCLUDES := <header_files_path>
LOCAL_SRC_FILES := <list_of_src_files>
# Optional compiler flags.
LOCAL_LDLIBS = -lz -lm
LOCAL_CFLAGS = -Wall -pedantic -std=c99 -g
include $(BUILD_STATIC_LIBRARY)
# First lib, which will be built statically.
include $(CLEAR_VARS)
LOCAL_MODULE := hello-jni
LOCAL_STATIC_LIBRARIES := <module_name>
LOCAL_C_INCLUDES := <header_files_path>
LOCAL_SRC_FILES := hello-jni.c
include $(BUILD_SHARED_LIBRARY)
If you want control over which modules to compile when you run ndk-build you can create create a Application.mk file (in the same directory as Android.mk) and list all the modules as in the following example:
APP_MODULES := <module_name_1> <module_name_2> ... <module_name_n>

In response to
Can you generate a static library (.a file) without a shared library
that uses it?
(which really should have been its own question), the answer is yes.
By default, the NDK will only build executables and shared libraries (with their dependencies of course). You can, however, force the NDK to build a standalone static library by explicitly referencing it in your Application.mk.
Assuming your static library module is LOCAL_MODULE := libXYZ, add the following line to Application.mk (creating the file in the same folder as your Android.mk if it doesn't exist):
APP_MODULES := XYZ
Note the the APP_MODULES value does not include the lib prefix included in your static library module name.
Alternatively, if you don't want to create an Application.mk, you can specify the value on the command line: ndk-build APP_MODULES=XYZ

A cool trick: if you have an Android.mk file, you can change the build type from:
include $(BUILD_SHARED_LIBRARY)
to
include $(BUILD_STATIC_LIBRARY)
and .a libraries will be output to the obj/ folder into their respective architectures when you ndk-build the library.

Related

How to include constraint layout library in an AOSP project

I have an existing android application that I'd like to build inside AOSP (android source tree) using Android.mk. The app uses constraint layout which is not included in AOSP source tree (AFAIK).
How can I satisfy this dependency? Other support libs are included such as recyclerview, v4 etc but not contraint layout.
Should I download the lib aar and if yes , how do I add/include it?
Or should I get the source (where to download?) and build it somewhere in the source tree?
Thanks in advance for any help.
There are several ways to resolve your issue.
1. Add a prebuilt .apk
You don't have to put your source code to the AOSP tree.
You can just add your .apk file, put it either in packages/apps/YourApp, or vendor/yourname/packages/apps/YourApp, or even your_dir_name/packages/apps/YourApp, and create an Android.mk file for build system to determine your application.
Android.mk will look like:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := YourApplication # your .apk name
LOCAL_SRC_FILES := $(LOCAL_MODULE).apk
LOCAL_MODULE_CLASS := APPS
LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
include $(BUILD_PREBUILT)
Pros: you can build your project with gradle.
2. Add source code to AOSP
If you still want to place your source code to packages/apps and build it there, you can put a ConstrainsLayout to your project's libs/ directory and add to your Android.mk something like:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# List of static libraries to include in the package
LOCAL_STATIC_JAVA_LIBRARIES := constraint-layout
# Build all java files in the java subdirectory
LOCAL_SRC_FILES := $(call all-subdir-java-files)
# Name of the APK
LOCAL_PACKAGE_NAME := YourApplication
# Tell it to build an APK
include $(BUILD_PACKAGE)
In case you will not get it work (I haven't met this issue, but he did):
LOCAL_STATIC_JAVA_LIBRARIES := libconstraint-layout
include $(BUILD_PACKAGE)
Other stuff, and finally
include $(CLEAR_VARS)
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := libconstraint-layout:libs/constraint-layout.aar
Cons: You will have to build your code either with make by mma or mm -B, or to have a gradle as your second build system for development. The second option will work, but to establish a full build and to have your .apk built in out/ directory you will have to build it with make.
3. Adding a ConstraintLayout
In case you want to have several applications, which use a constraint layout, you can add it as a new library module as precompiled .aar.
Can be somewhere in 'vendor/yourname/libs' or 'your_dir_name/libs' respectively.
It is similar to adding a prebuilt .apk:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := constraint-layout
LOCAL_SRC_FILES := $(LOCAL_MODULE).aar
LOCAL_MODULE_SUFFIX := .aar
include $(BUILD_PREBUILT)
After that, in your application's Android.mk you will have to add:
LOCAL_STATIC_JAVA_LIBRARIES := constraint-layout
Alternatively, you can add a ConstraintLayout's .aar to the prebuilds/ as it eventually will be there someday.
There is a good topic about Android.mk: https://wladimir-tm4pda.github.io/porting/build_cookbook.html
https://stackoverflow.com/a/46414919/9237859 is right, except LOCAL_STATIC_JAVA_AAR_LIBRARIES should be used instead of LOCAL_STATIC_JAVA_LIBRARIES, since constraint-layout is a aar file.
From Android 9.0, there is no need of adding .aar and .jar separately in the project for constraint-layout. We can use constraint-layout library built in to AOSP.
We need to add one extra line in Android.mk:
LOCAL_USE_AAPT2 := true
Then, we need to add:
LOCAL_AAPT_FLAGS := \
--auto-add-overlay \
--extra-packages android.support.constraint
LOCAL_STATIC_ANDROID_LIBRARIES += android-support-constraint-layout
LOCAL_STATIC_JAVA_LIBRARIES += android-support-constraint-layout-solver
For more detailed answer: How to use constraint-layout during AOSP build without including external .aar and .jar
This can be done as follows:
Download constraint-layout.aar and constraint-layout-solve.jar and put these files in lib folder.
Add the following to your Android.mk file
LOCAL_STATIC_JAVA_AAR_LIBRARIES += constraint-layout
LOCAL_STATIC_JAVA_LIBRARIES += constraint-layout-solver
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := constraint-layout:libs/constraint-layout.aar
LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES := constraint-layput-solver:libs/constraint-layout-solver.jar

Compiling Ceres Solver With Android and Eclipse

I am trying to use ceres solver with my android application, and there does not seem to be a lot of documentation about using them both together properly. I have followed the build instructions from the ceres solver website, as well as this helpful tutorial:
http://tech.sandyeggi.com/2013/10/using-ceres-solver-in-android-ndk.html
This has gotten me far and everything is linked properly, but when I try to compile the project I get an odd error:
/Users/Steven/Documents/ceres-solver-1.10.0/include/ceres/internal/port.h:39:35: fatal error: ceres/internal/config.h: No such file or directory
Sure enough that file does not exist. But the question is why? Is it something that is supposed to be auto-generated? or created my self?
I might be important, so here is my Android.mk:
LOCAL_PATH := $(call my-dir)
LOCAL_ALLOW_UNDEFINED_SYMBOLS := true
include $(CLEAR_VARS)
LOCAL_MODULE := ceres
LOCAL_SRC_FILES := libceres.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_C_INCLUDES += /Users/Steven/Documents/android-ndk-r10d/sources/cxx-stl/stlport/stlport
LOCAL_C_INCLUDES += /Users/Steven/Documents/eigen-eigen-36fd1ba04c12/eigen-eigen-36fd1ba04c12
LOCAL_C_INCLUDES += /Users/Steven/Documents/ceres-solver-1.10.0/include
LOCAL_C_INCLUDES += /Users/Steven/Documents/ceres-solver-1.10.0/internal/ceres/miniglog
LOCAL_MODULE := DrinkMateDeveloper
LOCAL_SRC_FILES := DrinkMateDeveloper.cpp
LOCAL_STATIC_LIBRARIES = ceres
include $(BUILD_SHARED_LIBRARY)
Questions like this are best asked on the ceres-solver mailinglist.
The config.h you are looking for exists in
ceres-solver-1.10.0/config/ceres/internal/config.h
as the documentation in that file indicates
Default (empty) configuration options for Ceres.
IMPORTANT: Most users of Ceres will not use this file, when compiling Ceres
with CMake, CMake will configure a new config.h with the currently
selected Ceres compile options and copy it into the source
directory before compilation. However, for some users of Ceres
who compile without CMake, this file ensures that Ceres will
compile, with the user either specifying manually the Ceres
compile options, or passing them directly through the compiler.
you are going to have to do your own compiler defines for the various variables that are defined in
https://ceres-solver.googlesource.com/ceres-solver/+/master/cmake/config.h.in?autodive=0%2F

Android NDK - How to build static libraries just once?

In my Android application, I have quite a few open-source C++ projects that are built as static libraries. Essentially, Android.mk builds all the libraries as static and links them all to create my final core.so library.
Our nightly build checks out all the files from the source control in a clean directory and builds everything that is needed.
I am looking at how I can optimize our nightly build. As the third-party code does not change (may be once every six months), I would like to build them just once and check in the generated libs. I am guessing these libs would have a ".a" extension. The nighly build will simply check out these libs and link them to create my final core.so.
Basically, I am hoping I can break my existing Android.mk into two different ones - one for building static libraries and one for building the final shared library that the Android code can use.
I am wondering if this is possible. Regards.
You're looking for prebuilt library support.
Assuming your static library declaration looks something like this:
include $(CLEAR_VARS)
LOCAL_MODULE := foo
LOCAL_SRC_FILES := foo/foo.c
LOCAL_EXPORT_CFLAGS := -DFOO=1
include $(BUILD_STATIC_LIBRARY)
you can make it use a prebuilt instead:
include $(CLEAR_VARS)
LOCAL_MODULE := foo
LOCAL_SRC_FILES := libs/foo.a
include $(PREBUILT_STATIC_LIBRARY)
and include in your core lib just the same:
include $(CLEAR_VARS)
LOCAL_MODULE := myCore
LOCAL_SRC_FILES := core/core.c
LOCAL_STATIC_LIBRARIES := foo
include $(BUILD_SHARED_LIBRARY)
So you could have a seperate Android.mk, or just use a conditional variable.
ifeq ($(USE_PREBUILT_LIBS),)
# declare with BUILD_STATIC_LIBRARY
else
# declare with PREBUILT_STATIC_LIBRARY
endif

How to compile Cmake file with Android.mk?

I need to generate ARM structure shared library for a sampleCPP project.
Sample projects contains:
CMakeLists.txt
some.cpp (s)
Some.h (s)
some.tab.cpp.make (S)
some.tab.hpp.cmake (s)
Now, I want to create a shared library for a different Android project. I tried to compile with [Android-Cmake][1]but it is generating X86 Architecture library not ARM.
Please let me know if there is another way to do it. Also can i run X86 on Android Platform for all version?
Edit :
Here is my Android.mk:
LOCAL_PATH := $(call my-dir)/../ //Path is according JNI Folder
SRC_TOP_DIR := $(LOCAL_PATH)
include $(CLEAR_VARS)
LOCAL_MODULE := smileParse
LOCAL_CFLAGS := -DANDROID
LOCAL_SRC_FILES := main.cpp test.cpp smamain.cpp
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../include $(LOCAL_PATH)/
Create a folder called JNI in your project:
Create or Edit Android.mk in JNI folder, set include and library path,
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := hello-jni
LOCAL_SRC_FILES := some.cpp
include $(BUILD_SHARED_LIBRARY)
Declare a java wrapper class, declare a native function:
public class JWrapperSomeClass {
public native void Demo(int para);
}
use javah command to generate the function signature for your C++ method wrapper:
javah -jni -classpath bin/classes/ -d jni com.example.Your.Package.Class
Edit the code in C++
Go to your project folder, run command:
$ANDROID_NDK/ndk-build
where $ANDROID_NDK is the folder where you installed android NDK
That is pretty much it. For more details, you might read NDK or JNI documentation.

Loading shared libs using Android.mk

How can I specify shared libraries to load in the Android.mk when compiling with ndk-build ?
Edit: This is my Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := lib-crypto
LOCAL_SRC_FILES := libcrypto.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := tema1
LOCAL_SRC_FILES := tema1.c
LOCAL_SHARED_LIBRARIES := lib-crypto
LOCAL_C_INCLUDES := /home/aleksei/openSSL0.9.8/include
include $(BUILD_EXECUTABLE)
libcrypto.so is the library that I have built for android. I want to make a program using it. Now it gives me this error:
Install : libcrypto.so => libs/armeabi/libcrypto.so
Executable : tema1
./obj/local/armeabi/libcrypto.so: undefined reference to `dladdr'
collect2: ld returned 1 exit status
make: *** [obj/local/armeabi/tema1] Error 1
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).
read more from http://source-android.frandroid.com/ndk/docs/ANDROID-MK.html
Show me what you have done till yet and where you facing problem.?
I had the same problem. To fix it, I did the following:
In the same directory as your Android.mk file, create a file named Application.mk
Add the following line of code into Application.mk:
"APP_PLATFORM := android-8"
If you already have an Application.mk file, just add the code in step 2 to the existing file. Now call ndk-build and see if it links. ndk-build may be compiling with an old version of libdl which does not have dladdr(). The code in step 2 will cause ndk-build to use an updated libdl which has dladdr().

Categories

Resources