我的操作系统是:XP
下载的NDKr5包是:android-ndk-r5b-windows.zip.
NDKr5的环境是:
$ cygcheck  -c cygwin
Cygwin Package Information
Package              Version        Status
cygwin               1.7.9-1        OK就以NDKr5提供的sample中的范例工程"two-libs"为例.其jni下的文件共4个:Android.mk,first.c,first.h,second.cfirst.h文件内容如下:
/////////////////////////////////////#ifndef FIRST_H
#define FIRST_Hextern int first(int  x, int  y);#endif /* FIRST_H */
/////////////////////////////////////first.c文件内容如下:
/////////////////////////////////////#include "first.h"int  first(int  x, int  y)
{
    return x + y;
}
////////////////////////////////////////////
second.c文件内容如下:
/////////////////////////////////////#include "first.h"
#include <jni.h>jint
Java_com_example_twolibs_TwoLibs_add( JNIEnv*  env,
                                      jobject  this,
                                      jint     x,
                                      jint     y )
{
    return first(x, y);
}
/////////////////////////////////////其中的Android.mk文件内容如下://///////////////////////////////////LOCAL_PATH:= $(call my-dir)# first lib, which will be built statically
#
include $(CLEAR_VARS)LOCAL_MODULE    := libtwolib-first
LOCAL_SRC_FILES := first.cinclude $(BUILD_STATIC_LIBRARY)# second lib, which will depend on and include the first one
#
include $(CLEAR_VARS)LOCAL_MODULE    := libtwolib-second
LOCAL_SRC_FILES := second.cLOCAL_STATIC_LIBRARIES := libtwolib-firstinclude $(BUILD_SHARED_LIBRARY)/////////////////////////////////////
然后进入two-libs目录,用ndk-build进行编译.可以用其编译过程中生成的静态库libtwolib-first.a一起编译成最终的动态库libtwolib-second.so文件(这一步倒是很正常,但是后面就....搞笑了.)
Administrator@CHINA-WARPO /cygdrive/e/android-ndk-r5b/samples/two-libs
$ $NDK/ndk-build
Compile thumb  : twolib-second <= second.c
Compile thumb  : twolib-first <= first.c
StaticLibrary  : libtwolib-first.a
SharedLibrary  : libtwolib-second.so
Install        : libtwolib-second.so => libs/armeabi/libtwolib-second.so但是笔者试将Android.mk文件修改如下,并将静态库libtwolib-first.a复制到jni目录下和头文件和C文件放一起,试图用现成的静态库libtwolib-first.a生成动态库libtwolib-second.so,却不成功,并报错:undefined reference to `first'
修改后的Android.mk:
$ $NDK/ndk-build
Compile thumb  : twolib-second <= second.c
SharedLibrary  : libtwolib-second.so
E:/android-ndk-r5b/samples/two-libs/obj/local/armeabi/objs/twolib-second/second.o: In function `Java_com
E:/android-ndk-r5b/samples/two-libs/jni/second.c:26: undefined reference to `first'
collect2: ld returned 1 exit status
make: *** [/cygdrive/e/android-ndk-r5b/samples/two-libs/obj/local/armeabi/libtwolib-second.so] Error 1
提问:
1.为什么用现成的.a静态库编译成最终的动态库不能成功,且报这种undefined reference错呢.2.后来在网上看到别人用了
LOCAL_LDFLAGS = $(LOCAL_PATH)/libxxx.a的方式
就在Androi.mk文件中加入了
LOCAL_LDFLAGS = $(LOCAL_PATH)/libtwolib-first.a
然后$/ndk-build.又报错.No such file or directory
Administrator@CHINA-WARPO /cygdrive/e/android-ndk-r5b/samples/two-libs
$ $NDK/ndk-build
Compile thumb  : twolib-second <= second.c
SharedLibrary  : libtwolib-second.so
arm-linux-androideabi-g++.exe: /cygdrive/e/android-ndk-r5b/samples/two-libs/jni/libtwolib-first.a: No such file or directory
make: *** [/cygdrive/e/android-ndk-r5b/samples/two-libs/obj/local/armeabi/libtwolib-second.so] Error 1不知道为什么会这样,本人刚接触NDK,不清楚到底是什么原因引起的.希望高人指点迷津.
难道NDK环境有问题吗?还是我语法写错了?

解决方案 »

  1.   

    我也在这上面纠结了很久到目前也没有彻底搞明白但是还是有些能给你帮助的东西的调用静态库 是要用 LOCAL_LDFLAGS没错 但不是这么用
    1.lib库的名字不能带前后缀 
    2.到目前为止 我只有把静态库 放在NDK的静态库文件夹里才会被找到
      放在其他路径下面都提示找不到  我也求解就是说 假如我用的r5版本 想使用一个libyyy.a 和一个libzzz.a
    那么我只能把它放在
    E:\Android\NDK\platforms\android-5\arch-arm\usr\lib\
    下面
    然后.mk里这么写
    LOCAL_LDFLAGS = -lyyy -lzzz
      

  2.   


    LOCAL_PATH := $(call my-dir)
    LOCAL_CPP_EXTENSION :=.cppinclude $(CLEAR_VARS)
    #LOCAL_C_INCLUDES := $(LOCAL_PATH)
    LOCAL_MODULE    := aaa
    LOCAL_SRC_FILES :=  aaa.cpp 
    LOCAL_LDLIBS := -llog 
    include $(BUILD_STATIC_LIBRARY)include $(CLEAR_VARS)
    #LOCAL_C_INCLUDES := $(LOCAL_PATH)
    LOCAL_MODULE    := MyLib
    LOCAL_SRC_FILES :=  w4e/w4e.cpp 
    LOCAL_LDLIBS := -llog -lGLESv1_CM 
    LOCAL_STATIC_LIBRARIES:=aaa
    LOCAL_LDFLAGS := -lbbb
    include $(BUILD_SHARED_LIBRARY)
    $(call import-module,android/native_app_glue)这样就可以让MyLib既可以依赖一起编译的libaaa.a  又可以依赖NDK库里面的libbbb.a
    我也是新手 哪里说的不对还望指点另外我不知道怎么让aaa可以依赖bbb 如果哪位高人知道的话还望告知
      

  3.   

    提问:
    1.为什么用现成的.a静态库编译成最终的动态库不能成功,且报这种undefined reference错呢.报这个 是因为根本就没有成功链接到那个库文件 我也不明白为什么路径没问题但就是提示找不到
      

  4.   

    谢谢你.
    我用你的方法试了一下,还是一样.
    静态库为:libtwolib-first.a 并放在\arch-arm\usr\lib\目录下和jni目录下.
    修改语句成: LOCAL_LDFLAGS = -ltwolib-first
    编译报错:/arm-linux-androideabi/bin/ld.exe: cannot find -ltwolib-first
    但你的却可以,所以我也很无奈了.说不清的原因.
    唉,英文不行,所以英文文档不太好理解.呵呵.不过你提到的 -lxxx -lzzz的方式
    我知道用在 LOCAL_LDLIBS := -lz -llog 这种语句下是只取lib和so之间的名字字符作为参数的.
    我和你一样,试过,都只能放在\arch-arm\usr\lib\目录下.个人猜测是NDK编译器遇到-l的参数是只会在这个目录下去找库文件或按某个优先顺序去寻找.这个我也做过验证了,的确只能在\arch-arm\usr\lib\目录下才能被找到.另外:LOCAL_LDFLAGS = 的方式我在Ubuntu的NDK5下验证了
    LOCAL_LDFLAGS = $(LOCAL_PATH)/(库名称全称).so
    是可以用这种试式连接动态库并最终生成所需要的动态库.在真机得到验证.
      

  5.   


    这个在NDKr5的Docs里的ANDROID-MK.html自述里是这么描述的.
    LOCAL_LDLIBS
        The list of additional linker flags to be used when building your
        module. This is useful to pass the name of specific system libraries
        with the "-l" prefix
    . For example, the following will tell the linker
        to generate a module that links to /system/lib/libz.so at load time:      LOCAL_LDLIBS := -lz    See docs/STABLE-APIS.html for the list of exposed system libraries you
        can linked against with this NDK release.
    所以,我估计LOCAL_LDLIBS := -lz 的方式就是给系统库连接专用的语法吧.只能在系统库目录里找.
      

  6.   

    少了个冒号LOCAL_LDFLAGS = -ltwolib-first
      

  7.   

    -l表示这是个自带的库  z是libz.so去掉前后缀的名字
      

  8.   

    可以把静态库放在当前Android.mk文件所在目录下,例如有静态库libtest.a,libabc.a
    这样引用:
    LOCAL_LDFLAGS := $(LOCAL_PATH)/libtest.a \
     $(LOCAL_PATH)/libabc.a
      

  9.   


    LOCAL_PATH:= $(call my-dir)
    LOCAL_MODULE    := libtwolib-second
    LOCAL_SRC_FILES := second.c#LOCAL_STATIC_LIBRARIES := libtwolib-first
    LOCAL_LDFLAGS := -ltwolib-firstinclude $(BUILD_SHARED_LIBRARY)还是找不到哦..~~
    Administrator@CHINA-WARPO /cygdrive/e/android-ndk-r5b/samples/two-libs
    $ $NDK/ndk-build
    Compile thumb  : twolib-second <= second.c
    SharedLibrary  : libtwolib-second.so
    E:/android-ndk-r5b/toolchains/arm-linux-androideabi-4.4.3/prebuilt/windows/bin/../lib/gcc/arm-linux-androideabi/4.4.3/../../../../arm-linux-androideabi/bin/ld.exe: cannot find -ltwolib-first
      

  10.   

    [Quote=引用 1 楼 wings4ever 的回复:]
    我也在这上面纠结了很久到目前也没有彻底搞明白关于这个贴子的问题.我自己解决了.不知道其它环境是怎么样,但针对我的环境下,我做下引起该问题的结论.
    经过反反复复的多次实验.
    在Android.mk文件中
    LOCAL_PATH := $(call my-dir)
    include $(CLEAR_VARS)
    LOCAL_LDFLAGS := $(LOCAL_PATH)/libtwolib-first.a我发现问题出在这一句: LOCAL_LDFLAGS := $(LOCAL_PATH)/libtwolib-first.a
    只要用$(LOCAL_PATH)这个路径就会出错,NDK编译器就会找不到库文件.只要换成绝对路径,
    或者自己做个变量比如:
    MY_LOCAL_PATH=E:/代码档区/JAVA/VOSkia/jni
    LOCAL_LDFLAGS := $(LOCAL_PATH)/libtwolib-first.a
    这样就没有问题了.
    而且不存在库文件一定要放在哪,随便哪里都可以.好了,结贴.希望对大家有所帮助.
      

  11.   

    我做过实验,NDK下可以链接一个静态库生成一个动态库.但没试过链接一个静态库生成一个静态库.
    NDK下如果直接只生成静态库,编译器好会罢工.就是没反应.没试过用NDK生成静态库的.NDK本意好像只是为了生成动态库而制定的.
      

  12.   


    恩,之前说的让NDK用静态库生成静态库的问题我也解决了,之前的猜想是错的.
    我后来试了下,的确可以用静态库再生成另一个静态态.
    我后来的Android.mk文件内容如下:
    # Android.mk by warpo,  20110527
    LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)MY_LOCAL_ANDSRC=E:/android-ndk-r5b/platforms/android-8/Android
    MY_LOCAL_SKIA=$(MY_LOCAL_ANDSRC)/external/skia/
    MY_LOCAL_NDKINCLUDE=E:/android-ndk-r5b/platforms/android-8/arch-arm/usr/include/
    MY_LOCAL_VOSINCLUDE=$(LOCAL_PATH)/VG_Engine/Header/VOS/Android
    MY_LOCAL_VTLINCLUDE=$(LOCAL_PATH)/VG_Engine/Header/VTL
    MY_LOCAL_TEMPLATESRC=$(LOCAL_PATH)/VG_Engine/Header/Template
    MY_LOCAL_SYSLIB=E:/android-ndk-r5b/platforms/android-8/arch-arm/usr/lib
    MY_LOCAL_JNIPATH=D:/TestWorkSpace/NDK/VOSkia/jni
    LOCAL_CPP_EXTENSION:=.cpp
    LOCAL_MODULE := skiajni
    LOCAL_SRC_FILES := tiros_gis_vos_SkView.cpp 
    LOCAL_C_INCLUDES := \
    $(MY_LOCAL_SKIA)/include/core \
    $(MY_LOCAL_SKIA)/include/config \
    $(MY_LOCAL_SKIA)/include/images \
    $(MY_LOCAL_SKIA)/include/effects \
    $(MY_LOCAL_ANDSRC)/frameworks/base/include \
    $(MY_LOCAL_ANDSRC)/system/core/include \
    $(MY_LOCAL_ANDSRC)/frameworks/base/core/jni/android/graphics \
    $(MY_LOCAL_ANDSRC)/dalvik/libnativehelper/include \
    $(MY_LOCAL_SYSLIB)/ \
    $(MY_LOCAL_VOSINCLUDE)/ \
    $(MY_LOCAL_TEMPLATESRC)/ \
    $(LOCAL_JNIPATH)/ \
    $(MY_LOCAL_NDKINCLUDE)/ \
    $(MY_LOCAL_VTLINCLUDE)/ \
    LOCAL_LDLIBS := -llog -lmLOCAL_LDFLAGS := $(MY_LOCAL_SYSLIB)/libskia.so \
    $(MY_LOCAL_SYSLIB)/libandroid_runtime.so \
    $(MY_LOCAL_SYSLIB)/libjnigraphics.so \
    $(MY_LOCAL_SYSLIB)/libskiagl.so \
    $(MY_LOCAL_JNIPATH)/libvtl.a \
    include $(BUILD_STATIC_LIBRARY)
    最后一句include $(BUILD_STATIC_LIBRARY)
    另还在新建一个Application.mk文件.并加入APP_MODULES := skiajni就行了.
      

  13.   

    给大家推荐一个解决方案,英文网站找到的:
    #it is used for ndk-r4
    LOCAL_LDLIBS := -L$(LOCAL_PATH)/platform/third_party/android/libraries \
                    -lGLESv1_CM -llog -lz \
                    -lpng \
                    -lxml2 \
                    -ljpeg \
                    -lskia# it is used for ndk-r5    
    because the new Windows toolchain doesn't support Cygwin's drive
    # mapping (i.e /cygdrive/c/ instead of C:/)  
    # LOCAL_LDLIBS := -L$(call host-path, $(LOCAL_PATH)/platform/third_party/android/libraries) \
    #                 -lGLESv1_CM -llog -lz \
    #                 -lpng \
    #                 -lxml2 \
    #                 -ljpeg \
    #                 -lskia
      

  14.   

    谢谢楼上的各位,帮我解决了问题。一并贡献一下我自己的一点小发现。NDK文档中有如下说明
     This NDK comes with a new toolchain (named arm-linux-androideabi-4.4.3)
      which provides many benefits, including:     - Better code generation than the previous one (gcc-4.4.0)
         - On Windows, the binaries do not depend on Cygwin anymore.
    也就是说,编译器改成windows版的了,/cygdrive/开头的cygwin下的路径不再支持,使用windows路径就可以了。
      

  15.   

    谢谢.不过我NDK的R5还是不支持WINDWOS目录.应该如何设定?