【问题标题】:Android NDK: Static compilation with CLang errorAndroid NDK:带有 CLang 错误的静态编译
【发布时间】:2015-05-16 05:20:43
【问题描述】:

我目前正在使用 NDK 和 JNI 为 Android 应用程序开发 C/C++ 模块。

我需要用 CLang 编译这个 C 模块并使用静态链接来删除对 libc 的依赖。

静态链接到 libC 的编译在 GCC 上运行良好,但我无法在 CLang 上运行。我收到以下错误:

D:/tools/android-ndk-r10d/platforms/android-21/arch-arm/usr/lib/../lib\crtbegin_static.o:crtbrand.c:function _start: error: undefined reference to 'main'

下面的例子是在 Windows 上,但在 linux 上的问题是一样的。

用一个非常简单的 hello world 来演示问题:

你好-jni.c:

#include <jni.h>
jstring Java_com_example_hellojni_HelloJni_stringFromJNI(JNIEnv* env, jobject thiz) {
return (*env)->NewStringUTF(env, "hello world");
}

makefile android.mk 是:

LOCAL_PATH := $(call my-dir)

ifndef NDK_PATH
    NDK_PATH = C:/dev/android-ndk-r10d/
endif

SDK_VERSION = 21

include $(CLEAR_VARS)
LOCAL_MODULE    := LibC 
LOCAL_SRC_FILES := $(NDK_PATH)platforms/android-$(SDK_VERSION)/arch- $(TARGET_ARCH)/usr/lib/libc.a
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE    := libhello
LOCAL_SRC_FILES := hello-jni.c

LOCAL_STATIC_LIBRARIES := LibC 
LOCAL_CFLAGS += -nostdlib
LOCAL_LDFLAGS := -static -v

include $(BUILD_SHARED_LIBRARY)

和application.mk:

APP_ABI := armeabi-v7a
NDK_TOOLCHAIN_VERSION := clang3.5

如果它有任何用处,为 LDFLAGS 设置 -v 标志会给我:

"D:/tools/android-ndk-r10d/toolchains/arm-linux-androideabi-4.8/prebuilt/windows-x86_64/lib/gcc/arm-linux-androideabi/4.8/../../../../arm-linux-androideabi/bin\ld.exe" --sysroot=D:/tools/android-ndk-r10d/platforms/android-21/arch-arm -X -m armelf_linux_eabi -Bstatic -dynamic-linker /system/bin/linker -o ./obj/local/armeabi-v7a/libhello.so "D:/tools/android-ndk-r10d/platforms/android-21/arch-arm/usr/lib/../lib\\crtbegin_static.o" -LD:/tools/android-ndk-r10d/toolchains/arm-linux-androideabi-4.8/prebuilt/windows-x86_64/lib/gcc/arm-linux-androideabi/4.8 -LD:/tools/android-ndk-r10d/toolchains/arm-linux-androideabi-4.8/prebuilt/windows-x86_64/lib/gcc/arm-linux-androideabi/4.8/../../../../arm-linux-androideabi/lib/../lib -LD:/tools/android-ndk-r10d/platforms/android-21/arch-arm/usr/lib/../lib -LD:/tools/android-ndk-r10d/platforms/android-21/arch-arm/usr/lib/arm-linux-androideabi/../../lib-LD:/tools/android-ndk-r10d/toolchains/arm-linux-androideabi-4.8/prebuilt/windows-x86_64/lib/gcc/arm-linux-androideabi/4.8/../../../../arm-linux-androideabi/lib -LD:/tools/android-ndk-r10d/platforms/android-21/arch-arm/usr/lib -soname libhello.so ./obj/local/armeabi-v7a/objs-debug/hello/hello-jni.o D:/tools/android-ndk-r10d/platforms/android-21/arch-arm/usr/lib/libc.a -lgcc --fix-cortex-a8 --no-undefined -z noexecstack -z relro -z now -lc -lm -lstdc++ -lm --start-group -lgcc -lc --end-group "D:/tools/android-ndk-r10d/platforms/android-21/arch-arm/usr/lib/../lib\\crtend_so.o" D:/tools/android-ndk-r10d/platforms/android-21/arch-arm/usr/lib/../lib\crtbegin_static.o:crtbrand.c:function _start: error: undefined reference to 'main' clang++.exe: error: linker command failed with exit code 1 (use -v to see invocation) make.exe: *** [obj/local/armeabi-v7a/libhello.so] Error 1

如果有人能帮助我,我将不胜感激!

干杯

【问题讨论】:

    标签: android android-ndk clang


    【解决方案1】:

    显然您正在尝试构建共享库libhello.so

    要构建共享库,您必须将选项 -shared 传递给链接器 (ld)。 您的链接命令表明您没有这样做。 如果您不这样做,则链接器假定您正在尝试构建可执行程序。和你 如果正在尝试构建 C 可执行文件,则它必须具有 main 函数 int main(int argc, char *argv[]) 开始执行的地方。如果你不这样做, 然后你会得到你看到的链接错误。 hello-jni.c 确实 不包含任何main 函数,因为它应该被构建为一个库, 不是程序。

    因此,将您的 LOCAL_LDFLAGS 更改为 -shared -static。 (或者可能更符合 构建的组织,将-shared 添加到链接器标志的任何位置 设置在include $(BUILD_SHARED_LIBRARY)) 内。你 可能会认为-shared-static 是相互矛盾的选项,但事实并非如此。 -shared 表示建立一个共享库-static 表示不链接任何共享库 无论正在建造什么

    另外,如果你正在构建一个共享库,那么你必须通过选项-fPIC, 在您编译源文件时生成与位置无关的目标代码。 我们看不到您的任何编译命令,但您需要-fPIC 才能在场 在您传递给编译器的CFLAGS 中。据我们所知,从您的 makefile,你只是传递-nostdlib

    我不清楚你为什么将-nostlib 传递给编译器。它是一个链接器 选项,对编译没有影响,我们在您的链接命令中看不到它, 它会产生一些影响。

    顺便说一句,似乎有一个缺失的空间潜伏在某处 您构建的看不见的解剖结构。在那个详细的链接命令中,怪物-L 选项:

    -LD:/tools/android-ndk-r10d/platforms/android-21/arch-arm/usr/lib/arm-linux-androideabi/../../lib-LD:/tools/android-ndk-r10d/toolchains/arm-linux-androideabi-4.8/prebuilt/windows-x86_64/lib/gcc/arm-linux-androideabi/4.8/../../../../arm-linux-androideabi/lib
    

    显然是两个结合在一起的:

    -LD:/tools/android-ndk-r10d/platforms/android-21/arch-arm/usr/lib/arm-linux-androideabi/../../lib
    -LD:/tools/android-ndk-r10d/toolchains/arm-linux-androideabi-4.8/prebuilt/windows-x86_64/lib/gcc/arm-linux-androideabi/4.8/../../../../arm-linux-androideabi/lib
    

    我希望这会使链接器尝试在怪物不存在的路径中进行搜索 两个较短的路径,但可能连接只是一个印刷错误。

    【讨论】:

    • 您好,感谢您提供如此详细的回复。我确实尝试添加 -fPIC 标志并从 LOCAL_CFLAGS 中删除 -nostdlib。我还在链接器中添加了 --shared 标志,但我仍然得到同样的错误。对于 ...lib–LD:/tools... 连接,这是一个复制粘贴问题,而不是实际问题。我不清楚 NDK 构建工具链实际上做了什么,但仅传递 –static 确实会使用 GCC 构建一个 .so,而那个 .so 实际上适用于我的 Java 程序。您是否认为实际上是 GCC 通过完成这项工作而不是 CLang 不这样做而表现得很奇怪?
    猜你喜欢
    • 2017-07-17
    • 1970-01-01
    • 2011-02-25
    • 2018-11-26
    • 2014-11-28
    • 1970-01-01
    • 2012-01-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多