Android CMake использует prebuild .a библиотеку - PullRequest
0 голосов
/ 05 июля 2018

Я абсолютно новичок в CMake и использую общий NDK. Я решил написать свой интерфейс JNI и использовать 2 метода, которые являются частью библиотеки C. Я скомпилировал эту библиотеку как статическую библиотеку и получил файл .a. Теперь я немного растерялся, так как не понимаю, как сказать Android Studio использовать эту библиотеку при попытке найти вызываемые функции.

Это мой текущий CMakeLists.txt, который находится в папке модуля "app".

cmake_minimum_required(VERSION 3.4.1)

add_library(my-lib SHARED src/main/cpp/my-lib.cpp )

target_link_libraries(my-lib z crypto)

target_link_libraries(my-lib ${CMAKE_CURRENT_SOURCE_DIR}/../libs/libmine.a)

При компиляции я получаю предупреждение о невозможности найти ссылку на вызываемые функции. Является ли мой файл CMakeLists.txt правильным и как мне включить файл .h для функций? Заранее спасибо за любую помощь!

Ответы [ 2 ]

0 голосов
/ 06 июля 2018

Я не понимаю, как сказать Android Studio использовать эту библиотеку при попытке найти вызываемые функции

Чтобы использовать ваши родные библиотеки, т. Е. libmy-lib.so для вашего случая, вам нужно загрузить эту общую библиотеку внутри вашей Java-части, как показано ниже.

    static {
        System.loadLibrary("my-lib");
    }

Мой CMakeLists.txt правильный?

Да, это правильно, но не совсем идеально.

и как мне включить файл .h для функций

Чтобы вам было проще работать с добавляемыми заголовочными файлами, вам нужно немного настроить CMakelists.txt. Например. Вы можете иметь структуру каталогов, как показано ниже, если у вас есть только app/src/main/cpp, то вы можете просто удалить эти несвязанные каталоги и конфигурации.

    app
    ├── CMakeLists.txt
    └── src
        ├── foo
        │   ├── CMakeLists.txt
        │   ├── foo.cpp
        │   └── foo.h
        ├── main
        │   └── cpp
        │       ├── CMakeLists.txt
        │       └── my-lib.cpp
        └── test
            ├── CMakeLists.txt
            └── google_test_classXXX.cpp

Затем вам нужно настроить app/CMakelists.txt, как показано ниже.

    # set the root directory as ${CMAKE_CURRENT_SOURCE_DIR} which is a
    # CMAKE build-in function to return the current dir where your CMakeLists.txt is. 
    # Specifically, it is "<your-path>/App/"
    set(APP_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR})

    # set your 3 other root dirs, i.e. foo, main and test under app/src.
    set(APP_ROOT_SRC_DIR ${APP_ROOT_DIR}/src)
    set(APP_ROOT_FOO_DIR ${APP_ROOT_SRC_DIR}/foo)
    set(APP_ROOT_MAIN_DIR ${APP_ROOT_SRC_DIR}/main)
    set(APP_ROOT_TEST_DIR ${APP_ROOT_SRC_DIR}/test)

    # set your include paths into "SHARED_INCLUDES" variable so that you can quote your header file without adding its relative paths. 
    set(SHARED_INCLUDES
                    ${APP_ROOT_FOO_DIR}
                    # ${APP_ROOT_FOO_DIR}/<your-other-child-dirs>

                    ${APP_ROOT_MAIN_DIR}
                    ${APP_ROOT_MAIN_DIR}/cpp
                    # ${APP_ROOT_MAIN_DIR}/<your-other-child-dirs>

                    ${APP_ROOT_TEST_DIR}
                    # ${APP_ROOT_TEST_DIR}/<your-other-child-dirs>
                    )

    # This function will have effect to all the downstream cmakelist files. 
    include_directories(${SHARED_INCLUDES})

    add_library(my-lib SHARED src/main/cpp/my-lib.cpp )

    target_link_libraries(my-lib z crypto)

    target_link_libraries(my-lib ${CMAKE_CURRENT_SOURCE_DIR}/../libs/libmine.a)

    # remember to include downstream cmakelist files for foo, main and test.
    add_subdirectory(${APP_ROOT_FOO_DIR} bin-dir)
    add_subdirectory(${APP_ROOT_MAIN_DIR} bin-dir)
    add_subdirectory(${APP_ROOT_TEST_DIR} bin-dir)

---- Edited ----

Для того, чтобы связать prebuild .a libs.

    # Specifies libraries CMake should link to your target library. You
    # can link multiple libraries, such as libraries you define in this
    # build script, prebuilt third-party libraries, or system libraries.
    target_link_libraries(my-lib -Wl,--whole-archive ${CMAKE_CURRENT_SOURCE_DIR}/../libs/libmine.a -Wl,--no-whole-archive)

---- Отредактировано, чтобы ответить на ваши три вопроса ----

Что входит в CMakeLists.txt внутри директории cpp? Это должно быть в каталоге cpp или в главном каталоге?

Теоретически, вы можете просто иметь один CMakelists.txt для всех ваших каталогов исходного кода и каталогов заголовков, но как только ваш проект разовьется в очень большом масштабе, это все-в-одном CMakelists.txt станет довольно сложным и не читаемым и ремонтопригоден. Обычно каждый модуль cmake должен иметь свой собственный файл CMakeLists.txt, чтобы он был модульным и более простым в управлении. Например. cpp dir имеет один CMakeLists.txt для управления всеми его подкаталогами, если таковые имеются, так же, как и main и test "module"

А как мне включить .h файл моей .a lib - #include не работает.

Как я упоминал выше, вам нужно настроить SHARED_INCLUDES, чтобы добавить ваши относительные пути к заголовкам (.h) вашего .a, чтобы вы могли просто использовать #include <xxx.h> для включения заголовка.

    set(SHARED_INCLUDES
                ${APP_ROOT_FOO_DIR}
                # ${APP_ROOT_FOO_DIR}/<your-other-child-dirs>

                ${APP_ROOT_MAIN_DIR}
                ${APP_ROOT_MAIN_DIR}/cpp
                # ${APP_ROOT_MAIN_DIR}/<your-other-child-dirs>

                ${APP_ROOT_TEST_DIR}
                # ${APP_ROOT_TEST_DIR}/<your-other-child-dirs>
       )

Установите ваши пути включения в переменную "SHARED_INCLUDES", чтобы вы могли заключить в кавычки файл заголовка без добавления его относительных путей.


Изменить, чтобы ответить на ваш вопрос о том, как настроить архитектуру

вы можете настроить свои цели внутри build.gradle, как показано ниже:

    defaultConfig {
        externalNativeBuild {
            cmake {
                ...
                abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
                ...
            }
        }
    }

Процесс сборки CMake будет принимать каждый ABI один за другим. Переменная ${ANDROID_ABI} внутри CMakelists.txt может сказать вам текущий ABI (архитектура), который она строит. И вы также можете использовать эту переменную для настройки PATH вашей библиотеки, если вам нужно.

например. Эта переменная ${ANDROID_ABI} внутри

target_link_libraries(${SHARED_LIBRARY_NAME} -Wl,--whole-archive ${CMAKE_CURRENT_SOURCE_DIR}/../libs/${ANDROID_ABI}/libmine.a -Wl,--no-whole-archive)

будет заменено на armeabi-v7a, arm64-v8a, x86 или x86_64 во время сборки.

0 голосов
/ 05 июля 2018

Прежде всего вам нужно указать каталоги включения, используя include_directories () команда. Во-вторых, кажется, что вы хотите связать статическую библиотеку (.a) с вашей окончательной общей библиотекой. Это не может быть сделано. Вам либо нужны общие библиотеки или статические библиотеки.

...