2012-10-19 24 views
3

有沒有辦法在Eclipse中更改構建配置時強制Android NDK重建特定庫?Android NDK - 配置更改時強制庫重建

我正在構建一個使用Android NDK構建C++庫的Android項目。我使用Eclipse與Sequoyah插件。一切都建立並運作良好。

但是,我遇到了構建配置的問題。您可以通過右鍵單擊項目 - >屬性來管理構建配置,然後轉到C/C++構建部分。這允許您以某種方式創建大多數C++庫所依賴的傳統調試和發佈版本。

這裏是我的「調試」配置的例子:

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

這些工作得很好,只是當我再次打開和配置之間來回,它不會觸發重建我建立了圖書館。對於像Visual Studio這樣的東西,每個構建配置都會轉儲到不同的目錄,但是在Eclipse中,所有東西都會被轉儲到同一個目錄。我被迫實際改變相關的源文件來觸發重建。所以最終發生的是我最終在Debug配置中運行(例如),但鏈接到在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) 
+1

在您的'Android.mk'文件中,構建** libBootInfo **的部分不應該重新計算'LOCAL_PATH:= $(call my-dir)'。這是因爲'$(call my-dir)'實際上在此語句之前包含最後一個_make file_的路徑。如果你將所有的** libBootInfo **部分移動到你的'Android.mk'的頂部,它將會順利運行。 –

+1

另外,其他評論也不正確:_「包含文件直接相對於NDK根目錄」_。實際上,包含文件'LOCAL_C_INCLUDES'是相對於_current目錄_通常是項目根目錄。 –

回答

0

我從來沒有能夠得到這個工作很正確。最後我創建了一個批處理文件,它寫出了一個空的源文件。該批處理文件作爲Eclipse中構建步驟的一部分執行。然後我將該源文件作爲我的庫的一部分。由於每次構建時間戳都會發生變化,因此每次都會使用ndk重建該庫。我確信這個庫很小,大部分代碼都存在於其他庫中,因此編譯時間很短。

2

NDK編譯總是刷新。所以圖書館lib/armeabi。另一方面,obj目錄爲每個模塊包含用於調試和發佈版本的獨立樹。

不幸的是,如果您的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) 

UPDATE:其實,使用一個模塊的名稱後綴分開構建的配置是,在我眼裏,最好的解決辦法。這種方法允許您一次構建和部署多個配置。例如,當我必須優化一個庫到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-build命令行上提供NDK_OUT參數,例如,

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

這很簡單,如果您使用Eclipse來維護和選擇您的配置。這使Java可以輕鬆加載模塊,因爲它將始終具有相同的名稱。但是您一次只能部署單個配置。

+0

這似乎並不適合我。 NDK不會將* .so和* .a文件構建到單獨的目錄中。只有目標文件(* .o和* .o.d)被放入「obj/local/armeabi/objs-debug /」和「.../armeabi/objs /」中。實際編譯的庫全部在「obj/local/armeabi /」中找到,不考慮構建配置。更不用說,objs-debug文件夾似乎基於APP_OPTIM標誌,它只支持「發佈」和「調試」,但我們的引擎有更多的配置。 – Goose

+1

使用'$(MY_BUILD_CONFIG_EXTENSION)'實際上是一個很好的解決方案。我的想法是。這或多或少是我喜歡的項目。這可以非常好地控制實際部署到設備的配置(_hint:_可能不止_one!)。有關其他解決方案,請參閱答案的**更新**部分。 –

+0

try/catch解決方案對我來說似乎很棒,但我不清楚的一件事是如何在調試會話期間停止其他版本的libs部署到設備(例如,在Eclipse中打擊F11)。例如,在「... \ obj \ local \ armeabi」中我有「radgamed.so」和「radgamer.so」。如果我運行在Debug配置中,我希望它只能找到以「d」結尾的庫,但看起來以「r」結尾的庫也會被部署,所以我的try/catch只會在它嘗試的第一個庫上成功。順便說一句:謝謝你的詳細解答!對此,我真的非常感激! – Goose