代码之家  ›  专栏  ›  技术社区  ›  MDMoore313

“未定义引用错误”疑难解答-Android Studio/CMake/Clang++A

  •  0
  • MDMoore313  · 技术社区  · 8 年前

    我正试图设置 HelloJNI tutorial

    文件结构如下:

    ├── app
    │   ├── libs
    │   │   ├── bthread
    │   │   │   ├── CMakeLists.txt
    │   │   │   └── include
    │   │   ├── cuse
    │   │   │   ├── CMakeLists.txt
    │   │   │   └── include
    │   │   └── fuse
    │   │       ├── CMakeLists.txt
    │   │       ├── include
    │   │       └── modules
    │   └── src
    │       ├── main
    │       │   ├── cpp
    │       │   │   ├── hello-jni.cpp
    │       │   │   └── daemon.cpp
    

    这个 CMakeLists.txt 中库的文件 libs

    cmake_minimum_required(VERSION 3.4.1)
    
    # Create a library called "Hello" which includes the source file "hello.cxx".
    # The extension is already found. Any number of sources could be listed here.
    
    include_directories(
        ${CMAKE_SOURCE_DIR}/lib/fuse/include
        ${CMAKE_SOURCE_DIR}/lib/cuse/include)
    
    
    add_library    (cuse    SHARED
                            cuse.c)
    
    add_executable (cuse_client cuse_client.c)
    
    
    # Make sure the compiler can find include files for our Hello library
    # when other libraries or executables link to Hello
    
    target_include_directories(cuse PUBLIC
        $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
        $<INSTALL_INTERFACE:include>)
    
    set_target_properties(cuse PROPERTIES PUBLIC_HEADER  "include/cuse.h")
    
    target_link_libraries( # Specifies the target library.
                           cuse
                           fuse)
    
    install(TARGETS cuse
        EXPORT cuse-targets
        PUBLIC_HEADER DESTINATION include
        ARCHIVE DESTINATION lib
        LIBRARY DESTINATION lib
        RUNTIME DESTINATION bin)
    
    install(EXPORT cuse-targets
        NAMESPACE cuse::
        FILE cuse-config.cmake
        DESTINATION lib/cmake/cuse)
    

    对于每个库。 cuse 取决于 fuse 取决于 bthread ,并将每个库设置为“共享” add_library()

    这个 app/CMakeLists.txt

    # For more information about using CMake with Android Studio, read the
    # documentation: https://d.android.com/studio/projects/add-native-code.html
    
    # Sets the minimum version of CMake required to build the native library.
    
    cmake_minimum_required(VERSION 3.4.1)
    
    project(app)
    
    include_directories(
        ${CMAKE_SOURCE_DIR}/libs/cuse/include
        ${CMAKE_SOURCE_DIR}/libs/fuse/include)
    
    
    add_subdirectory(libs/bthread)
    add_subdirectory(libs/fuse)
    add_subdirectory(libs/cuse)
    
    #find_library(LIB_CUSE NAMES cuse libcuse HINTS libs libs/cuse)
    
    add_library(hello-jni SHARED    src/main/cpp/hello-jni.cpp
                                    src/main/cpp/daemon.cpp)
    
    
    
    target_link_libraries( # Specifies the target library.
                           hello-jni
                           ${LIB_CUSE})
    

    cuse.c . 例如:

    src/main/cpp/daemon.cpp.o: In function `start_cuse_server()':
    src/main/cpp/daemon.cpp:65: undefined reference to `cusexmp_process_arg(void*, char const*, int, fuse_args*)'
    

    我改了 app/CMakeLists.txt' several times to try and link to the

    头文件 cuse.h :

    #ifndef CUSE_H
    #define CUSE_H
    
    #include "cuse_lowlevel.h"
    #include <fuse_opt.h>
    #include <stddef.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <errno.h>
    
    #include "ioctl.h"
    
    #define CUSEXMP_OPT(t, p) { t, offsetof(struct cusexmp_param, p), 1 }
    
    void *cusexmp_buf;
    size_t cusexmp_size;
    
    int cusexmp_resize(size_t new_size);
    
    void cusexmp_open(fuse_req_t req, struct fuse_file_info *fi);
    
    void cusexmp_read(fuse_req_t req, size_t size, off_t off,
                             struct fuse_file_info *fi);
    
    int cusexmp_expand(size_t new_size);
    
    void cusexmp_write(fuse_req_t req, const char *buf, size_t size,
                              off_t off, struct fuse_file_info *fi);
    
    void fioc_do_rw(fuse_req_t req, void *addr, const void *in_buf,
                           size_t in_bufsz, size_t out_bufsz, int is_read);
    
    void cusexmp_ioctl(fuse_req_t req, int cmd, void *arg,
                              struct fuse_file_info *fi, unsigned flags,
                              const void *in_buf, size_t in_bufsz, size_t out_bufsz);
    
    int cusexmp_process_arg(void *data, const char *arg, int key,
                                   struct fuse_args *outargs);
    
    struct cusexmp_param {
        unsigned        major;
        unsigned        minor;
        char            *dev_name;
        int         is_help;
    };
    
    const struct cuse_lowlevel_ops cusexmp_clop = {
            .open       = cusexmp_open,
            .read       = cusexmp_read,
            .write      = cusexmp_write,
            .ioctl      = cusexmp_ioctl,
    };
    
    const struct fuse_opt cusexmp_opts[] = {
            CUSEXMP_OPT("--maj=%u",     major),
            CUSEXMP_OPT("-m %u",        minor),
            CUSEXMP_OPT("--min=%u",     minor),
            CUSEXMP_OPT("-n %s",        dev_name),
            CUSEXMP_OPT("--name=%s",    dev_name),
            FUSE_OPT_KEY("-h",      0),
            FUSE_OPT_KEY("--help",      0),
            FUSE_OPT_END
    };
    
    const char *usage =
            "usage: cusexmp [options]\n"
                    "\n"
                    "options:\n"
                    "    --help|-h             print this help message\n"
                    "    --maj=MAJ|-M MAJ      device major number\n"
                    "    --min=MIN|-m MIN      device minor number\n"
                    "    --name=NAME|-n NAME   device name (mandatory)\n"
                    "    -d   -o debug         enable debug output (implies -f)\n"
                    "    -f                    foreground operation\n"
                    "    -s                    disable multi-threaded operation\n"
                    "\n";
    
    
    #endif
    

    因为 图书馆编译得很好。Gradle的示例输出:

    Build hello-jni arm64-v8a
    [1/3] Building CXX object CMakeFiles/hello-jni.dir/src/main/cpp/hello-jni.cpp.o
    [2/3] Building CXX object CMakeFiles/hello-jni.dir/src/main/cpp/daemon.cpp.o
    /home/mike/Desktop/hellojni/app/src/main/cpp/daemon.cpp:76:20: warning: ISO C++11 does not allow conversion from string literal to 'char *' [-Wwritable-strings]
        param.dev_name="/dev/chardev_test";
                       ^
    1 warning generated.
    [3/3] Linking CXX shared library ../../../../build/intermediates/cmake/debug/obj/arm64-v8a/libhello-jni.so
    FAILED: : && /data/android-ndk-r17b/toolchains/llvm/prebuilt/linux-x86_64/bin/clang++  --target=aarch64-none-linux-android --gcc-toolchain=/data/android-ndk-r17b/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64 --sysroot=/data/android-ndk-r17b/sysroot -fPIC -isystem /data/android-ndk-r17b/sysroot/usr/include/aarch64-linux-android -D__ANDROID_API__=21 -g -DANDROID -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -Wa,--noexecstack -Wformat -Werror=format-security -std=c++11  -O0 -fno-limit-debug-info  -Wl,--exclude-libs,libgcc.a -Wl,--exclude-libs,libatomic.a -nostdlib++ --sysroot /data/android-ndk-r17b/platforms/android-21/arch-arm64 -Wl,--build-id -Wl,--warn-shared-textrel -Wl,--fatal-warnings -L/data/android-ndk-r17b/sources/cxx-stl/llvm-libc++/libs/arm64-v8a -Wl,--no-undefined -Wl,-z,noexecstack -Qunused-arguments -Wl,-z,relro -Wl,-z,now -shared -Wl,-soname,libhello-jni.so -o ../../../../build/intermediates/cmake/debug/obj/arm64-v8a/libhello-jni.so CMakeFiles/hello-jni.dir/src/main/cpp/hello-jni.cpp.o CMakeFiles/hello-jni.dir/src/main/cpp/daemon.cpp.o  -latomic -lm "/data/android-ndk-r17b/sources/cxx-stl/llvm-libc++/libs/arm64-v8a/libc++_static.a" "/data/android-ndk-r17b/sources/cxx-stl/llvm-libc++/libs/arm64-v8a/libc++abi.a" && :
    CMakeFiles/hello-jni.dir/src/main/cpp/daemon.cpp.o:(.bss+0x0): multiple definition of `cusexmp_buf'
    CMakeFiles/hello-jni.dir/src/main/cpp/hello-jni.cpp.o:(.bss+0x0): first defined here
    CMakeFiles/hello-jni.dir/src/main/cpp/daemon.cpp.o: In function `__daemon_init()':
    /home/mike/Desktop/hellojni/app/src/main/cpp/daemon.cpp:65: multiple definition of `cusexmp_size'
    CMakeFiles/hello-jni.dir/src/main/cpp/hello-jni.cpp.o:/data/android-ndk-r17b/sources/cxx-stl/llvm-libc++/include/string:1543: first defined here
    CMakeFiles/hello-jni.dir/src/main/cpp/daemon.cpp.o: In function `__daemon_init()':
    /home/mike/Desktop/hellojni/app/src/main/cpp/daemon.cpp:65: multiple definition of `usage'
    CMakeFiles/hello-jni.dir/src/main/cpp
    /hello-jni.cpp.o:/data/android-ndk-r17b/sources/cxx-stl/llvm-libc++/include/string:1543: first defined here
    CMakeFiles/hello-jni.dir/src/main/cpp/daemon.cpp.o: In function `start_cuse_server()':
    /home/mike/Desktop/hellojni/app/src/main/cpp/daemon.cpp:65: undefined reference to `cusexmp_process_arg(void*, char const*, int, fuse_args*)'
    /home/mike/Desktop/hellojni/app/src/main/cpp/daemon.cpp:65: undefined reference to `cusexmp_process_arg(void*, char const*, int, fuse_args*)'
    /home/mike/Desktop/hellojni/app/src/main/cpp/daemon.cpp:81: undefined reference to `fuse_opt_parse'
    /home/mike/Desktop/hellojni/app/src/main/cpp/daemon.cpp:101: undefined reference to `cuse_lowlevel_main'
    CMakeFiles/hello-jni.dir/src/main/cpp/daemon.cpp.o:(.data.rel.ro+0xd8): undefined reference to `cusexmp_open(fuse_req*, fuse_file_info*)'
    CMakeFiles/hello-jni.dir/src/main/cpp/daemon.cpp.o:(.data.rel.ro+0xe0): undefined reference to `cusexmp_read(fuse_req*, unsigned long, long, fuse_file_info*)'
    CMakeFiles/hello-jni.dir/src/main/cpp/daemon.cpp.o:(.data.rel.ro+0xe8): undefined reference to `cusexmp_write(fuse_req*, char const*, unsigned long, long, fuse_file_info*)'
    CMakeFiles/hello-jni.dir/src/main/cpp/daemon.cpp.o:(.data.rel.ro+0x108): undefined reference to `cusexmp_ioctl(fuse_req*, int, void*, fuse_file_info*, unsigned int, void const*, unsigned long, unsigned long)'
    clang++: error: linker command failed with exit code 1 (use -v to see invocation)
    ninja: build stopped: subcommand failed.
    :app:externalNativeBuildDebug FAILED
    

    这个 multiple definition

    我的问题是 :How to next fix/Troubleshow this error:似乎CMake没有正确链接库,但我对CMake或链接器不够熟悉,不知道如何调试此问题。我尝试了很多不同的符号库的组合。

    我怎么跑 cmake 在bash中,查看 cmake公司 ld 找到错误了吗?

    更新

    我不知道 find_library() 在里面 仍然被注释掉了。取消对该行的注释会产生以下错误:

    CMake Error: The following variables are used in this project, but they are set to NOTFOUND.
    Please set them or make sure they are set and tested correctly in the CMake files:
    LIB_CUSE
        linked by target "hello-jni" in directory /home/mike/Desktop/hellojni/app
    
    0 回复  |  直到 8 年前