You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Android Studio中带原生库的模块A-B-C依赖链配置方法问询

Hey there! Let's walk through how to set up the dependency chain (A → B → C) for your native shared libraries—so building A automatically links B, and building B automatically pulls in C. I'll cover the most common build systems since you didn't specify which one you're using.

CMake (Cross-Platform & Widely Used)

CMake makes dependency handling straightforward with target-based configuration. Here's how to set it up:

Module C Setup

First, configure your CMakeLists.txt for module C to build its shared library:

# Module C's CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(C)

# Build shared library for C
add_library(C SHARED
    src/c_core.cpp
    src/c_utils.cpp
)

# Export headers so dependent modules can include them
target_include_directories(C PUBLIC
    ${CMAKE_CURRENT_SOURCE_DIR}/include
)

Module B Setup

Link B directly to C, and include C's directory so B can use its headers. If C is a subdirectory of your project, use add_subdirectory to pull it in first:

# Module B's CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(B)

# Include Module C's build configuration
add_subdirectory(path/to/module/C)

# Build shared library for B
add_library(B SHARED
    src/b_logic.cpp
)

# Link B to C—CMake will automatically handle linking C when building B
target_link_libraries(B PRIVATE C)

# Export B's headers
target_include_directories(B PUBLIC
    ${CMAKE_CURRENT_SOURCE_DIR}/include
)

Module A Setup

Repeat the pattern: include B's build, then link A to B. CMake will automatically propagate the dependency on C to A, so linking A will pull in both B and C:

# Module A's CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(A)

# Include Module B's build configuration
add_subdirectory(path/to/module/B)

# Build shared library for A
add_library(A SHARED
    src/a_entry.cpp
)

# Link A to B—CMake handles the C dependency automatically
target_link_libraries(A PRIVATE B)

Gradle + Android NDK (For Android Apps)

If you're building for Android with the NDK, use Gradle's module dependency system alongside CMake:

Module C (Android Library Module)

Set up your build.gradle to build the C shared library, and mark it as an Android Library:

// Module C's build.gradle (:C)
plugins {
    id 'com.android.library'
}

android {
    namespace "com.yourdomain.c"
    compileSdk 34

    defaultConfig {
        minSdk 24
        targetSdk 34

        externalNativeBuild {
            cmake {
                arguments "-DANDROID_STL=c++_shared"
                targets "C" // Match the library name from C's CMakeLists.txt
            }
        }
    }

    externalNativeBuild {
        cmake {
            path file('src/main/cpp/CMakeLists.txt')
            version '3.22.1'
        }
    }
}

Module B (Android Library Module)

Add a dependency on Module C in Gradle, then link B to C in its CMakeLists.txt:

// Module B's build.gradle (:B)
plugins {
    id 'com.android.library'
}

android {
    // ... similar config to Module C
}

dependencies {
    // Add dependency on Module C
    implementation project(':C')
}

In B's CMakeLists.txt, link to C just like in the cross-platform example:

target_link_libraries(B PRIVATE C)

Module A & Your App

Add a dependency on Module B to your app's build.gradle:

// App module's build.gradle (:app)
dependencies {
    implementation project(':A')
}

Gradle will automatically package all three shared libraries (A, B, C) into your APK, and linking will happen without extra manual steps.

Makefile (Traditional Native Builds)

Makefiles require a bit more manual setup, but you can use variables to simplify dependency propagation:

Module C's Makefile

# Module C's Makefile
CC = gcc
CFLAGS = -fPIC -Wall -Wextra
INCLUDES = -I./include
LIB_OUTPUT = libC.so

all: $(LIB_OUTPUT)

$(LIB_OUTPUT): c_core.o c_utils.o
	$(CC) -shared -o $@ $^

c_core.o: src/c_core.c
	$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@

c_utils.o: src/c_utils.c
	$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@

clean:
	rm -f *.o $(LIB_OUTPUT)

Module B's Makefile

Include C's build and link against its library. Use variables to store C's paths so they're easy to reference:

# Module B's Makefile
CC = gcc
CFLAGS = -fPIC -Wall -Wextra
INCLUDES = -I./include -I../C/include
LIB_C_PATH = ../C
LIB_C = -L$(LIB_C_PATH) -lC
LIB_OUTPUT = libB.so

# Build Module C first
all: $(LIB_C_PATH)/libC.so $(LIB_OUTPUT)

$(LIB_C_PATH)/libC.so:
	cd $(LIB_C_PATH) && make

$(LIB_OUTPUT): b_logic.o
	$(CC) -shared -o $@ $^ $(LIB_C)

b_logic.o: src/b_logic.c
	$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@

clean:
	rm -f *.o $(LIB_OUTPUT)
	cd $(LIB_C_PATH) && make clean

Module A's Makefile

Repeat the pattern, using B's variables to pull in both B and C dependencies:

# Module A's Makefile
CC = gcc
CFLAGS = -fPIC -Wall -Wextra
INCLUDES = -I./include -I../B/include -I../C/include
LIB_B_PATH = ../B
LIB_B = -L$(LIB_B_PATH) -lB
LIB_C = -L../C -lC
LIB_OUTPUT = libA.so

all: $(LIB_B_PATH)/libB.so $(LIB_OUTPUT)

$(LIB_B_PATH)/libB.so:
	cd $(LIB_B_PATH) && make

$(LIB_OUTPUT): a_entry.o
	$(CC) -shared -o $@ $^ $(LIB_B) $(LIB_C)

a_entry.o: src/a_entry.c
	$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@

clean:
	rm -f *.o $(LIB_OUTPUT)
	cd $(LIB_B_PATH) && make clean

Key Takeaway

No matter which build system you use, the core idea is the same: explicitly declare each module's direct dependencies. Modern build systems like CMake and Gradle will automatically handle dependency propagation, so you don't have to manually link all transitive dependencies (like C when building A). For Makefiles, use variables and pre-build steps to ensure dependent libraries are built and linked correctly.

内容的提问来源于stack exchange,提问作者Kamille

火山引擎 最新活动