jpo38 jpo38 - 24 days ago 11
Android Question

Android.mk: How to check if a module already exists

I'm trying to generate Android.mk files automatically for an existing build environment. This environment has many libraries linking to each other and also possibly linking to 3rd party libs (like boost).

Let's say I have

libA
using boost.
My goal being to build both
libA
and
libB
by running ndk-build from libB folder.

So I generate this Android.mk for
libA
:

LOCAL_PATH := $(call my-dir)

# Import boost
include $(CLEAR_VARS)
LOCAL_MODULE := boost_atomic
LOCAL_SRC_FILES := ../dev/libcpp/boost/1.60.1/lib/libboost_atomic.a
include $(PREBUILT_STATIC_LIBRARY)

# libA:
include $(CLEAR_VARS)
LOCAL_MODULE := libA
LOCAL_SRC_FILES := libA.cpp
LOCAL_C_INCLUDES := ../dev/libcpp/boost/1.60.1

# boost import:
LOCAL_CPPFLAGS += -DHAVE_CONFIG_H -fexceptions -frtti
LOCAL_STATIC_LIBRARIES += boost_atomic

# build libA:
include $(BUILD_SHARED_LIBRARY)


Now I have
libB
using both
boost
and
libA
.
libB
's
Android.mk
is very similar to
libA
's except I added the import of
libA
file as below:

# Import libA
include $(CLEAR_VARS)
LOCAL_MODULE := libA
include ../../libA/jni/Android.mk


When I try to make
libB
, I'm being reported:

Android NDK: Trying to define local module 'boost_atomic' in ../../libA/jni/Android.mk.
Android NDK: But this module was already defined by ../../libA/jni/Android.mk.
B:/Android/android-ndk-r11b/build//../build/core/build-module.mk:34: *** Android
NDK: Aborting. . Stop.


Is there a way for me to check if
boost_atomic
is already defined (like
if (exists boost_atomic)
) to make sure it gets defined once only? Or should I suffix all the names (ending up with
boost_system_for_libA
and
boost_system_for_libB
) to prevent the conflict? Or any other alternative?

Answer

You have an NDK function $(modules_get_list). Relying on it, your libA/jni/Android.mk file may look as follows:

LOCAL_PATH := $(call my-dir)

include ../../boost/Android.mk

# libA:
include $(CLEAR_VARS)
LOCAL_MODULE    := libA
LOCAL_SRC_FILES := libA.cpp

# boost import:
LOCAL_STATIC_LIBRARIES += boost_atomic

# build libA:
$(if $(call set_is_member,$(modules-get-list),$(LOCAL_MODULE)),\
    ,$(eval include $(BUILD_SHARED_LIBRARY)))

and boost/Android.mk file:

LOCAL_PATH := $(call my-dir)

# Import boost
include $(CLEAR_VARS)
LOCAL_MODULE    := boost_atomic
LOCAL_SRC_FILES := ../dev/libcpp/boost/1.60.1/lib/libboost_atomic.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/../dev/libcpp/boost/1.60.1
LOCAL_EXPORT_CPPFLAGS += -DHAVE_CONFIG_H -fexceptions -frtti
$(if $(call set_is_member,$(modules-get-list),$(LOCAL_MODULE)),\
    ,$(eval include $(PREBUILT_STATIC_LIBRARY))

Finally, libB/jni/Android.mk:

LOCAL_PATH := $(call my-dir)

include ../../boost/Android.mk
include ../../libA/jni/Android.mk

# libB:
include $(CLEAR_VARS)
LOCAL_MODULE    := libB
LOCAL_SRC_FILES := libB.cpp

# boost import:
LOCAL_STATIC_LIBRARIES += boost_atomic

# build libA:
$(if $(call set_is_member,$(modules-get-list),$(LOCAL_MODULE)),\
    ,$(eval include $(BUILD_SHARED_LIBRARY)))

I prefer not to have duplicate definitions for 3rd party prebuilt libs, like boost, but rather to use a separate Android.mk definition for each, and include it whenever necessary. This way, I have one place to change if the external library is updated.

Update: if you don't like $(if …) syntax, you may use

ifeq ($(filter $(modules-get-list),$(LOCAL_MODULE)),)
    include $(BUILD_…_LIBRARY)
endif

instead.

Comments