Android.mk:如何检查模块是否已经存在

Android.mk:如何检查模块是否已经存在,android,c++,android-ndk,Android,C++,Android Ndk,我正在尝试为现有构建环境自动生成Android.mk文件。这个环境中有许多库相互链接,也可能链接到第三方lib(如boost) 假设我有libA使用boost。 我的目标是通过从libB文件夹运行ndk build来构建libA和libB 因此,我为libA生成了这个Android.mk: LOCAL_PATH := $(call my-dir) # Import boost include $(CLEAR_VARS) LOCAL_MODULE := boost_atomic LOCAL

我正在尝试为现有构建环境自动生成Android.mk文件。这个环境中有许多库相互链接,也可能链接到第三方lib(如boost)

假设我有
libA
使用boost。 我的目标是通过从libB文件夹运行ndk build来构建
libA
libB

因此,我为
libA
生成了这个Android.mk:

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)
现在,我使用了
boost
libA
,实现了
libB
libB
的Android.mk与
libA
非常相似,只是我添加了
libA
文件的导入,如下所示:

# Import libA
include $(CLEAR_VARS)
LOCAL_MODULE := libA
include ../../libA/jni/Android.mk
当我尝试创建
libB
时,有人报告我:

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.

我是否有办法检查是否已经定义了
boost\u-atomic
(比如
if(exists-boost\u-atomic)
),以确保只定义一次?或者我应该为所有的名字加后缀(最后是
boost\u system\u表示_libA
boost\u system\u表示_libB
),以防止冲突?或任何其他替代方案?

正如Alex Cohn所提到的,可以通过替换:

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

...

# boost import:
LOCAL_CPPFLAGS += -DHAVE_CONFIG_H -fexceptions -frtti
LOCAL_STATIC_LIBRARIES += boost_atomic
简单地说:

LOCAL_LDLIBS += ../dev/libcpp/boost/1.60.1/lib/libboost_atomic.a
这是可行的,但:

  • 引入编译警告:

    警告:/Users/jwalton/Android CryptoPP/jni/Android.mk:prng: 链接器标志中的非系统库:-lcryptopp-lstlport\u共享
    这可能会导致不正确的生成。尝试使用本地\u静态\u库
    或本地共享库,以列出 电流模块

  • 不适用于共享的第三方库

因此,我最终修复了这个问题,添加了一个新的mk文件,该文件特定于
libA
libB

libA
Android.mk
现在是:

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)

include libA.mk
LOCAL_PATH := $(call my-dir)

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

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

# build libA:
include $(BUILD_SHARED_LIBRARY)
# Import libA
include $(CLEAR_VARS)
LOCAL_MODULE := libA
include ../../libA/jni/libA.mk
libA
libA.mk
现在是:

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)

include libA.mk
LOCAL_PATH := $(call my-dir)

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

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

# build libA:
include $(BUILD_SHARED_LIBRARY)
# Import libA
include $(CLEAR_VARS)
LOCAL_MODULE := libA
include ../../libA/jni/libA.mk
libB
libB.mk
现在有:

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)

include libA.mk
LOCAL_PATH := $(call my-dir)

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

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

# build libA:
include $(BUILD_SHARED_LIBRARY)
# Import libA
include $(CLEAR_VARS)
LOCAL_MODULE := libA
include ../../libA/jni/libA.mk
因此,它导入
libA
,而不导入
boost
(也在
libB
Android.mk
中定义)

然后,没有任何警告,它可以顺利编译

我正在尝试为现有的应用程序自动生成Android.mk文件 构建环境。此环境有许多库链接到每个库 其他,也可能链接到第三方LIB(如boost)


为什么不使用,而不是痛苦地处理
Android.mk
文件?听起来独立的工具链非常适合您的情况。

您有一个NDK函数
$(模块获取列表)
。依靠它,您的libA/jni/Android.mk文件可能如下所示:

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)))
boost/Android.mk文件:

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))
最后,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)))
我不希望对第三方预构建的lib(如boost)有重复的定义,而是希望对每个lib使用单独的Android.mk定义,并在必要时包含它。这样,如果外部库被更新,我就有一个地方可以更改

更新:如果您不喜欢
$(如果…
语法,您可以使用

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

相反。

可以避免模块的重复定义,但在您的情况下,对于boost,只需添加
LOCAL\u LDLIBS+=../dev/libcpp/boost/1.60.1/lib/libboost\u atomic.a
而不是将其添加为LOCAL\u STATIC_LIBRARIES@AlexCohn:这将是一个很好的解决办法。我明天试试。我可以对共享库执行同样的操作吗?因为我想如果使用
libB
libA
使用
libC
我也会遇到同样的问题,
libA
将在编译
libC
时被定义两次(由
libB
libC
导入)。不,这不适用于非预构建的libs,无论如何,不应在LDLIBS中指定共享LIB。但通常很容易根据子目录的层次结构包含您的Android.mk文件。这避免了重复。@AlexCohn:谢谢,
LOCAL\u LDLIBS+=../dev/libcpp/boost/1.60.1/lib/libboost\u atomic。a
将在链接器中发出
非系统库的警告。如何摆脱这个警告?(仅尝试了
LOCAL_STATIC_LIBRARIES+=../dev/libcpp/boost/1.60.1/lib/libboost_atomic.a
,但无效)。您可以忽略此警告。它只与共享LIB相关。@jpo38是的,它们是。。。对于现有生成环境…-看起来您已经有了一些makefiles/构建脚本,不是吗?是的,我正在使用Visual Studio。它本身也支持Android target,但只支持专业版,我使用的是Express edition…@jpo38 Visual Studio不是我喜欢的,但无论如何,我相信即使是Express edition也能让你以某种方式使用自定义工具链。也许会给你一个主意,我去看看。但是,老实说,从CMake手动生成makefile并不是什么大事。我只编写了100行CMake代码就可以工作了(不久前,我已经这样做了,以便从CMake生成QtCreator项目文件,因为在QtCreator中导入CMake对我来说并不正常)。我完全控制发生的事情……很好,我设置了自己的变量来跟踪重复的定义,但这会使代码变得复杂(请参阅)。我会试试你的解决方案,但只在几周后(度假回来的时候)。不起作用。我尝试调用
ifndef$(modules\u get\u list)。$(LOCAL\u MODULE)
就在我执行
include$(预构建的静态库)
之后,这被评估为
true
。我错过了什么吗?很抱歉,这是
$(模块获取列表)
。请查看更新的答案。谢谢Alex。如何将其放入常规if语句中
ifeq($(调用集\是\成员,$(模块获取列表),$(本地\模块)),true)
失败,因为
$(调用集\是\成员,$(模块获取列表),$(本地\模块))
被计算为
T
不是
true
(对不起,我不是很熟悉)