在維護舊專案時發現,OpenCV 升級到 2.4.11 版本後,原本的 Android.mk 建構腳本不再適用,編譯過程中噴出大量錯誤。其中一個關鍵錯誤訊息為:
Android NDK: WARNING:jni/Android.mk:ProcessImg: non-system libraries in linker flags: -lopencv_java
Android NDK: This is likely to result in incorrect builds. Try using LOCAL_STATIC_LIBRARIES
Android NDK: or LOCAL_SHARED_LIBRARIES instead to list the library dependencies of the
Android NDK: current module
雖然 .so 檔案仍能生成並安裝,但產出的函式庫僅約 330KB,遠小於預期的 4.5MB 左右。執行時會找不到 libopencv.so,導致應用程式崩潰。
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
ifeq ("$(wildcard $(OPENCV_MK_PATH))","")
include /Users/yanzi/work/OpenCV-android-sdk/sdk/native/jni/OpenCV.mk
else
include $(OPENCV_MK_PATH)
endif
LOCAL_LDLIBS += -lm -llog
LOCAL_MODULE := ProcessImg
LOCAL_SRC_FILES := DetectFace_JNI.cpp \
src/copyToAssets.cpp \
src/detectFace.cpp
include $(BUILD_SHARED_LIBRARY)
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# 關鍵設定:必須放在 include OpenCV.mk 之前
OpenCV_INSTALL_MODULES:=on
OPENCV_CAMERA_MODULES:=off
OPENCV_LIB_TYPE:=STATIC
ifeq ("$(wildcard $(OPENCV_MK_PATH))","")
include /Users/yanzi/work/OpenCV-android-sdk/sdk/native/jni/OpenCV.mk
else
include $(OPENCV_MK_PATH)
endif
LOCAL_MODULE := ProcessImg
LOCAL_SRC_FILES := DetectFace_JNI.cpp \
src/copyToAssets.cpp \
src/detectFace.cpp
LOCAL_LDLIBS += -lm -llog
include $(BUILD_SHARED_LIBRARY)
關鍵在於三行設定,特別是 OPENCV_LIB_TYPE:=STATIC:
OpenCV_INSTALL_MODULES:=on - 安裝 OpenCV 模組OPENCV_CAMERA_MODULES:=off - 關閉相機模組(可減小體積)OPENCV_LIB_TYPE:=STATIC - 靜態連結 OpenCV,這是關鍵重要提醒:這三行必須放在 include OpenCV.mk 之前,否則不生效!
加上這三行後,OpenCV 會以靜態函式庫方式編譯進最終的 .so 檔案中,不再依賴外部的 libopencv_java.so,解決了執行時找不到函式庫的問題,同時也消除了 NDK 的警告訊息。
另一個常見錯誤是 LOCAL_LDLIBS += -lm -llog 被錯寫成 LOCAL_LDLIBS := -lm -llog(使用 := 而非 +=),這會覆蓋掉 OpenCV.mk 中預設的連結器旗標,同樣會導致建構異常。