3

在 Eclipse 中更改构建配置时,有没有办法强制 Android NDK 重新构建特定库?

我正在使用 Android NDK 构建一个 Android 项目来构建 C++ 库。我正在使用带有 Sequoyah 插件的 Eclipse。一切都已设置并且运行良好。

但是,我遇到了构建配置的问题。您可以通过右键单击项目-> 属性来管理构建配置,然后转到 C/C++ 构建部分。这允许您创建大多数 C++ 库以某种方式依赖的传统调试和发布版本。

这是我的“调试”配置的示例:

V=1 NDK_DEBUG=1 NDK_APPLICATION_MK=config/debug/Application.mk

这些运行良好,除了当我在配置之间来回切换时,它不会触发我正在构建的库的重建。这对于像 Visual Studio 这样的东西来说是可以预期的,其中每个构建配置都转储到不同的目录,但在 Eclipse 中,所有内容都会转储到同一个目录。我被迫实际更改相关的源文件以触发重建。所以最终发生的事情是我最终在调试配置中运行(例如),但链接到在 Release 中构建的库。

所以我的问题是:有没有办法在更改配置时强制 NDK 重建库?我知道我可以添加 -B 命令,但是每次都会重建所有内容。如果我可以只为一个特定的库(在本例中为 libBootInfo)进行重建,我每次都可以重建。

这是我的根 Android.mk 文件的样子:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := game$(MY_BUILD_CONFIG_EXTENSION)

# Include files are relative to the NDK root directly (fix by prepending with $(LOCAL_PATH))
# Source files are relative $(LOCAL_PATH)

#LOCAL_LDLIBS    := -landroid

# Add all source file names to be included in lib separated by a whitespace
LOCAL_SRC_FILES :=  ../../../../../../engine/code/main/mainandroid.cpp

# Module dependencies are expressed with LOCAL_STATIC_LIBRARIES and LOCAL_SHARED_LIBRARIES.
# we're building the "main" entry point, so it doesn't depend on much
LOCAL_STATIC_LIBRARIES := libDebug$(MY_BUILD_CONFIG_EXTENSION) libCore$(MY_BUILD_CONFIG_EXTENSION)

include $(BUILD_SHARED_LIBRARY)

$(call import-module,libBdCore)
$(call import-module,libDebug)

##################################################################
## In addition to the core game library, we also build another
## *.so file here: "libBootInfo". This very small library is used
## by Java to find out which version of game to load based on
## the current build configuration.
##

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := libBootInfo

# Add all source file names to be included in lib separated by a whitespace
# TODO: This path is relative to "android-ndk\build\core" which seems
#       different from the LOCAL_SRC_FILES in game above. It seems like
#       the build process leaves us in a different directory than we started.
#       We make need to look into a way to make sure that this path always 
#       works regardless of what came before it.
#
LOCAL_SRC_FILES := ../../../../engine/code/main/bootinfo.cpp

include $(BUILD_SHARED_LIBRARY)
4

2 回答 2

2

NDK 构建始终刷新.so中的库lib/armeabiobj另一方面,该目录包含用于每个模块的调试和发布构建的单独树。

Android.mk不幸的是,如果你做了一些 tge 框架不支持的事情,那么很容易搞砸这个设置。

例如,在您的情况下,cpp 文件 ( ../../../..) 的长上行路径可能不是一个好主意。我建议LOCAL_PATH为每个模块设置,并避免../LOCAL_SRC_FILES.

这是我对 Android.mk 的建议更改:

ANDROID_MK_PATH := $(call my-dir)
LOCAL_PATH := $(ANDROID_MK_PATH)/../../../engine/code/main

include $(CLEAR_VARS)

LOCAL_MODULE := game$(MY_BUILD_CONFIG_EXTENSION)
LOCAL_SRC_FILES :=  mainandroid.cpp
LOCAL_STATIC_LIBRARIES := libDebug$(MY_BUILD_CONFIG_EXTENSION) libCore$(MY_BUILD_CONFIG_EXTENSION)

include $(BUILD_SHARED_LIBRARY)

##################################################################
## In addition to the core game library, we also build another
## *.so file here: "libBootInfo". This very small library is used
## by Java to find out which version of game to load based on
## the current build configuration.
##

include $(CLEAR_VARS)

LOCAL_MODULE := libBootInfo
LOCAL_SRC_FILES := bootinfo.cpp

include $(BUILD_SHARED_LIBRARY)

$(call import-module,libBdCore)
$(call import-module,libDebug)

更新:实际上,在我看来,使用模块名称后缀来分隔构建配置是最好的解决方案。这种方法允许您一次构建和部署多个配置。例如,当我必须针对 Tegra(不带 Neon)或 Snapdragon(带 Neon)优化库时,我会使用它:直到最近,在 Play 商店中放置两个单独的 APK 并不容易,因此我将两者都打包libv-neon.solibv-tegra.so进入lib/armeabi-v7a.

我不知道你的BootInfo库包含什么逻辑,但如果你只部署一个库,你可以避免在 Java 类静态构造函数中使用以下代码的所有麻烦:

static {
    boolean loaded = false;
    while (!loaded) {
        try {
            System.loadLibrary("game" + nextExtensionAttempt);
            loaded = true;
        } 
        catch (Exception ex) {
        }
    }
}

另一种方法是覆盖输出目录./obj。为此,您可以将以下行添加到Application.mk文件中:

NDK_APP_OUT := obj$(MY_BUILD_EXTENSION)

这样,所有.obj.a.so文件(在它们被安装到之前libs/armeabi)将被放置在每个配置的单独目录中。更简单的是,您可以在命令行上提供NDK_OUT参数,例如ndk-build

ndk-build V=1 NDK_OUT=obj${MY_BUILD_EXTENSION}

如果您使用 Eclipse 来维护和选择您的配置,这将非常容易。这使得 Java 很容易加载模块,因为它总是具有相同的名称。但是您一次只能部署一个配置。

于 2012-10-20T10:06:47.777 回答
0

我从来没有能够让这个工作完全正确。最后我只是创建了一个批处理文件,它写出了一个空的源文件。该批处理文件在 Eclipse 中作为构建步骤的一部分执行。然后我将该源文件包含在我的库中。由于每次构建时时间戳都会更改,因此它会欺骗 ndk 每次都重新构建该库。我确保该库保持较小,并且大多数代码都存在于其他库中,从而使构建时间非常短。

于 2012-11-15T17:48:08.247 回答