将 VTK 与 NDK r17c 上的 ndk-build 链接会导致 'undefined references' 错误
Linking VTK with ndk-build on NDK r17c results with 'undefined references' errors
我用 Android NDK r17c 在 Linux 上构建了 VTK,结果是 54 个静态 (.a) 库,总计 600+ MB。现在,我已将这些库导入到我的 AndroidStudio 3.3 项目中,我想在我的本机代码中使用构建的库。在 Android Studio 中,我使用相同版本的 NDK (r17c)。
在 AndroidStudio 中,我创建了使用 VTK 的新模块,在该模块中,我使用 ndk-build 构建库。模块结构为:
...
|--jni/
|--|--include/
|--|--|--vtkAbstractArray.h
|--|--|--vtkAbstractCellLinks.h
|--|--|-- ...
|--|--lib/
|--|--|--arm64-v8a/
|--|--|--|--libvtkCommonColor-8.9.0.a
|--|--|--|--libvtkCommonComputationalGeometry-8.9.0.a
|--|--|--|--...
|--|--Application.mk
|--|--Android.mk
|--|--vtk-lib.cpp
我在我的 vtk-lib.cpp 文件中使用 VTK 库(我从 Java 代码访问)。
为了让它工作,我没有为所有支持的 android 架构构建库(但只为我的 arm64-v8a设备),所以我定义了一个 Application.mk 文件,如下所示:
APP_STL := c++_static
API_ABI := arm64-v8a
在我的 Android.mk 文件中,我定义了 54 个模块 和 PREBUILT_STATIC_LIBRARY
(每个模块一个54 个构建的 .a 文件)。最后,我正在构建一个 BUILD_SHARED_LIBRARY
和 vtk-lib.cpp 文件,可以从 Java:
访问
LOCAL_PATH := $(call my-dir)
#prepare vtk-common-color
include $(CLEAR_VARS)
LOCAL_MODULE := vtk-common-color
LOCAL_SRC_FILES := lib/$(TARGET_ARCH_ABI)/libvtkCommonColor-8.90.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_STATIC_LIBRARY)
#...53 more modules for every .a static library
include $(CLEAR_VARS)
LOCAL_SRC_FILES := vtk-lib.cpp
LOCAL_MODULE := vtk-lib
LOCAL_STATIC_LIBRARIES := vtk-common-color ... # 53 more module names
LOCAL_CPP_FEATURES := rtti exceptions
LOCAL_CPPFLAGS += --std=c++11
include $(BUILD_SHARED_LIBRARY)
当我尝试构建应用程序时,出现了一堆关于 undefined reference
的错误,如下所示:
Build command failed.
Error while executing process [some path]\Android\sdk\ndk-bundle\ndk-
build.cmd with arguments {NDK_PROJECT_PATH=null
APP_BUILD_SCRIPT=[some path]\src\main\jni\Android.mk NDK_APPLICATION_MK=
[some path]\src\main\jni\Application.mk APP_ABI=arm64-v8a
NDK_ALL_ABIS=arm64-v8a NDK_DEBUG=1 APP_PLATFORM=android-23
NDK_OUT=[some path]/build/intermediates/ndkBuild/debug/obj
NDK_LIBS_OUT=[some path]\build\intermediates\ndkBuild\debug\lib [some
path]build/intermediates/ndkBuild/debug/obj/local/arm64-v8a/libvtk-lib.so}
[arm64-v8a] Compile++ : vtk-lib <= vtk-lib.cpp
[arm64-v8a] SharedLibrary : libvtk-lib.so
[some path]/src/main/jni/lib/arm64-v8a/libvtkFiltersSources-
8.90.a(vtkConeSource.cxx.o): In function `vtkConeSource::New()':
[some path ON LINUX]/VTK/Filters/Sources/vtkConeSource.cxx:30: undefined
reference to `vtkObjectBase::InitializeObjectBase()'
[some path]/src/main/jni/lib/arm64-v8a/libvtkFiltersSources-
8.90.a(vtkConeSource.cxx.o): In function
`vtkConeSource::vtkConeSource(int)':
[some path ON LINUX]/VTK/Filters/Sources/vtkConeSource.cxx:35: undefined
reference to `vtkPolyDataAlgorithm::vtkPolyDataAlgorithm()'
#etc etc many more errors
我遇到了 this github thread 所以我尝试使用 LOCAL_WHOLE_STATIC_LIBRARIES
而不是 LOCAL_STATIC_LIBRARIES
,不同版本的 LOCAL_LDLIBS
和 LOCAL_LDFLAGS
但仍然没有运气.
有什么帮助吗?
这很可能不是循环依赖,而只是列表中的错误顺序。
如果所有undefined references都来自VTK库,您可以简单地找到LOCAL_STATIC_LIBRARIES的工作顺序,一一消除这些link错误。例如。第一个错误意味着 vtkCommonCore
必须在 vtkFiltersSources
之后,第二个 – vtkCommonExecutionModel
也应该在 vtkFiltersSources
之后。
VTK 支持 CMake,因此如果您使用 CMake 而不是 Android.mk 构建脚本,可能更容易获得正确的依赖顺序。
我最终使用 CMake 而不是 ndk-build。
我需要将此代码添加到我模块的 build.gradle:
android {
...
defaultConfig {
...
externalNativeBuild {
cmake {
cppFlags "-std=c++11"
arguments "-DANDROID_CPP_FEATURES=rtti exceptions",
"-DANDROID_STL=gnustl_shared"
abiFilters 'arm64-v8a'
}
}
}
...
externalNativeBuild {
cmake {
path "src/main/jni/CMakeLists.txt"
}
}
}
而且,我的 CMakeLists.txt 看起来像这样:
cmake_minimum_required(VERSION 3.4.1)
set(LIB_DIR ${PROJECT_SOURCE_DIR}/lib/${ANDROID_ABI})
add_library(vtk-common-color STATIC IMPORTED)
set_target_properties(vtk-common-color
PROPERTIES IMPORTED_LOCATION
${LIB_DIR}/libvtkCommonColor-8.90.a)
#53 more libraries
add_library( vtk-lib SHARED ${PROJECT_SOURCE_DIR}/vtk-lib.cpp)
target_include_directories(vtk-lib PRIVATE ${PROJECT_SOURCE_DIR}/include)
target_link_libraries(
vtk-lib
-Wl,--start-group -L ${TARGET_OUT}
vtk-common-color
#53 more libraries names
-Wl,--end-group
)
我用 Android NDK r17c 在 Linux 上构建了 VTK,结果是 54 个静态 (.a) 库,总计 600+ MB。现在,我已将这些库导入到我的 AndroidStudio 3.3 项目中,我想在我的本机代码中使用构建的库。在 Android Studio 中,我使用相同版本的 NDK (r17c)。
在 AndroidStudio 中,我创建了使用 VTK 的新模块,在该模块中,我使用 ndk-build 构建库。模块结构为:
...
|--jni/
|--|--include/
|--|--|--vtkAbstractArray.h
|--|--|--vtkAbstractCellLinks.h
|--|--|-- ...
|--|--lib/
|--|--|--arm64-v8a/
|--|--|--|--libvtkCommonColor-8.9.0.a
|--|--|--|--libvtkCommonComputationalGeometry-8.9.0.a
|--|--|--|--...
|--|--Application.mk
|--|--Android.mk
|--|--vtk-lib.cpp
我在我的 vtk-lib.cpp 文件中使用 VTK 库(我从 Java 代码访问)。
为了让它工作,我没有为所有支持的 android 架构构建库(但只为我的 arm64-v8a设备),所以我定义了一个 Application.mk 文件,如下所示:
APP_STL := c++_static
API_ABI := arm64-v8a
在我的 Android.mk 文件中,我定义了 54 个模块 和 PREBUILT_STATIC_LIBRARY
(每个模块一个54 个构建的 .a 文件)。最后,我正在构建一个 BUILD_SHARED_LIBRARY
和 vtk-lib.cpp 文件,可以从 Java:
LOCAL_PATH := $(call my-dir)
#prepare vtk-common-color
include $(CLEAR_VARS)
LOCAL_MODULE := vtk-common-color
LOCAL_SRC_FILES := lib/$(TARGET_ARCH_ABI)/libvtkCommonColor-8.90.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_STATIC_LIBRARY)
#...53 more modules for every .a static library
include $(CLEAR_VARS)
LOCAL_SRC_FILES := vtk-lib.cpp
LOCAL_MODULE := vtk-lib
LOCAL_STATIC_LIBRARIES := vtk-common-color ... # 53 more module names
LOCAL_CPP_FEATURES := rtti exceptions
LOCAL_CPPFLAGS += --std=c++11
include $(BUILD_SHARED_LIBRARY)
当我尝试构建应用程序时,出现了一堆关于 undefined reference
的错误,如下所示:
Build command failed.
Error while executing process [some path]\Android\sdk\ndk-bundle\ndk-
build.cmd with arguments {NDK_PROJECT_PATH=null
APP_BUILD_SCRIPT=[some path]\src\main\jni\Android.mk NDK_APPLICATION_MK=
[some path]\src\main\jni\Application.mk APP_ABI=arm64-v8a
NDK_ALL_ABIS=arm64-v8a NDK_DEBUG=1 APP_PLATFORM=android-23
NDK_OUT=[some path]/build/intermediates/ndkBuild/debug/obj
NDK_LIBS_OUT=[some path]\build\intermediates\ndkBuild\debug\lib [some
path]build/intermediates/ndkBuild/debug/obj/local/arm64-v8a/libvtk-lib.so}
[arm64-v8a] Compile++ : vtk-lib <= vtk-lib.cpp
[arm64-v8a] SharedLibrary : libvtk-lib.so
[some path]/src/main/jni/lib/arm64-v8a/libvtkFiltersSources-
8.90.a(vtkConeSource.cxx.o): In function `vtkConeSource::New()':
[some path ON LINUX]/VTK/Filters/Sources/vtkConeSource.cxx:30: undefined
reference to `vtkObjectBase::InitializeObjectBase()'
[some path]/src/main/jni/lib/arm64-v8a/libvtkFiltersSources-
8.90.a(vtkConeSource.cxx.o): In function
`vtkConeSource::vtkConeSource(int)':
[some path ON LINUX]/VTK/Filters/Sources/vtkConeSource.cxx:35: undefined
reference to `vtkPolyDataAlgorithm::vtkPolyDataAlgorithm()'
#etc etc many more errors
我遇到了 this github thread 所以我尝试使用 LOCAL_WHOLE_STATIC_LIBRARIES
而不是 LOCAL_STATIC_LIBRARIES
,不同版本的 LOCAL_LDLIBS
和 LOCAL_LDFLAGS
但仍然没有运气.
有什么帮助吗?
这很可能不是循环依赖,而只是列表中的错误顺序。
如果所有undefined references都来自VTK库,您可以简单地找到LOCAL_STATIC_LIBRARIES的工作顺序,一一消除这些link错误。例如。第一个错误意味着 vtkCommonCore
必须在 vtkFiltersSources
之后,第二个 – vtkCommonExecutionModel
也应该在 vtkFiltersSources
之后。
VTK 支持 CMake,因此如果您使用 CMake 而不是 Android.mk 构建脚本,可能更容易获得正确的依赖顺序。
我最终使用 CMake 而不是 ndk-build。
我需要将此代码添加到我模块的 build.gradle:
android {
...
defaultConfig {
...
externalNativeBuild {
cmake {
cppFlags "-std=c++11"
arguments "-DANDROID_CPP_FEATURES=rtti exceptions",
"-DANDROID_STL=gnustl_shared"
abiFilters 'arm64-v8a'
}
}
}
...
externalNativeBuild {
cmake {
path "src/main/jni/CMakeLists.txt"
}
}
}
而且,我的 CMakeLists.txt 看起来像这样:
cmake_minimum_required(VERSION 3.4.1)
set(LIB_DIR ${PROJECT_SOURCE_DIR}/lib/${ANDROID_ABI})
add_library(vtk-common-color STATIC IMPORTED)
set_target_properties(vtk-common-color
PROPERTIES IMPORTED_LOCATION
${LIB_DIR}/libvtkCommonColor-8.90.a)
#53 more libraries
add_library( vtk-lib SHARED ${PROJECT_SOURCE_DIR}/vtk-lib.cpp)
target_include_directories(vtk-lib PRIVATE ${PROJECT_SOURCE_DIR}/include)
target_link_libraries(
vtk-lib
-Wl,--start-group -L ${TARGET_OUT}
vtk-common-color
#53 more libraries names
-Wl,--end-group
)