2013-06-27 46 views
12

所以我有,我已經放在$PROJECT/jni目錄巨大現有的C項目。該項目通常通過運行一個配置腳本來創建Makefiles,然後允許通過make編譯該項目。如何將現有的生成文件與Android NDK

這個項目是相當大的,並具有包含源文件和頭文件許多目錄。

我想我在這裏的Android.mk應該如何工作缺少一個基本的瞭解。它應該替換當前用於編譯項目的configure和makefile嗎?或者,我會將生成的makefile從我的配置腳本合併到Android.mk?他們提供的例子很少,只有少數源文件。我jni目錄看起來更像是:

jni/ 
    folder1/subfolder1 
    folder1/subfolder2 
    folder1/source 
    folder2/source 
    ..... 
    foldern/source 
    configure/ 
    configure/configure.sh 
    Makefile 
    Android.mk 

生成的makefile是相當廣泛的(配置量好,並具有一個在每一個目錄下),所以我有點失去了對如何處理這個。

編輯:

的主要問題是,隨着NDK附帶的例子是簡單的例子。他們在頂級jni目錄中有3-5個源文件。我的問題是,這是一個龐大的項目,配置複雜,有4個頂級文件夾,每個文件夾都有很多子目錄。我不能簡單地將源代碼移動到jni文件夾並運行ndk編譯器。

回答

12

要回答你的問題,是的Android.mk的Android構建系統。 Google幾乎沒有提到這個文件的「語言」是作爲GNU make宏來實現的。文檔希望你用這些宏來描述你的項目。他們處理所有蹩腳的交叉編譯細節。我相當確信Google隨着開發工具的發展,採取了這種方法來提高Android.mk文件的正向可移植性。

結果是(我知道你不會想聽到這個)最好的答案可能是從頭開始爲你的大項目編寫一個合適的NDK Android.mk

This article列出了同樣的意見,我移植了大約800個文件和300k SLOC庫。不幸的是我燒了差不多兩週的時間,得出了相同的結論:交叉編譯導致至少一些configure腳本失敗(導致錯誤的config.h文件)。我「發明了」幾乎與他在文章中使用的技術相同。但是,即使我得到了一個乾淨的構建,所產生的靜態庫不能完全工作。調試時間沒有獲得有用的信息。 [警告:我不是那種配置工具專家。古魯可能會發現我的錯誤。所以它就是了。]我花了幾天的時間創建一個乾淨的Android.mk。最終的庫首次運行所有測試。它已經通過多種開發工具徹底移植。

不幸的是,建立一個使用configure但沒有自動工具的庫意味着爲目標環境手動構建自己的config.h。這可能不像聽起來那麼糟糕。 IME系統傾向於在其實際使用的環境中定義更多的環境。清楚地瞭解真正的依賴關係可能會彌補未來重構過程中繁瑣的工作。

從文章的簡要說明了一切:

Autotool好只在GNU系統和使用它的交叉編譯可以很乏味,混亂,容易出錯的,甚至是不可能的。這裏描述的方法是一種黑客攻擊,應該使用您自己的風險。

對不起,我沒有更積極的建議。

+0

我完全同意你的觀察。在交叉編譯環境中,從config.h.in生成'config.h'是不可能的。然而,運行配置本身'可能'工作,但這是一個完整的其他野獸:)。 – Samveen

3

下面是周圍做的事情的其他方式的解決方案:建立 兩個外部庫,並從標準的Makefile Android包。

作爲先決條件,您需要安裝做的命令行 Android開發所需要的一切:

  • 一個獨立的工具鏈,包括看到在Android NDK的文件;
  • 螞蟻。

的例子的結構是:

:爲外部庫 和用於在與一個Makefile 在每個目錄和頂層相同的水平在Android源的目錄,遞歸生成文件的目錄
Makefile 
mylib/ 
    Makefile 
android/ 
    Makefile 

mylib/Makefile建立一個靜態庫:

AR=/path/to/standalone/bin/arm-linux-androideabi-ar 
CC=/path/to/standalone/bin/arm-linux-androideabi-gcc 

libmylib.a: mylib.o 
    $(AR) rcs libmylib.a mylib.o 

mylib.o: mylib.c 
    $(CC) -c mylib.c -o mylib.o 

android/Makefile是提供規則建立Android包:

  • 我們需要依賴項來複制mylib;
  • 我們使用一個jni/ndkmake.c文件來調用換到mylib並提供Android的具體的東西;
  • Android包依賴於Java源代碼和對共享庫。

的生成文件提供了兩個目標:release(默認值)和debug建立或者釋放包或調試一個。

NDK_BUILD=/path/to/ndk-build 
JAVASRC=src/com/example/ndkmake/NdkMake.java 

release: bin/NdkMake-release-unsigned.apk 

debug: bin/NdkMake-debug.apk 

bin/NdkMake-release-unsigned.apk: libs/armeabi/libndkmake.so $(JAVASRC) 
ant release 

bin/NdkMake-debug.apk: libs/armeabi/libndkmake.so $(JAVASRC) 
ant debug 

libs/armeabi/libndkmake.so: jni/ndkmake.c jni/libmylib.a 
$(NDK_BUILD) 

jni/libmylib.a: ../mylib/libmylib.a 
cp ../mylib/libmylib.a jni/libmylib.a 

Android.mk文件提供了規則,包括在生成靜態庫,作爲預建。 我們使用LOCAL_EXPORT_C_INCLUDES包含來自mylib庫的標題。

LOCAL_PATH := $(call my-dir) 

include $(CLEAR_VARS) 
LOCAL_MODULE := ndkmake 
LOCAL_SRC_FILES := ndkmake.c 
LOCAL_STATIC_LIBRARIES := mylib-prebuilt 
include $(BUILD_SHARED_LIBRARY) 

include $(CLEAR_VARS) 
LOCAL_MODULE := mylib-prebuilt 
LOCAL_SRC_FILES := libmylib.a 
LOCAL_EXPORT_C_INCLUDES := ../mylib/ 
include $(PREBUILT_STATIC_LIBRARY) 

現在,我們只需要一個頂層Makefile構建兩個子目錄:

all: libmylib package 

libmylib: 
    cd mylib && $(MAKE) 

package: 
    cd android && $(MAKE) 

任何改變圖書館,到JNI來源或Java源代碼將觸發重建的 包裹。

+0

感謝您的建議。你能否澄清幾點:1)「爲NDK添加構建規則」是什麼意思?構建規則是什麼?你的意思是在Android.mk文件中通常指定的命令? 2)我在哪裏可以找到關於這個獨立工具鏈的信息?謝謝! – thatidiotguy

+0

您可以找到有關隨NDK的文檔中獨立的工具鏈的更多信息,有一個在線副本,在這裏:http://www.kandroid.org/ndk/docs/STANDALONE-TOOLCHAIN.html至於NDK構建規則,我的意思是保持Android.mk,但從你的Makefile運行ndk-build(參見我的示例) – Guillaume

+0

我可以直接鏈接到編譯的c對象嗎?例如,如果我現在使用我的c軟件,它會輸出3個'.so'文件。有沒有辦法用鏈接到庫文件中的對象的JNI方法創建C文件? – thatidiotguy

4

我的回答最好與Gene的答案配合使用。

./configure創建配置文件是基於編譯(可能運行)每個測試的代碼爲C的小片段。可以在交叉編譯環境中成功測試僅編譯測試。但是,編譯運行測試無法在交叉編譯環境中運行。每個測試的成功在config.h.in模板中設置相應的變量以創建config.h

因此,要開始轉換過程,你需要設置CPPCCLD等工具交叉編譯器的工具集(大概是從NDK的那些),然後運行./configure。完成此操作後,您需要更正config.h以符合您的目標環境。 這是您最關鍵和最容易出錯的步驟。

至於Android.mk,它遵循相當接近Makefile.am可以很容易地轉化成它的格式。您可以忽略Makefile.inMakefile,因爲從Makefile.am產生。

要採取的file(版本5.11),我跑了下列選項配置爲例,

./configure --host arm-toshiba-linux-androideabi --build x86_64-linux-gnu \ 
      --prefix=/data/local/ host_alias=arm-linux-androideabi \ 
      "CFLAGS=--sysroot=~/ndk/platforms/android-8/arch-arm -Wall -Wextra" \ 
      "CPPFLAGS=--sysroot=~/ndk/platforms/android-8/arch-arm" \ 
      CPP=arm-linux-androideabi-cpp 

下一步是採取src/Makefile.am如下:

MAGIC = $(pkgdatadir)/magic 
lib_LTLIBRARIES = libmagic.la 
include_HEADERS = magic.h 

bin_PROGRAMS = file 

AM_CPPFLAGS = -DMAGIC='"$(MAGIC)"' 
AM_CFLAGS = $(CFLAG_VISIBILITY) @[email protected] 

libmagic_la_SOURCES = magic.c apprentice.c softmagic.c ascmagic.c \ 
     encoding.c compress.c is_tar.c readelf.c print.c fsmagic.c \ 
     funcs.c file.h readelf.h tar.h apptype.c \ 
     file_opts.h elfclass.h mygetopt.h cdf.c cdf_time.c readcdf.c cdf.h 
libmagic_la_LDFLAGS = -no-undefined -version-info 1:0:0 
if MINGW 
MINGWLIBS = -lgnurx -lshlwapi 
else 
MINGWLIBS = 
endif 
libmagic_la_LIBADD = $(LTLIBOBJS) $(MINGWLIBS) 

file_SOURCES = file.c 
file_LDADD = libmagic.la 
CLEANFILES = magic.h 
EXTRA_DIST = magic.h.in 
HDR= $(top_srcdir)/src/magic.h.in 
BUILT_SOURCES = magic.h 

magic.h:  ${HDR} 
     sed -e "s/X.YY/$$(echo @[email protected] | tr -d .)/" < ${HDR} > [email protected] 

,創造從這個Android.mk

最後和最重要的一步是修改config.h以準確地反映目標系統的狀態。這將是一個手動過程,我無法給出解決方法,主要涉及到查看configure.log,查看頭文件和「調用」Google。這項勞動的成果可用on XDA

相關問題