Problems using NDK build system and subdirectories

2,513 views
Skip to first unread message

Timmmm

unread,
May 24, 2010, 5:55:41 PM5/24/10
to android-ndk
Hi, I've been trying to build an NDK app that links with freetype and
stlport for a while. Finally got it to work, but there appear to be
some very weird things in the NDK build system that may be bugs.
Either way, hopefully someone will find this useful.

My tree structure is:

$PROJECT/jni/Android.mk
$PROJECT/jni/main.c

$PROJECT/jni/freetype/Android.mk
$PROJECT/jni/freetype/<all the other freetype files>

$PROJECT/jni/stlport/Android.mk
$PROJECT/jni/stlport/<all the other stlport files>

Now, naively following the docs you might thing the following main
Android.mk will work:

#############################

LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)

# Build freetype and stlport as static libraries
include $(call all-subdir-makefiles)

# Build main library as shared library.
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

LOCAL_MODULE := main
LOCAL_SRC_FILES := main.c
LOCAL_STATIC_LIBRARIES := ft2 stlport

include $(BUILD_SHARED_LIBRARY)

############################

And as far as I can tell it *should* work, but it doesn't. The first
reason is because 'all-subdir-makefiles' just doesn't work. No idea
why; it just doesn't. Fine, replace it with:

include freetype/Android.mk
include stlport/Android.mk

Ok, now we get errors about not having a target for <ndk_dir>/build/
core/main.c. What the hell? I eventually realised that 'my-dir'
doesn't really work that well either, or at least the current
directory gets easily changed.
You have to store the correct directory at the start of the Android.mk
like this:

###########################

JNI_DIR := $(call my-dir)

LOCAL_PATH:= $(JNI_DIR)
include $(CLEAR_VARS)

# Build freetype and stlport as static libraries.
include freetype/Android.mk
include stlport/Android.mk

# Build main library as shared library.
LOCAL_PATH := $(JNI_DIR)
include $(CLEAR_VARS)

LOCAL_MODULE := main
LOCAL_SRC_FILES := main.c
LOCAL_STATIC_LIBRARIES := ft2 stlport

include $(BUILD_SHARED_LIBRARY)

#############################

Finally it works! I hope somebody finds this useful and I doubt anyone
will fix these bugs (whether they be in the code or the
documentation).

Tim

PS: If you're wanting to link freetype or stlport, you just need to
copy the latest freetype snapshot from AOSP to jni/freetype, and there
is a link on the stlport page for stlport.

--
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.

David Turner

unread,
May 24, 2010, 6:05:22 PM5/24/10
to andro...@googlegroups.com
This is due to a limitation of the GNU Make command language: All variables are global, and the implementation of $(call my-dir) can only give you the name of the last included Makefile (even if you already exited the Makefile). There is no way to implement something that works properly with GNU Make.

In this specific case, the problem is that LOCAL_PATH has been redefined by an included Android.mk, and must be re-instanced to the value proper to your module definition.

Generally speaking, try including other sub-makefiles after module definitions in your own module.
Or, simply re-assign the LOCAL_PATH value as you did in your fix.

Hope this helps

Timmmm

unread,
May 24, 2010, 7:00:00 PM5/24/10
to android-ndk


On May 24, 11:05 pm, David Turner <di...@android.com> wrote:
> Generally speaking, try including other sub-makefiles after module
> definitions in your own module.
> Or, simply re-assign the LOCAL_PATH value as you did in your fix.

Ah ok I didn't realise they don't have to be in dependency order. Any
idea why the all-subdir-makefiles function doesn't seem to work?

Thanks for the quick reply!

Tim

David Turner

unread,
May 24, 2010, 7:06:00 PM5/24/10
to andro...@googlegroups.com
On Mon, May 24, 2010 at 4:00 PM, Timmmm <tdh...@gmail.com> wrote:


On May 24, 11:05 pm, David Turner <di...@android.com> wrote:
> Generally speaking, try including other sub-makefiles after module
> definitions in your own module.
> Or, simply re-assign the LOCAL_PATH value as you did in your fix.

Ah ok I didn't realise they don't have to be in dependency order. Any
idea why the all-subdir-makefiles function doesn't seem to work?


Probably because all-subdir-makefiles uses my-dir internally to determine where you are.

Since you included $(CLEAR_VARS) just before calling this function, the last included Makefile is probably $NDK/build/core/clear-vars.mk and the function will look for sub-directories under $NDK/build/core/

MAKEFILES_LIST is broken by design, unfortunately :-(
 
Thanks for the quick reply!

Tim

--
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.

Timmmm

unread,
May 26, 2010, 4:37:08 PM5/26/10
to android-ndk
I found another serious problem with Android.mk. If you use the second
approach I posted the final library gets built, but not copied into
the $PROJECT/lib directory! I expect this is another case of the
current directory getting changed...

Anyway, it all works (except the sub-dirs thing) if you do it like
this:

--------------------8<-------------

# Build game library as shared library.


LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

LOCAL_MODULE := game
LOCAL_C_INCLUDES := \
$(LOCAL_PATH)/stlport/stlport \
$(LOCAL_PATH)/freetype/include
LOCAL_SRC_FILES := ...

LOCAL_STATIC_LIBRARIES := ft2 stlport
LOCAL_LDLIBS := -lGLESv1_CM
LOCAL_CPPFLAGS := -DANDROID_NDK

include $(BUILD_SHARED_LIBRARY)

# Build freetype and stlport as static libraries.
include freetype/Android.mk
include stlport/Android.mk

---------->8-----------------

I really really think you should add some more documentation about
what the hell is going on here! (Or at least include an example like
this one. Surely it is a very common use case - the current twolibs
example puts all the source files in the same directory which I'm
pretty sure no-one would do in practice).

Tim


Doug Schaefer

unread,
May 26, 2010, 6:27:04 PM5/26/10
to andro...@googlegroups.com

What we really need is a repository of prebuilt libraries like freetype and friends for Android.

Timmmm

unread,
May 27, 2010, 12:08:38 PM5/27/10
to android-ndk
On May 26, 11:27 pm, Doug Schaefer <cdtd...@gmail.com> wrote:
> What we really need is a repository of prebuilt libraries like freetype and
> friends for Android.

Actually that part was really really easy. It's just the build system
that needs fixing or documenting.

Another issue I've found is that in order to regenerate the APK after
building the library I have to clean the project. However this deletes
all the intermediate object files so when I go to rebuild the jni
library it has to rebuild it all. That is, I do something like this:

1. Alter source files.
2. ndk-build
3. Try running the project in eclipse - it doesn't notice the library
has changed and uses an old apk.
4. Clean the project.
5. Run it, now it rebuilds the apk with the new library.
6. Alter the source files some more.
7. ndk-build - at this point I expect it to do an incremental build
but it actually recompiles every file.

Doug Schaefer

unread,
May 27, 2010, 6:59:41 PM5/27/10
to andro...@googlegroups.com
On Thu, May 27, 2010 at 12:08 PM, Timmmm <tdh...@gmail.com> wrote:
On May 26, 11:27 pm, Doug Schaefer <cdtd...@gmail.com> wrote:
> What we really need is a repository of prebuilt libraries like freetype and
> friends for Android.

Actually that part was really really easy. It's just the build system
that needs fixing or documenting.

I was thinking more about things like OGRE which may not be so easy. 

David Turner

unread,
May 27, 2010, 7:14:12 PM5/27/10
to andro...@googlegroups.com
Yes, we plan to integrate the NDK into the SDK so that sort of thing won't happen
(and you won't even have to use the command-line to generate the native code).

However, we'll need to get rid of Cygwin before that. This is on the roadmap though.

Reply all
Reply to author
Forward
0 new messages