Android NDK: how to include Android.mk into another Android.mk (hierarchical project structure)?-ThrowExceptions

Exception or error:

Looks like it’s possible, but my script produces odd results:

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

include $(LOCAL_PATH)/libos/Android.mk
include $(LOCAL_PATH)/libbase/Android.mk
include $(LOCAL_PATH)/utils/Android.mk

LOCAL_MODULE := native
include $(BUILD_SHARED_LIBRARY)

Only the first include is being parsed fine, other Android.mk files are being seacrhed at odd paths.
Suggestions?

Update: I have broken my building environment… It was OK in the office, but at home LOCAL_PATH:= $(call my-dir) defines LOCAL_PATH to NDK dir instead of project dir. This is my batch for building:

set BASHPATH=K:\cygwin\bin\bash
set PROJECTDIR=/cygdrive/h/Alex/Alex/Work/Android/remote-android
set NDKDIR=/cygdrive/h/Alex/Programming_Docs/Android/android-ndk-r6/ndk-build
set APP_BUILD_SCRIPT=/cygdrive/h/Alex/Alex/Work/Android/project/jni/Android.mk
set DEV_ROOT=h:/Alex/Alex/Work/Android/project

%BASHPATH% --login -c "cd %PROJECTDIR% && %NDKDIR%"

Update: I absolutely don’t understand how does this thing compose paths. I’m getting errors with paths like “/cygdrive/d/project/jni//cygdrive/d/Soft/project/jni/libos/src/libos.cpp’. This is after I decided to specify all files in the root Android.mk instead of including submodules.

Update 2: No luck, this doesn’t work either:

LOCAL_PATH:= $(call my-dir)
# Include makefiles here.
include $(LOCAL_PATH)/libos/Android.mk
include $(LOCAL_PATH)/libbase/Android.mk
include $(LOCAL_PATH)/utils/Android.mk

# Clear variables here.
 include $(CLEAR_VARS)
How to solve:

Pretty late here, but in case somebody reads this question, one way to get past the problem of broken paths(pointing to the ndk insted of your files from the jni) is to have in your jni folder:

include $(call all-subdir-makefiles)

and then in every subfolder of it (libos, libbase and ustils inthe case of OP) an Android.mk of this form:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_C_INCLUDES        := $(LOCAL_PATH)
LOCAL_MODULE            := utils
LOCAL_SRC_FILES         := one.c
LOCAL_SRC_FILES         += two.c

where this second Android.mk in with the one.c and two.c files in a subfolder found in the jni folder.

Note that trying something as

LOCAL_PATH_BIS_WEIRD_OTHER_NAME := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_C_INCLUDES        := $(LOCAL_PATH_OTHER_FUNKY_NAME)
LOCAL_MODULE            := utils
LOCAL_SRC_FILES         := one.c
LOCAL_SRC_FILES         += two.c

will lead again to a confused compiler looking for your source code where the ndk is.

So, use the LOCAL_PATH := $(call my-dir) EXACTLY in this form in every subdirectory of the jni and include $(call all-subdir-makefiles) in the jni itself and you shouldn’t have problems.

Hope this will help someone.

Edit: this behaviour happens because what is kept in LOCAL_PATH is not deleted by include $(CLEAR_VARS).

###

Here’s how I do it.

One caveat is that I don’t put any of my C++ source code in the build dir, since most of it is platform-independent. This just means that LOCAL_PATH is not a subdir of the project dir, and the only files in /jni are the 2 .mk files.

Anyway, here’s a full top-level Android.mk and one of the included ones for a real project:

Top level:

LOCAL_PATH := $(abspath $(call my-dir)/../../../src)

# utility to create paths for included makefiles
local-rel-path = $(patsubst /%,%,$(subst $(LOCAL_PATH),,$(abspath $1)))

include $(CLEAR_VARS)

LOCAL_MODULE := NativeApp

LOCAL_LDLIBS := -lGLESv1_CM

# As opposed to "thumb"
LOCAL_ARM_MODE := arm

LOCAL_SRC_FILES :=

#
# includes
#
# Note that LOCAL_C_INCLUDE is relative to thr NDK root, unlike source paths
# (or you can just make 'em absolute)
#
STL_INC_DIR = /cygdrive/c/STLport-5.2.1/stlport

MY_LOCAL_C_INCLUDES := core satcalc bruce/bruce/inc bruce/gfx/inc bruce/ui/inc bruce/unzip bruce/libpng

LOCAL_C_INCLUDES := $(addprefix $(LOCAL_PATH)/,$(MY_LOCAL_C_INCLUDES)) $(STL_INC_DIR) 

ifeq ($(APP_OPTIM),debug)
# debug
LOCAL_CFLAGS = -DPLATFORM_ANDROID -D_DEBUG -fvisibility=hidden
else
#release
LOCAL_CFLAGS = -DPLATFORM_ANDROID -fvisibility=hidden
endif

LOCAL_STATIC_LIBRARIES := 

#
# Code
#
include $(LOCAL_PATH)/core/Android.mk
include $(LOCAL_PATH)/satcalc/Android.mk
include $(LOCAL_PATH)/bruce/bruce/src/Android.mk
include $(LOCAL_PATH)/bruce/gfx/src/Android.mk
include $(LOCAL_PATH)/bruce/ui/src/Android.mk
include $(LOCAL_PATH)/bruce/unzip/Android.mk
include $(LOCAL_PATH)/bruce/libpng/Android.mk

#
# Build it
#
include $(BUILD_SHARED_LIBRARY)

…and an included Android.mk:

MY_PATH = $(call my-dir)

MY_LOCAL = $(call local-rel-path, $(MY_PATH))

MY_SRC_FILES = Font.cpp Gfx2d_ogles.cpp SgaState.cpp \
        Sprite.cpp TImage.cpp TImageOgles.cpp 

LOCAL_SRC_FILES += $(addprefix $(MY_LOCAL)/,$(MY_SRC_FILES))

###

My approah is like this:

LOCAL_PATH:= $(call my-dir)

# Clear variables here.
include $(CLEAR_VARS)

# Current module settings.
LOCAL_MODULE := native
# setup some source files
LOCAL_SRC_FILES := file1.c file2.c
# setup some includes
LOCAL_C_INCLUDES := $(LOCAL_PATH)/libos/include
# setup the included libs for the main module
LOCAL_STATIC_LIBRARIES := libos libbase utils # note that order matters here

include $(BUILD_SHARED_LIBRARY)

# Include makefiles here. Its important that these 
# includes are done after the main module, explanation below.

# create a temp variable with the current path, because it 
# changes after each include
ZPATH := $(LOCAL_PATH)

include $(ZPATH)/libos/Android.mk
include $(ZPATH)/libbase/Android.mk
include $(ZPATH)/utils/Android.mk

Note, that includes are done after the setup of current module variables. This is needed because each include modifies the LOCAL_PATH variable (actually it modifes what $(call my-dir) returns) and thats why includes must be done last.

This will automatically compile all included modules (or clean then if called with clean) and then link with all the included libraries.

This setup was tested in a real project and works correctly.

answer taken from here: https://docs.google.com/document/d/1jDmWgVgorTY_njX68juH5vt0KY_FXWgxkxmi2v_W_a4/edit

###

You’re on the right track. That is the proper way to include Android.mk files within another – it’s actually required by the Android make system. One thing to note is that the line to clear variables should appear -after- you include the other makefiles, like this:

LOCAL_PATH:= $(call my-dir)

# Include makefiles here.
include $(LOCAL_PATH)/libos/Android.mk
include $(LOCAL_PATH)/libbase/Android.mk
include $(LOCAL_PATH)/utils/Android.mk

# Clear variables here.
include $(CLEAR_VARS)

# Final settings.
LOCAL_MODULE := native
include $(BUILD_SHARED_LIBRARY)

I’d also mention that there’s other important flags you may or may not want to set, including the following (an example from one of my makefiles):

# Settings.
LOCAL_C_INCLUDES             := $(MY_INCLUDES)
LOCAL_STATIC_LIBRARIES       := $(MY_MODULES) 
LOCAL_WHOLE_STATIC_LIBRARIES := $(MY_WHOLE_MODULES) 
LOCAL_LDLIBS                 := -lz -llog -lGLESv1_CM -lGLESv2 
LOCAL_ARM_MODE               := arm
LOCAL_MODULE                 := game

Finally, I’ve found the documentation that comes embedded within the Android ndk to be especially helpful. Mine is found in the following location:

android-ndk-r6/documentation.html

Let me know if you have further questions. Hope this helps! 🙂

###

Very late answer here, but I had this problem and none of these solutions were useful. The solution turns out to be straightforward: as detailed here, set a MY_LOCAL_PATH variable and reallocate LOCAL_PATH every time:

MY_LOCAL_PATH := $(call my-dir)

LOCAL_PATH := $(MY_LOCAL_PATH)

... declare one module

include $(LOCAL_PATH)/foo/Android.mk

LOCAL_PATH := $(MY_LOCAL_PATH)

... declare another module

###

I test the below code ok.

# I want only second-level mk files, that is the direct sub-directories
# in the current path.
include $(wildcard */*/Android.mk)
# include $(call all-subdir-makefiles)  ## $(wildcard $(call my-dir)/*/Android.mk)
# include $(call all-makefiles-under,$(LOCAL_PATH))

Android.mk

# I dunno why it's an empty result for $(call all-subdir-makefiles).
# $(info [^-^ print-test] all-subdir-makefiles = "$(call all-subdir-makefiles) ")
$(info [print-test] assert "jni/Android.mk" = "$(wildcard */Android.mk)") # print: jni/Android.mk
$(info [print-test] $$(wildcard */*/Android.mk) = "$(wildcard */*/Android.mk)") # print: jni/xxdir/Android.mk

I print the result :

$ cd your_project_path
$ ndk-build
[print-test] assert "jni/Android.mk" = "jni/Android.mk"
[print-test] (wildcard */*/Android.mk) = "jni/HelloWorld/Android.mk jni/MessagePack/Android.mk"

Leave a Reply

Your email address will not be published. Required fields are marked *