Problem building multiple shared libraries with sources spread over multiple directories

554 views
Skip to first unread message

Divkis

unread,
Jan 31, 2010, 2:49:07 PM1/31/10
to android-ndk
Hi,
I am trying to build my source which is spread over multiple
directories. My sources also depend on some other native libraries
which are not part of NDK. The way my sources are organized is this:

Please bear with the long post and description but don't really know
how else to describe my problem.

NDK_ROOT/apps/myapp
--- Application.mk
|
client
----jni
Android.mk
--- extra_libs

Android.mk

--- library-a

Android.mk
...
other sources

--- library-b

Android.mk
...
other sources
---source-dir-1

a.cpp
---source-dir-2

b.cpp

My Application.mk looks like this:
-----------------------------------------------------------------------------------------------
APP_MODULES := a b myapp
APP_PROJECT_PATH := $(call my-dir)/client
-----------------------------------------------------------------------------------------------

client/jni/Android.mk looks like this:
-----------------------------------------------------------------------------------------------
LOCAL_PATH := $(call my-dir)

include $(LOCAL_PATH)/extra_libs/Android.mk

include $(CLEAR_VARS)

LOCAL_SRC_FILES := source-dir1/a.cpp source-dir2/b.cpp

LOCAL_MODULE := mylib
LOCAL_LDLIBS := -ldl

include $(BUILD_SHARED_LIBRARY)
-----------------------------------------------------------------------------------------------


client/jni/extra_libs/Android.mk looks like this:
-----------------------------------------------------------------------------------------------
LOCAL_PATH := $(call my-dir)

include $(call all-subdir-makefiles)
-----------------------------------------------------------------------------------------------

Android Makefiles inside library-a and library-b are not important as
they seem to build fine.


The trouble comes when it starts to build the 'mylib' shared library,
where the build process emits something like this:

make: *** No rule to make target `apps/myapp/client/jni/extra_libs/
library-a/source-dir-1/a.cpp', needed by `out/apps/myapp/client/jni/
source-dir-1/oscall.o'. Stop.


I have tried building this in various ways by placing individual
Android.mk files inside source-dir-1/2, but apparently simply building
static libraries without shared library in a single Android.mk doesn't
work. The only way was to list all the sources at the top level
makefile itself with individual directory prefixes.

I also tried by doing:

include $(LOCAL_PATH)/extra_libs/Android.mk
include $(LOCAL_PATH)/source-dir-1/Android.mk
include $(LOCAL_PATH)/source-dir-2/Android.mk

but I see similar issues there as well.

Could anyone please help or suggest how could I build native sources
in such a scenario. The crux is that I want to build several shared
libraries instead of one.

Thanks in advance,
DivKis

Divkis

unread,
Jan 31, 2010, 3:12:02 PM1/31/10
to android-ndk
Viewing through google groups the formatting of directory hierarchy
seems screwed up. Let me list that again.

NDK_ROOT/apps/myapp
--- Application.mk
client
----jni
Android.mk
--- extra_libs
Android.mk
--- library-a
Android.mk
...other sources
--- library-b
Android.mk

...other sources
---source-dir-1
a.cpp
---source-dir-2
b.cpp

Divkis

unread,
Feb 2, 2010, 1:37:01 AM2/2/10
to android-ndk
Hi,
I have discovered that building of shared library in the same
Android.mk which does

include $(call all-subdir-makefiles)

doesn't work for some reasons.

For now I have manged to solve my problem by moving the code directory
which builds my own shared library at the same level which builds the
other third party libraries.

I hope that NDK build system becomes more robust and provides other
'documented' functions and macros to solve issues like this.

Thanks anyway,
Divkis

David Turner

unread,
Feb 2, 2010, 2:11:51 PM2/2/10
to andro...@googlegroups.com
You are redefining the meaning of LOCAL_PATH in several Android.mk, that probably explains why things are not working for you.


--
You received this message because you are subscribed to the Google Groups "android-ndk" group.
To post to this group, send email to andro...@googlegroups.com.
To unsubscribe from this group, send email to android-ndk...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/android-ndk?hl=en.


Divkis

unread,
Feb 3, 2010, 12:28:03 AM2/3/10
to android-ndk
Hi David,

> You are redefining the meaning of LOCAL_PATH in several Android.mk, that
> probably explains why things are not working for you.

Quoting from the NDK documentation:

"LOCAL_PATH
This variable is used to give the path of the current file.
You MUST define it at the start of your Android.mk, which can
be done with:"

Hence I define it at the top of my Android.mk files, which I have
spread over several directories. I assumed that it would be something
like having multiple Makefile i.e. one inside every directory.

If I don't define LOCAL_PATH inside each Android.mk then how else
would I find path to the current Android.mk? Hence an Android.mk
residing deep inside the project hierarchy would either need to hard
code or use path from top most LOCAL_PATH. I don't see any other
macro/ function that serves this purpose.

Thanks again,
Divkis

David Turner

unread,
Feb 3, 2010, 1:39:18 AM2/3/10
to andro...@googlegroups.com
Ah, that's a good point and it's a bit hard to explain in a very short amount
of text. Let me try to clarify all of this.

First, LOCAL_PATH is only needed when you want to build a module, so
you don't need it if your Android.mk only calls all-subdir-makefiles.

Second, GNU Make only handles a single variable name space, and parses
all build files in sequence, so each time you re-assign LOCAL_PATH, the
new definition is kept even if you exit the included build file. For example,
consider these two files:

$TOP/Android.mk:
====================================
LOCAL_PATH := $(call my-dir)
include $(LOCAL_PATH)/subdir/Android.mk
$(info LOCAL_PATH=$(LOCAL_PATH))


$TOP/subdir/Android.mk:
====================================
LOCAL_PATH := $(call my-dir)

The effect of these two files is to print the value of LOCAL_PATH as $TOP/subdir
because the definition in subdir/Android.mk persists in Android.mk after the include.

Due to the way GNU Make works, the my-dir command can only work by returning
the directory containing the _latest_ included file, even if the parser exited it.

A simple fix for your problem is to have a top-level Android.mk that includes several
other sub-build files which actually define LOCAL_PATH and modules, for example:

$TOP/Android.mk:
===========================================
TOP_DIR := $(call my-dir)
include $(TOP_DIR)/subdir1/Android.mk
include $(TOP_DIR)/subdir2/Android.mk
incldue $(TOP_DIR)/subdir3/Android.mk

$TOP/subdir1/Android.mk
===========================================
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE := libfoo
LOCAL_SRC_FILES := foo.c
include $(BUILD_SHARED_LIBRARY)

$TOP/subdir2/Android.mk
===========================================
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE := libbar
LOCAL_SRC_FILES := bar.c
include $(BUILD_SHARED_LIBRARY)

$TOP/subdir3/Android.mk
===========================================
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE := libzoo
LOCAL_SRC_FILES := zoo.c
include $(BUILD_SHARED_LIBRARY)

You probably get the idea. Using the TOP_DIR variable ensures that it is not redefined by
sub-build files like LOCAL_PATH typically is.

Hope this helps


Thanks again,
Divkis

Divkis

unread,
Feb 5, 2010, 12:39:28 AM2/5/10
to android-ndk
Hi David,

Yeah it __does__ work for me now. I think I was confused and assumed
that defining LOCAL_PATH is necessary in every Android.mk files.
Without realizing that LOCAL_PATH is only necessary in the files which
build a module, I was defining in every Android.mk files and to work
around to the problem I was storing this LOCAL_PATH in another
variable and using that variable for obtaining paths, the following
fashion, which is not necessary now.

> LOCAL_PATH := $(call my-dir)
> LIB1_PATH := LOCAL_PATH
>include $LIB1_PATH/<path to Android.mk)

Thanks a lot for explaining this in so detail,
Regards,
Divkis

Reply all
Reply to author
Forward
0 new messages