I have a curious question. I have an aar library, which contains and uses native .so library. Now, I want to write another lib, which depends on that library and also has native part depending on native lib from the first lib. The dependent library uses both the native code and java wrappers from the first lib.
我有个奇怪的问题。我有一个aar库,它包含和使用native .so库。现在,我想写另一个库,它依赖于那个库,并且有本地部分依赖于第一个库中的本地库。
I wonder, is there any way, how to do this by standard gradle dependency(with copied headers files from the first lib)? Or have I to build the second lib directly from the sources?
我想知道,有什么方法可以通过标准的gradle依赖(使用来自第一个库的拷贝头文件)来实现这一点吗?还是直接从源代码构建第二个库?
Why I need this: We have a multiplatform lib with basic functionality, for android as aar. This lib can be used in standard android app and we use it in multiple projects, which have no another native code.
为什么我需要这个:我们有一个多平台库,有基本的功能,用于android as aar。这个库可以在标准的android应用程序中使用,我们可以在多个没有其他本地代码的项目中使用它。
But in one app we want to write multiplatform shared app code, depending on that lib and I want to have these libs separated.
但在一个应用程序中,我们想编写多平台共享应用程序代码,这取决于lib和我想让这些libs分开。
Thanks!
谢谢!
2 个解决方案
#1
3
Here is a workable example basic on OpenCV
, you can do the same for your first lib
.
下面是OpenCV上一个可行的基本示例,您可以对您的第一个库执行相同的操作。
Prepare first lib as following
Package the jar
, *.so
, and exported headers
(see the file OpenCV4Android/opencv/build.gradle
in the linked project how to append the headers to aar).
包的jar,*。因此,并导出header(请参阅文件OpenCV4Android/opencv/build)。在链接项目中如何将标题附加到aar)。
You get first.aar
for example from the building of first lib
.
你得到第一。举个例子,从第一次解放运动开始。
Using first lib in your other projects
Add the first.aar
in your other projects when you needed.
添加第一个。在你需要的时候在你的其他项目。
allprojects {
repositories {
jcenter()
flatDir {
dirs '/path/to/aar'
}
}
}
// in your app's build.gradle
dependencies {
// ...
compile 'com.example:example-with-header@aar'
// ...
}
Link against your native library to the first.aar
from your native build system.
将本地库链接到第一个库。aar来自您的本地构建系统。
If you use CMake
, it should look like this
如果你使用CMake,它应该是这样的
add_library(first
SHARED
IMPORTED)
set_target_properties(
first
PROPERTIES IMPORTED_LOCATION
../../../../build/intermediates/exploded-aar/org.example/example-debug/jni/${ANDROID_ABI}/libfirst.so
# use find command to figure out the location of the first lib before use it, not sure if it's different in different build environment
# for android studio gradle plugin latest version use
# ../../../../build/intermediates/transforms/mergeJniLibs/debug/folders/2000/1f/main/lib/${ANDROID_ABI}/libfirst.so
)
# also use find command to figure the actual location of the exported header from aar
# this might be different in your environment for different version of gradle plugin
include_directories(build/intermediates/exploded-aar/com.example/example-debug/cpp/include)
target_link_libraries( # Specifies the target library.
native-lib
# Links the target library to the log library
# included in the NDK.
first
${log-lib} )
#2
1
As you mentioned Gradle, I am assuming you are using the latest Android Studio. I am using 1.2.2 and found it easy to build the simple NDK projects from the many tutorials floating around, but frustratingly difficult to build an NDK project of any complexity. I will summarize what I found, but I highly suggest reading this blog and this *.
正如您提到的Gradle,我假设您使用的是最新的Android Studio。我使用的是1.2.2,并且发现从大量的教程构建简单的NDK项目很容易,但是构建任何复杂性的NDK项目都非常困难。我将总结我的发现,但我强烈建议阅读这个博客和*。
My project is similar to yours but not exactly. The trick for me was figuring out how to make Android Studio use my Android.mk, then finding the right makefile variables. Hopefully this will help.
我的项目和你的相似,但不完全一样。我的诀窍是弄明白如何让Android Studio使用我的Android。然后找到正确的makefile变量。希望这将帮助。
The stock Android Studio will completely ignore any custom Android.mk file you create, and instead auto-generate its own. To correct this, you must first hack the build.gradle script for your project, located at project/app/build.gradle
. You could probably hack the top-level build.gradle, if desired.
传统的Android工作室将完全忽略任何定制的Android。你创建的mkfile,并自动生成它自己的。为了纠正这个错误,您必须首先修改构建。您的项目的gradle脚本,位于项目/app/build.gradle。您可能会破解*构建。gradle(如果需要的话)。
This is my hacked build.gradle. I build on a Windows box, so I hacked it for Windows only. Uncomment the lines if you are using OSX or Linux.
这是我被黑的建筑。我建在一个Windows框上,所以我只对Windows操作系统进行了黑客攻击。如果使用OSX或Linux,请取消注释。
project/app/build.gradle:
项目/应用程序/ build.gradle:
//import org.apache.tools.ant.taskdefs.condition.Os
apply plugin: 'com.android.application'
android {
compileSdkVersion 22
buildToolsVersion "22.0.1"
defaultConfig {
applicationId "com.sample.app"
minSdkVersion 15
targetSdkVersion 22
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
//ENABLE CUSTOM ANDROID.MK >>
sourceSets.main.jni.srcDirs= [] //Disable automatic ndk-build.
sourceSets.main.jniLibs.srcDir 'src/main/libs'
//Call regular ndk-build script from app directory
task ndkBuild(type: Exec) {
workingDir file('src/main')
commandLine getNdkBuildCmd()
}
tasks.withType(JavaCompile) {
compileTask -> compileTask.dependsOn ndkBuild
}
task cleanNative(type: Exec) {
workingDir file('src/main')
commandLine getNdkBuildCmd(), 'clean'
}
clean.dependsOn cleanNative
}
//ENABLE CUSTOM ANDROID.MK <<
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:22.2.0'
compile 'com.google.android.gms:play-services:7.5.0'
}
//ENABLE CUSTOM ANDROID.MK >>
def getNdkDir() {
if (System.env.ANDROID_NDK_ROOT != null)
return System.env.ANDROID_NDK_ROOT
Properties properties = new Properties()
properties.load(project.rootProject.file('local.properties').newDataInputStream())
def ndkdir = properties.getProperty('ndk.dir', null)
if (ndkdir == null)
throw new GradleException("NDK location not found. Define location with ndk.dir in the local.properties file")
return (ndkdir)
}
def getNdkBuildCmd() {
def ndkbuild = getNdkDir() + "/ndk-build.cmd"
// def ndkbuild = getNdkDir() + "/ndk-build"
// if (Os.isFamily(Os.FAMILY_WINDOWS))
// ndkbuild += ".cmd"
return ndkbuild
}
//ENABLE CUSTOM ANDROID.MK <<
Now I can create my multi-library Android.mk. This builds two static-link libraries, then builds the final dynamic-link libraries and links in the first two. The directories involved are:
现在我可以创建我的多库android。这将构建两个静态链接库,然后在前两个中构建最后的动态链接库和链接。涉及的目录:
Directories:
目录:
project/
app/
build.gradle
src/
main/
java/
jni/
Android.mk
include/
libmp3lame/
MiniMp3/
mp3_jni.c
mpglib/
Android.mk:
Android.mk:
TOP_PATH := $(call my-dir)
LOCAL_PATH := $(TOP_PATH)/libmp3lame
include $(CLEAR_VARS)
LOCAL_C_INCLUDES := $(TOP_PATH)/include
LOCAL_CFLAGS := -DSTDC_HEADERS
LOCAL_MODULE := libmp3lame
LOCAL_SRC_FILES := \
bitstream.c \
...
version.c
include $(BUILD_STATIC_LIBRARY)
MY_LOCAL_STATIC_LIBRARIES += libmp3lame
LOCAL_PATH := $(TOP_PATH)/mpglib
include $(CLEAR_VARS)
LOCAL_C_INCLUDES := $(TOP_PATH)/include
LOCAL_C_INCLUDES += $(TOP_PATH)/libmp3lame
LOCAL_CFLAGS := -DSTDC_HEADERS
LOCAL_MODULE := mpglib
LOCAL_SRC_FILES := \
common.c \
...
tabinit.c
include $(BUILD_STATIC_LIBRARY)
MY_LOCAL_STATIC_LIBRARIES += mpglib
LOCAL_PATH := $(TOP_PATH)
include $(CLEAR_VARS)
LOCAL_C_INCLUDES := $(TOP_PATH)/include
LOCAL_CFLAGS := -DSTDC_HEADERS
LOCAL_MODULE := Mp3
LOCAL_STATIC_LIBRARIES := $(MY_LOCAL_STATIC_LIBRARIES)
LOCAL_LDLIBS := -llog
LOCAL_SRC_FILES := \
./mp3_jni.c
include $(BUILD_SHARED_LIBRARY)
You will need to tweak the Android.mk.
你需要调整Android.mk。
#1
3
Here is a workable example basic on OpenCV
, you can do the same for your first lib
.
下面是OpenCV上一个可行的基本示例,您可以对您的第一个库执行相同的操作。
Prepare first lib as following
Package the jar
, *.so
, and exported headers
(see the file OpenCV4Android/opencv/build.gradle
in the linked project how to append the headers to aar).
包的jar,*。因此,并导出header(请参阅文件OpenCV4Android/opencv/build)。在链接项目中如何将标题附加到aar)。
You get first.aar
for example from the building of first lib
.
你得到第一。举个例子,从第一次解放运动开始。
Using first lib in your other projects
Add the first.aar
in your other projects when you needed.
添加第一个。在你需要的时候在你的其他项目。
allprojects {
repositories {
jcenter()
flatDir {
dirs '/path/to/aar'
}
}
}
// in your app's build.gradle
dependencies {
// ...
compile 'com.example:example-with-header@aar'
// ...
}
Link against your native library to the first.aar
from your native build system.
将本地库链接到第一个库。aar来自您的本地构建系统。
If you use CMake
, it should look like this
如果你使用CMake,它应该是这样的
add_library(first
SHARED
IMPORTED)
set_target_properties(
first
PROPERTIES IMPORTED_LOCATION
../../../../build/intermediates/exploded-aar/org.example/example-debug/jni/${ANDROID_ABI}/libfirst.so
# use find command to figure out the location of the first lib before use it, not sure if it's different in different build environment
# for android studio gradle plugin latest version use
# ../../../../build/intermediates/transforms/mergeJniLibs/debug/folders/2000/1f/main/lib/${ANDROID_ABI}/libfirst.so
)
# also use find command to figure the actual location of the exported header from aar
# this might be different in your environment for different version of gradle plugin
include_directories(build/intermediates/exploded-aar/com.example/example-debug/cpp/include)
target_link_libraries( # Specifies the target library.
native-lib
# Links the target library to the log library
# included in the NDK.
first
${log-lib} )
#2
1
As you mentioned Gradle, I am assuming you are using the latest Android Studio. I am using 1.2.2 and found it easy to build the simple NDK projects from the many tutorials floating around, but frustratingly difficult to build an NDK project of any complexity. I will summarize what I found, but I highly suggest reading this blog and this *.
正如您提到的Gradle,我假设您使用的是最新的Android Studio。我使用的是1.2.2,并且发现从大量的教程构建简单的NDK项目很容易,但是构建任何复杂性的NDK项目都非常困难。我将总结我的发现,但我强烈建议阅读这个博客和*。
My project is similar to yours but not exactly. The trick for me was figuring out how to make Android Studio use my Android.mk, then finding the right makefile variables. Hopefully this will help.
我的项目和你的相似,但不完全一样。我的诀窍是弄明白如何让Android Studio使用我的Android。然后找到正确的makefile变量。希望这将帮助。
The stock Android Studio will completely ignore any custom Android.mk file you create, and instead auto-generate its own. To correct this, you must first hack the build.gradle script for your project, located at project/app/build.gradle
. You could probably hack the top-level build.gradle, if desired.
传统的Android工作室将完全忽略任何定制的Android。你创建的mkfile,并自动生成它自己的。为了纠正这个错误,您必须首先修改构建。您的项目的gradle脚本,位于项目/app/build.gradle。您可能会破解*构建。gradle(如果需要的话)。
This is my hacked build.gradle. I build on a Windows box, so I hacked it for Windows only. Uncomment the lines if you are using OSX or Linux.
这是我被黑的建筑。我建在一个Windows框上,所以我只对Windows操作系统进行了黑客攻击。如果使用OSX或Linux,请取消注释。
project/app/build.gradle:
项目/应用程序/ build.gradle:
//import org.apache.tools.ant.taskdefs.condition.Os
apply plugin: 'com.android.application'
android {
compileSdkVersion 22
buildToolsVersion "22.0.1"
defaultConfig {
applicationId "com.sample.app"
minSdkVersion 15
targetSdkVersion 22
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
//ENABLE CUSTOM ANDROID.MK >>
sourceSets.main.jni.srcDirs= [] //Disable automatic ndk-build.
sourceSets.main.jniLibs.srcDir 'src/main/libs'
//Call regular ndk-build script from app directory
task ndkBuild(type: Exec) {
workingDir file('src/main')
commandLine getNdkBuildCmd()
}
tasks.withType(JavaCompile) {
compileTask -> compileTask.dependsOn ndkBuild
}
task cleanNative(type: Exec) {
workingDir file('src/main')
commandLine getNdkBuildCmd(), 'clean'
}
clean.dependsOn cleanNative
}
//ENABLE CUSTOM ANDROID.MK <<
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:22.2.0'
compile 'com.google.android.gms:play-services:7.5.0'
}
//ENABLE CUSTOM ANDROID.MK >>
def getNdkDir() {
if (System.env.ANDROID_NDK_ROOT != null)
return System.env.ANDROID_NDK_ROOT
Properties properties = new Properties()
properties.load(project.rootProject.file('local.properties').newDataInputStream())
def ndkdir = properties.getProperty('ndk.dir', null)
if (ndkdir == null)
throw new GradleException("NDK location not found. Define location with ndk.dir in the local.properties file")
return (ndkdir)
}
def getNdkBuildCmd() {
def ndkbuild = getNdkDir() + "/ndk-build.cmd"
// def ndkbuild = getNdkDir() + "/ndk-build"
// if (Os.isFamily(Os.FAMILY_WINDOWS))
// ndkbuild += ".cmd"
return ndkbuild
}
//ENABLE CUSTOM ANDROID.MK <<
Now I can create my multi-library Android.mk. This builds two static-link libraries, then builds the final dynamic-link libraries and links in the first two. The directories involved are:
现在我可以创建我的多库android。这将构建两个静态链接库,然后在前两个中构建最后的动态链接库和链接。涉及的目录:
Directories:
目录:
project/
app/
build.gradle
src/
main/
java/
jni/
Android.mk
include/
libmp3lame/
MiniMp3/
mp3_jni.c
mpglib/
Android.mk:
Android.mk:
TOP_PATH := $(call my-dir)
LOCAL_PATH := $(TOP_PATH)/libmp3lame
include $(CLEAR_VARS)
LOCAL_C_INCLUDES := $(TOP_PATH)/include
LOCAL_CFLAGS := -DSTDC_HEADERS
LOCAL_MODULE := libmp3lame
LOCAL_SRC_FILES := \
bitstream.c \
...
version.c
include $(BUILD_STATIC_LIBRARY)
MY_LOCAL_STATIC_LIBRARIES += libmp3lame
LOCAL_PATH := $(TOP_PATH)/mpglib
include $(CLEAR_VARS)
LOCAL_C_INCLUDES := $(TOP_PATH)/include
LOCAL_C_INCLUDES += $(TOP_PATH)/libmp3lame
LOCAL_CFLAGS := -DSTDC_HEADERS
LOCAL_MODULE := mpglib
LOCAL_SRC_FILES := \
common.c \
...
tabinit.c
include $(BUILD_STATIC_LIBRARY)
MY_LOCAL_STATIC_LIBRARIES += mpglib
LOCAL_PATH := $(TOP_PATH)
include $(CLEAR_VARS)
LOCAL_C_INCLUDES := $(TOP_PATH)/include
LOCAL_CFLAGS := -DSTDC_HEADERS
LOCAL_MODULE := Mp3
LOCAL_STATIC_LIBRARIES := $(MY_LOCAL_STATIC_LIBRARIES)
LOCAL_LDLIBS := -llog
LOCAL_SRC_FILES := \
./mp3_jni.c
include $(BUILD_SHARED_LIBRARY)
You will need to tweak the Android.mk.
你需要调整Android.mk。