Android NDK链接,“未定义引用”与静态库链接时

时间:2014-11-26 05:09:13

标签: android makefile android-ndk

环境

  • 机器人-NDK-R 10c中
  • VisualGDB
  • Windows x64

用例1

  • ADB Cmdline可执行文件(无Java / APK)由多个C ++文件组成
  • 编译可执行文件" APP_STL:= gnustl_static"在Application.mk
  • 已成功编译并运行可执行文件

用例2

  • 用例1的ADB工具分为两个独立的项目
    • 封装通用功能的静态库
    • ADB工具减去移出静态库的功能
  • 可执行文件& static Lib编译为" APP_STL:= gnustl_static"在Application.mk
  • 使用LOCAL_LDLIBS编译ADB Exe:= -L $(PATH_TO_STATIC_LIB)-lstaticlib
  • 编译失败,"未定义引用`std :: terminate()'"链接器错误

手头的问题

将所有CPP文件编译为一个项目时,一切正常,没有链接器错误 当将逻辑吐入一个瘦的可执行文件和一个staticlib(可执行文件被链接)时,我得到了一个"未定义的对`std :: terminate()'"的引用。链接器错误。

在我看来好像" gnustl_static"尽管" APP_STL:= gnustl_static"并未与可执行文件链接。被指定......

我在这里缺少什么?有没有办法强迫“gnustl_static”#39;链接?

用于参考的make文件:

Makefile,其中所有文件都是同一个可执行文件的一部分(WORKING)

Application.mk

APP_STL := gnustl_static
APP_ABI := all
APP_CFLAGS := -std=gnu++11
APP_CPPFLAGS := -std=gnu++11
NDK_TOOLCHAIN_VERSION := 4.9

Android.mk

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE    := ScreenCapSvc
LOCAL_SRC_FILES := ScreenCapSvc.cpp SnapshotController.cpp SimpleTCPStream.cpp SocketsServer.cpp uuids.cpp
LOCAL_C_INCLUDES := 
LOCAL_STATIC_LIBRARIES := 
LOCAL_SHARED_LIBRARIES := 
LOCAL_LDLIBS := -llog
LOCAL_CFLAGS := 
LOCAL_CPPFLAGS := 
LOCAL_LDFLAGS := 
COMMON_SRC_FILES := $(LOCAL_SRC_FILES)
include $(BUILD_EXECUTABLE)

Makefile文件被分成静态库和可链接lib的可执行文件 (不工作)

可执行的Application.mk

APP_STL := gnustl_static
APP_ABI := all
APP_CFLAGS := -std=gnu++11
APP_CPPFLAGS := -std=gnu++11
NDK_TOOLCHAIN_VERSION := 4.9

可执行Android.mk

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE    := ScreenCapSvc
LOCAL_SRC_FILES := ScreenCapSvc.cpp SnapshotController.cpp
LOCAL_C_INCLUDES := 
LOCAL_STATIC_LIBRARIES := 
LOCAL_SHARED_LIBRARIES := 
LOCAL_LDLIBS := -llog -L$(PATH_TO_STATIC_LIB) -lCollections_statis
LOCAL_CFLAGS := 
LOCAL_CPPFLAGS := 
LOCAL_LDFLAGS := 
COMMON_SRC_FILES := $(LOCAL_SRC_FILES)
include $(BUILD_EXECUTABLE)

Static Lib Application.mk

APP_STL := gnustl_static
APP_ABI := all
APP_CFLAGS := -std=gnu++11
APP_CPPFLAGS := -std=gnu++11
NDK_TOOLCHAIN_VERSION := 4.9
APP_MODULES := Collections-static Collections-shared

Static Lib Android.mk

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE    := Collections-shared
LOCAL_SRC_FILES := SimpleTCPStream.cpp SocketsServer.cpp uuids.cpp
LOCAL_C_INCLUDES :=
LOCAL_STATIC_LIBRARIES :=
LOCAL_SHARED_LIBRARIES :=
LOCAL_LDLIBS := -llog
LOCAL_CFLAGS :=
LOCAL_CPPFLAGS :=
LOCAL_LDFLAGS :=
COMMON_SRC_FILES := $(LOCAL_SRC_FILES)
include $(BUILD_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE    := Collections-static
LOCAL_SRC_FILES :=  $(COMMON_SRC_FILES)
include $(BUILD_STATIC_LIBRARY)

2 个答案:

答案 0 :(得分:3)

这不是NDK构建系统中的错误,但是如何使用它是一个问题。

如果你运行ndk-build V=1,你会看到它试图执行的实际命令,你发现它已经尝试在gnustl_static中链接,但它在你自己的静态链接之前链接它图书馆。链接器仅按照链接器命令行中指定的顺序尝试库,这意味着它不会尝试使用先前指定的gnustl_static库来解析以后库中的未定义引用。

这里正确的解决方案是不使用LOCAL_LDLIBS强制链接到静态库,而是使用NDK提供的基础结构链接到静态库。也就是说,像这样更改你的可执行文件Android.mk:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE           := ScreenCapSvc
LOCAL_SRC_FILES        := ScreenCapSvc.cpp SnapshotController.cpp
LOCAL_STATIC_LIBRARIES := Collections_static
LOCAL_LDLIBS           := -llog
include $(BUILD_EXECUTABLE)

include $(CLEAR_VARS)
LOCAL_MODULE    := Collections_static
LOCAL_SRC_FILES := $(PATH_TO_STATIC_LIB)/libCollections_static.a
include $(PREBUILT_STATIC_LIBRARY)

这样,无论静态库是作为同一版本的一部分构建,还是预构建的库,都以相同的方式将静态库包含在可执行文件的构建中。

此语法还允许您在静态库的部分中添加LOCAL_EXPORT_C_INCLUDES,以在构建可执行文件时添加正确的包含路径,而无需手动将其添加到可执行文件的部分。

答案 1 :(得分:2)

看来确实虽然在可执行文件的Application.mk中严格指定了“APP_STL:= gnustl_static”但它并没有真正链接,强制gnustl_static链接我已将以下内容添加到Android.mk的LOCAL_LDLIBS

LOCAL_LDLIBS += -L$(NDK_ROOT)/sources/cxx-stl/gnu-libstdc++/4.9/libs/$(TARGET_ARCH_ABI) -lgnustl_static

在我看来,就像NDK构建系统中的一个错误......