Very simple question, hoping for a very simple answer. I've been looking at a lot of people's android.mk files and have noticed this line. I had no documentation on it within my NDK's docs (at least find . -name "*.txt" | xargs grep "LOCAL_EXPORT_C_INCLUDES" came up with nothing). This was the only documentation I've read on it...goes way over my head...
Part 2: Am I correct in my assumption that I will need this line to use a pre-built shared library with another module? Thanks guys (and gals)
III. Exporting headers for prebuilt libraries:
The example above was called 'naive' because, in practice, the code in
foo-user.c is going to depend on specific declarations that are normally
found in a header file distributed with the prebuilt library (e.g. "foo.h").
In other words, foo-user.c is going to have a line like:
include < foo.h >
And you need to provide the header and its include path to the compiler
when building the foo-user module.
A simple way to deal with that is to use exports in the prebuilt module
definition. For example, assuming that a file "foo.h" is located under
the 'include' directory relative to the prebuilt module, we can write:
`include $(CLEAR_VARS)
LOCAL_MODULE := foo-prebuilt
LOCAL_SRC_FILES := libfoo.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_SHARED_LIBRARY)`
The LOCAL_EXPORT_C_INCLUDES definition here ensures that any module that
depends on the prebuilt one will have its LOCAL_C_INCLUDES automatically
prepended with the path to the prebuilt's include directory, and will thus
be able to find headers inside that.
URL: http://www.srombauts.fr/android-ndk-r5b/docs/PREBUILTS.html
The following explanation for the LOCAL_EXPORT_* variables in ANDROID-MK.html in the docs folder of the r6 NDK:
LOCAL_EXPORT_CFLAGS
Define this variable to record a set of C/C++ compiler flags that will
be added to the LOCAL_CFLAGS definition of any other module that uses
this one with LOCAL_STATIC_LIBRARIES or LOCAL_SHARED_LIBRARIES.
For example, consider the module 'foo' with the following definition:
include $(CLEAR_VARS)
LOCAL_MODULE := foo
LOCAL_SRC_FILES := foo/foo.c
LOCAL_EXPORT_CFLAGS := -DFOO=1
include $(BUILD_STATIC_LIBRARY)
And another module, named 'bar' that depends on it as:
include $(CLEAR_VARS)
LOCAL_MODULE := bar
LOCAL_SRC_FILES := bar.c
LOCAL_CFLAGS := -DBAR=2
LOCAL_STATIC_LIBRARIES := foo
include $(BUILD_SHARED_LIBRARY)
Then, the flags '-DFOO=1 -DBAR=2' will be passed to the compiler when
building bar.c
Exported flags are prepended to your module's LOCAL_CFLAGS so you can
easily override them. They are also transitive: if 'zoo' depends on
'bar' which depends on 'foo', then 'zoo' will also inherit all flags
exported by 'foo'.
Finally, exported flags are not used when building the module that
exports them. In the above example, -DFOO=1 would not be passed to the
compiler when building foo/foo.c.
LOCAL_EXPORT_CPPFLAGS
Same as LOCAL_EXPORT_CFLAGS, but for C++ flags only.
LOCAL_EXPORT_C_INCLUDES
Same as LOCAL_EXPORT_CFLAGS, but for C include paths.
This can be useful if 'bar.c' wants to include headers
that are provided by module 'foo'.
Related
I'm having trouble getting the dependency module to build while building a static library in AOSP. Call this library A, it has a dependency on another static lib B.
A's Android.mk looks like this:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := A
LOCAL_SRC_FILES := <files...>
LOCAL_STATIC_LIBRARIES := B
include $(BUILD_STATIC_LIBRARY)
Individually B builds fine (mma).
Problem is when I build A, B is not being built. Instead I see this at output:
Export includes file: <...>/B/Android.mk -- out/<...>/STATIC_LIBRARIES/B_intermediates/export_includes
Can someone explain what does this line mean and, why is it not trying use B's Android.mk to properly build B?
I understand it's not ideal to package a static lib inside another, but here I'm more courious about why is it the build system not running through B's makefile, when it's clearly a dependency?
Thank you!
The build system ignores lots of irrelevant statements, LOCAL_STATIC_LIBRARIES being one of examples. They don't write every entry in LOCAL_STATIC_LIBRARIES as a dependency for libA.a. Instead, they interpret the Android.mk files to produce make rules for all targets, and if a dependency happens to show up, it will eventually get built, too.
Therefore, the easiest workaround for you would be to add a dummy shared library to your Android.mk, like
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := A
LOCAL_SRC_FILES := <files...>
include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := dummyA
LOCAL_SRC_FILES := dummy.c
LOCAL_STATIC_LIBRARIES := B
include $(BUILD_SHARED_LIBRARY)
I am not sure if you can drop LOCAL_SRC_FILES completely. In terms of good old plain make files, the above is roughly equivalent to:
all: libA.a libdummyA.so
libdummyA.so: dummy.c libB.a
gcc -o $# dummy.c -lb
Alternatively, you can manually specify the dependency:
$(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libA_intermediates/libA.a: $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libB_intermediates/libB.a
Re: export_includes message, it is the result of processing LOCAL_EXPORT_C_INCLUDES statement for libB.
I'm trying to wrap some functions of a c-library (OpenAL-MOB) in order to use them in my Android application.
I think that my functions aren't correctly exported.
Steps I've taken:
I've made a java class with the functions I would like to use in my Android application,
Created stubs by using javah and javac (I haven't changed any class names or package names after doing this),
Added the wrapper files to the Android.mk
Build an .so library (with ndk-build)
Copied the .so file to the libs/armeabi-folder of my android project
Loaded the library in my android code and called a native function -> unsatisfiedinkerror.
When I try to use the library in my android code, I am able to load the library, but it cannot find my wrapped functions.
System.loadLibrary("openal"); // Works
OpenAlConnector.init(); // My wrapped function throws an unsatisfiedlinkerror
I think that my functions aren't actually exported.
To add my wrapper functions, I've modified the Android.mk that was already present in the OpenAL-MOB project. I didn't get any errors during the build. The only thing I did, was adding 2 files (.c created by javah and a helper class) to the end of LOCAL_SRC_FILES.
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../include $(LOCAL_PATH)/../../OpenAL32/Include $(LOCAL_PATH)/../../mob/Include $(LOCAL_PATH)
LOCAL_MODULE := openal-static
LOCAL_SRC_FILES := ../../Alc/ALc.c ../../Alc/alcConfig.c ../../Alc/alcDedicated.c ../../Alc/alcEcho.c ../../Alc/alcModulator.c ../../Alc/alcReverb.c ../../Alc/alcRing.c ../../Alc/alcThread.c ../../Alc/ALu.c ../../Alc/backends/loopback.c ../../Alc/backends/null.c ../../Alc/backends/opensl.c ../../Alc/backends/wave.c ../../Alc/bs2b.c ../../Alc/helpers.c ../../Alc/hrtf.c ../../Alc/mixer.c ../../Alc/mixer_c.c ../../Alc/mixer_inc.c ../../Alc/mixer_neon.c ../../Alc/mixer_sse.c ../../Alc/panning.c ../../mob/alConfigMob.c ../../OpenAL32/alAuxEffectSlot.c ../../OpenAL32/alBuffer.c ../../OpenAL32/alEffect.c ../../OpenAL32/alError.c ../../OpenAL32/alExtension.c ../../OpenAL32/alFilter.c ../../OpenAL32/alListener.c ../../OpenAL32/alSource.c ../../OpenAL32/alState.c ../../OpenAL32/alThunk.c openalwrapper.c org_vansina_openal_OpenAlConnector.c
# set the platform flags
ifeq ($(APP_ABI),x86)
LOCAL_CFLAGS += -D HAVE_SSE
else
LOCAL_CFLAGS += -D HAVE_NEON -mfloat-abi=softfp -mfpu=neon -marm
endif
include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := openal
LOCAL_STATIC_LIBRARIES := openal-static
include $(BUILD_SHARED_LIBRARY)
I've used NM to see which functions were exported (nm.exe -D libopenal.so). This was the result:
00002004 A __bss_start
U __cxa_atexit
U __cxa_finalize
00002004 A _edata
00002004 A _end
I'm not sure if I'm correct, but it seems that my functions are missing.
Does anyone have an idea what I can do or check? Is there a problem in my .mk file?
I'm try to wrap this library for some days now and I'm getting quite desparate. Any help is very much appreciated!
Edit:
I believe that it has something to do with building the library as a static first and then as a shared library. It seems that all the symbols get lost if I create a shared lib like that. Can someone give me additional info about this?
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
I compiled Sox et al with NDK. So, I have all Android-friendly shared libs.
I made a simple test file which calls a sox function.
NDK build tells me:
undefined reference to `sox_open_read'
sox_open_read is defined in sox.h. I know it's finding sox.h because it gives me a warning about that file:
In file included from (...)/sox/sox.h:19
So maybe it wants to find sox_open_read in the actual libsox.so. Well, I've tried about a 100 different ways to tell it where the sox shared lib is e.g.
LOCAL_SHARED_LIBRARY := sox
LOCAL_LDLIBS := -L$(LOCAL_PATH_FULL)/jni/libs/libsox.so
However, It will work if I specify Sox as a static library:
#LOCAL_SHARED_LIBRARY := sox
LOCAL_STATIC_LIBRARIES := sox
LOCAL_LDLIBS := -L$(LOCAL_PATH_FULL)/jni/libs/libsox.so
It's my understanding that I don't want to staticly link to the sox lib - I want to dynamically link to it.
You should define libsox.so as a prebuilt library. Create a makefile as the following and put your prebuilt libsox.so in the same directory with this makefile. After that, you can use libsox same as you've rebuilt it. Don't forget to include this makefile into your build.
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libsox
LOCAL_SRC_FILES := libsox.so
include $(PREBUILT_SHARED_LIBRARY)
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.