How to create a static library (.a file) in Androi

2019-07-13 05:06发布

Now i create a new project include c++ support in Android Studio 3.2, it has native-lib.cpp naturally, the CMakeLists.txt looks like this:

add_library( # Sets the name of the library.
    native-lib

    # Sets the library as a shared library.
    SHARED

    # Provides a relative path to your source file(s).
    src/main/cpp/native-lib.cpp)

now if i build this project, i can find libnative-lib.so in some "debug" directoies, that's OK, but i want static library ie .a files.

Change SHARED to STATIC won't generate those files, what else should i do?

The CMake docs does not mention other way than add_library().

Every docs i searched only talk about SHARED/STATIC.

What did i miss?

3条回答
ゆ 、 Hurt°
2楼-- · 2019-07-13 05:59

Change SHARED to STATIC won't generate those files, what else should i do?

You can have the static library by setting your lib as STATIC and the generated .a is located at <project-dir>/build/intermediates/cmake/debug/obj/<abi>/libnative-lib.a

add_library( native-lib
         STATIC
         src/main/cpp/native-lib.cpp)

But, like @Dan Albert said, this static lib itself is not much useful. You still need to link it with your other parts of code/libs to come out a final shared library, so that your Android app can use.

For example,

add_library(my-shared-native SHARED src/main/cpp/other-source.cpp)
target_link_libraries(my-shared-native -Wl,--whole-archive native-lib -Wl,--no-whole-archive)

Then on your Java side, you can use this shared library, i.e. libmy-shared-native.so.

static {
    System.loadLibrary("my-shared-native");
}
查看更多
小情绪 Triste *
3楼-- · 2019-07-13 06:00

Adding to @DanAlbert 's comment, the question is not how useful a static library alone can be. The issue is that Android Studio via its Gradle plugin, by default, will not build a CMake target that is a STATIC library.

Luckily, you can explicitly specify the targets you want to produce, e.g.

android { defaultConfig { externalNativeBuild { cmake {
    targets "native_staticlib"
} } } }

Actually, there is not much added value building the static library via integrated externalNativeBuild. You can achieve same if you run cmake --build from command line.

查看更多
Luminary・发光体
4楼-- · 2019-07-13 06:04

First, i want to thank all guys above, without your inspiration, i cannot get this answer.

I write this answer down NOT becase those answers are wrong, i just want to help newbies like me, setp by step, with all details should know.

This answer was proved in Android Studio 3.2.1 with CMake 3.4.1, i triple checked.

Now if you create a new project with C++ support, click "next" all the way, you will get a CMakeLists.txt, whick should looks like :

cmake_minimum_required(VERSION 3.4.1)

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

find_library( 
        log-lib
        log)

target_link_libraries( 
        native-lib
        ${log-lib})

Change SHARED to STATIC won't output any .a file, you will get nothing, even no .so file( of course, there is no SHARED library be added in this file).

This is Gradle/Android Studio 's "fault", the answers above already mentioned it, if you use CMake alone, you'll definetely get a .a file.

OK, now is my TRICK:

We already have a add SHARED library, then we add a STATIC library, which uses the same source file. Add below in your CMakeLists.txt:

add_library(
        native-lib-static
        STATIC
        src/main/cpp/native-lib.cpp
)

"native-lib-static" can be replaced with any name but "native-lib" since it is used for the SHARED version.

Change your target_link_libraries like this:

target_link_libraries(
        native-lib
        native-lib-static
        ${log-lib})

enter image description here

Gradle->app->build->assembleDebug/assembleRelease

Then you'll get libnative-lib-static.a, in

app\.externalNativeBuild\cmake\debug(release)\<abi>\libnative-lib-static.a

This path is set in app\build.gradle:

android{
    defaultConfig{
         externalNativeBuild{
             CMake{

ATM i'm not sure whether Google will change it in the future, but you can always search the project folder for *.a files.

I don't think i miss anything this time.

All credit to @Michael @Dan Albert @Alex Cohn @shizhen

查看更多
登录 后发表回答