Android Studio 2.0 Preview 5, linking ndk app fails to locate module .so and .a - android-studio

I have an ndk project with two modules:
abwrenderer - native library module
app - native and java hybrid, glues java to the abwrenderer
I just updated to AS 2.0 Preview 5 this morning, and encountered some gradle related issues.
I upgraded to gradle-2.10 and switched to gradle-experimental:0.6.0-alpha5. When attempting to debug, an ndk build is triggered and I run into the following problem:
Error:error: C:\android\projects\foo\abwrenderer\build\intermediates\binaries\debug\obj\armeabi-v7a\libabwrenderer.so: No such file or directory
Now when I was on gradle-2.9 & gradle-experimental:0.6.0-alpha3, the libraries were built in this directory. After this morning's upgrades, the libraries are now located in:
C:\android\projects\foo\abwrenderer\build\libs\abwrenderer\shared\armeabi-v7a\debug
Is there a way to update the search location for project dependencies that build libraries?
For reference, I define the dependency on abwrenderer project as follows (build.gradle (app)):
android.sources {
main {
jni {
source {
srcDirs 'src/main/jni'
}
dependencies {
project ":abwrenderer" buildType "debug" linkage "shared"
}
}
jniLibs {
source {
srcDirs 'src/main/libs'
}
}
}
}
And build.gradle for abwrenderer project is as follows:
apply plugin: "com.android.model.native"
model {
android {
compileSdkVersion = 23
}
android.ndk {
moduleName = "abwrenderer"
cppFlags.addAll(["--std=c++11",
"-fexceptions",
"-frtti"])
ldLibs.addAll(["android", "EGL", "GLESv3", "log", "dl"])
stl = "c++_static"
debuggable = true
}
android.sources {
main {
jni {
exportedHeaders {
srcDir "src/main/jni"
}
}
}
}
}
I have invalidated caches and restarted, done a clean build, etc. Any help would be greatly appreciated!

Your defaultConfig and ndk blocks were missing some info. They should look similar to this:
defaultConfig {
applicationId = 'com.myapp.abwrenderer'
minSdkVersion.apiLevel = 13
targetSdkVersion.apiLevel = 23
versionCode = 1
versionName = '1.0'
}
ndk {
platformVersion = 21
moduleName = 'abwrenderer'
toolchain = 'clang'
stl = 'gnustl_static'
cppFlags.addAll(['-std=c++11'])
ldLibs.addAll(['android', 'EGL', 'GLESv3', 'log', 'dl'])
}
You should take a look at the following NDK sample from Google to see how they did it: hello-libs

Related

Android Studio - error: linker command failed with exit code 1

I downloaded the code from this repository (its a app to control a parrot drone):
Github
with the hopes of getting it to work so i can study the code, however im getting this error that seems hard to find a solution after searching the web, i mostly found things for IOS, xcode, etc
I imported the project into android studio, when i try to execute the app i get the following error:
Error:error: linker command failed with exit code 1 (use -v to see invocation)
I am not really into NDK, but from what i saw it could be the reason, things i tried:
Downloaded NDK and added the correct path to it.
Using latest SDK.
Changes to build.gradle like setting buildToolsVersion "25.0.0", etc
Build.gradle (Project: ardrone)
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.2.2'
}
}
allprojects {
repositories {
jcenter()
}
}
Build.gradle (Module:app)
import org.apache.tools.ant.taskdefs.condition.Os
apply plugin: 'com.android.application'
android {
compileSdkVersion 24
buildToolsVersion "25.0.0"
defaultConfig {
multiDexEnabled true
applicationId "com.parrot.freeflight"
minSdkVersion 9
targetSdkVersion 24
versionCode 20000
versionName "2.0-SDK"
ndk {
moduleName "adfreeflight"
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
// TODO proguard-rules seem outdated and useless cause it's only Android stuff
}
}
sourceSets.main {
jni.srcDirs = [] // This prevents the auto generation of Android.mk
jniLibs.srcDir 'src/main/jniLibs'
// This is not necessary unless you have precompiled libraries in your project.
}
task buildNative(type: Exec, description: 'Compile JNI source via NDK') {
def ndkCommand = "${android.ndkDirectory}/ndk-build"
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
ndkCommand += ".cmd"
}
commandLine ndkCommand,
'-C', file('src/main/jni').absolutePath,
'-j', Runtime.runtime.availableProcessors(),
'all',
'NDK_DEBUG=1'
}
task cleanNative(type: Exec, description: 'Clean JNI object files') {
def ndkCommand = "${android.ndkDirectory}/ndk-build"
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
ndkCommand += ".cmd"
}
commandLine ndkCommand,
'-C', file('src/main/jni').absolutePath,
'clean'
}
clean.dependsOn 'cleanNative'
tasks.withType(JavaCompile) {
compileTask -> compileTask.dependsOn buildNative
}
}
dependencies {
compile 'com.google.android.gms:play-services:10.0.0'
compile files('libs/android-support-v13.jar')
compile files('libs/com.sony.rdis.receiver-20111206.jar')
compile files('libs/com.sony.rdis.receiver.utility-20111206.jar')
}
local.properties
ndk.dir=C\:\\Users\\BugDroid\\AppData\\Local\\Android\\Sdk\\ndk-bundle
sdk.dir=C\:\\Users\\BugDroid\\AppData\\Local\\Android\\Sdk
You need to check your log for more details as the error 'Linker command failed with exit code 1' is usually followed by the more detailed error.
So to find more details, in Xcode click on the error under Buildtime and choose Reveal in log. This should give you extra hint. Without any specific error, it's difficult to know what's the problem.

Could not find method externalNativeBuild() for arguments

i'm trying to integrate the ndkBuild functionality into an existing android studio project, using the new android studio 2.2 , in order to enable c++ debugging etc.
i have tried out one of the ndk example projects which android studio 2.2 offers, which works perfectly fine. However, when i try to run the gradle commands in my own project, i get this error message:
Error:(73, 0) Could not find method externalNativeBuild() for arguments [build_c6heui1f67l8o1c3ifgpntw6$_run_closure2$_closure9#4329c1c9] on project ':core' of type org.gradle.api.Project.
By following this description
http://tools.android.com/tech-docs/external-c-builds
i ended up with a gradle script which includes the following commands:
externalNativeBuild{
ndkBuild{
path "$projectDir/jni/Android.mk"
}
}
externalNativeBuild {
ndkBuild {
arguments "NDK_APPLICATION_MK:=$projectDir/jni/Application.mk"
abiFilters "armeabi-v7a", "armeabi","arm64-v8a","x86"
cppFlags "-frtti -fexceptions"
}
}
Did i perhaps miss out on something here with the project setup?
I have set the Android NDK location properly under
File -> Project Structure ... -> SDK Location -> Android NDK location
in my android studio.
Anything else i might have forgotton?
Has anyone run into a similar problem before?
Advice would be much appreciated =)
Just had this error myself. In your root build.gradle, make sure that gradle is set to at least version 2.2.0:
So you should have the following in buildscript {...}
dependencies {
classpath 'com.android.tools.build:gradle:2.2.0'
}
Suggested by Kun Ming Xies answer, I have separated my cmake part in two to get rid of the annoying error:
Could not find method arguments() for arguments [-DREVISION=1.3.1] on object of type com.android.build.gradle.internal.dsl.CmakeOptions.
The first part in defaultConfig contains the configuration (command line arguments for CMake and C++ flags), and the second contains the path to CMakeLists.txt:
def revision = "1.3.1"
android {
compileSdkVersion 25
buildToolsVersion "25.0.2"
defaultConfig {
versionCode = ...
versionName "${revision}"
externalNativeBuild {
cmake {
arguments "-DREVISION=${revision}"
cppFlags '-fexceptions', '-frtti', '-std=c++11'
}
}
}
buildTypes { }
lintOptions { }
externalNativeBuild {
cmake {
path 'CMakeLists.txt'
}
}
}
android {
defaultConfig {
externalNativeBuild {
cmake {
arguments '-DANDROID_TOOLCHAIN=clang'
}
}
}

Build and link multiple NDK libraries using gradle

I have an Android project that links together a bunch of sources into a single monolithic JNI library. I would like to split this single library out into multiple smaller libraries with some dependencies between them. How can I achieve this with the new gradle build system?
You can achieve this with the standalone android native plugin from the experimental gradle plugin family. The new plugins are based on the gradle component approach towards modeling builds. There are many advantages to using the new system.
For example:
root
+ lib -> 'com.android.model.native'
+ lub -> 'com.android.model.native'
+ aar -> 'com.android.model.library'
+ app -> 'com.android.model.application'
build.gradle
configure([project(':lib'), project(':lub'), project(':aar'), project(':app')]) {
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle-experimental:0.6.0-alpha5'
}
}
}
lib/build.gradle
apply plugin: "com.android.model.native"
model {
android {
compileSdkVersion 23
ndk {
moduleName "foo"
}
sources {
main {
jni {
exportedHeaders {
srcDir "src/main/headers"
}
}
}
}
}
lub/build.gradle
apply plugin: "com.android.model.native"
model {
android {
compileSdkVersion 23
ndk {
moduleName "bar"
}
sources {
main {
jni {
exportedHeaders {
srcDir "include"
}
}
}
}
}
aar/build.gradle
apply plugin: "com.android.model.library"
model {
android {
buildToolsVersion '23.0.2'
compileSdkVersion 23
ndk {
moduleName "aggregate-jni"
stl "stlport_shared" // using cpp?
}
sources {
main {
jni {
dependencies {
project ":lib"
project ":lub"
}
}
}
}
}
app/build.gradle
apply plugin: 'com.android.model.application'
model {
android {
buildToolsVersion '23.0.2'
compileSdkVersion 23
defaultConfig {
applicationId "com.example.app"
minSdkVersion.apiLevel 21
targetSdkVersion.apiLevel 23
versionCode 1
versionName "1.0"
}
}
}
dependencies {
compile project(':aar')
}
If linkage is dynamic (default for ndk), the aar will contain:
libfoo.so libbar.so libaggregate-jni.so libstlport.so
and your mirror java classes. You can simply
System.load("aggregate-jni");
in your java classes and referenced libraries will load too. If linkage is static, you'll end up with a single libaggregate-jni.so anyway. Note that it's bad to link a bunch of things statically against the stl as you will end up with multiple copies of the stl in your binary. This can really mess things up.
Note that the default gcc toolchain is now deprecated. It's probably best to use:
model {
android {
ndk {
toolchain 'clang'
stl 'c++_shared'
}
}
}
Finally, you absolutely don't need an aar, I simply included it for completeness. The app project can depend directly on standalone native lib projects as the application plugin fully support the ndk, too.

Missing dependencies tab in android studio

Screenshot http://i.imgur.com/2i41Vih.png
My project is named Pudge. When I open Module settings, I select my project and all the tabs (dependencies, etc.) are missing.
This is probably something stupid, but I don't know what.
Edit: adding more info:
The project has a folder named libraries, and in it there is the folder of the library (facebook in my case)
build.gradle of the main project
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.7.+'
}
}
apply plugin: 'android'
repositories {
mavenCentral()
}
android {
compileSdkVersion 17
buildToolsVersion "17.0.0"
sourceSets {
main {
manifest {
srcFile 'AndroidManifest.xml'
}
java {
srcDir 'src'
}
res {
srcDir 'res'
}
resources {
srcDir 'src'
}
}
test {
java {
srcDir 'tests/src'
}
}
}
defaultConfig {
minSdkVersion 17
targetSdkVersion 17
}
}
dependencies {
compile project(':libraries:facebook')
compile 'com.android.support:appcompat-v7:18.0.0'
compile 'com.google.android.gms:play-services:3.2.25'
}
task wrapper(type: Wrapper) {
gradleVersion = '1.8'
}
build.gradle of the facebook library
apply plugin: 'android-library'
dependencies {
compile 'com.android.support:support-v4:13.0.+'
}
android {
compileSdkVersion 17
buildToolsVersion "17.0.0"
defaultConfig {
minSdkVersion 17
targetSdkVersion 17
}
sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml'
java {
srcDir 'src'
}
res {
srcDir 'res'
}
}
}
}
settings.gradle
include ':Pudge'
include ':libraries:facebook'
As I said in the comments - after I added the library through the gradle files - its working. But the tabs are still missing.
Looking at your main build file, it has the comment in it about being the top-level build file, so it looks like your main module is located at the project root instead of inside a folder. This is probably what's confusing the Project Structure dialog, because when it examines settings.gradle, it expects to see modules in the Pudge and libraries/facebook directories.
If my assumption about your main module being at the project root is correct, if you change your settings.gradle file to this it should work:
include ':'
include ':libraries:facebook'

NDK Debugging with gradle-experimental plugin

I'm trying to add native debugging to a project that is an Android Studio NDK project. In the past I just used gradle to kick off a shell script, which built the NDK lib. Now I'm trying to move to use the gradle-experimental plugin.
I've scoured the net for what little info there is, (mostly here, Android Tools Site - Gradle Experimental), about using gradle-experimental with the NDK and I've put together this build.gradle file which is using the preview NDK support for doing the NDK build inline with the Java build.
After finally getting this together from bits-and-pieces of info, I managed to get the NDK portion building, but now it fails to include the httpmime-4.4-beta1.jar file that is clearly included in the dependencies, and I've tried many different permutations of it such as in:
compile files("libs/httpmime-4.4.jar")
But regardless, the errors for the missing symbols from the Jar file still appear.
build.gradle source
apply plugin: 'com.android.model.application'
String APP_PACKAGE_NAME = 'com.obfuscated.app',
VERSION_NAME = '3.0',
TOOLS_VERSION = '23.0.2'
int VERSION_CODE = 15,
MIN_SDK_VERSION = 13,
TARGET_SDK_VERSION = 19,
COMPILE_SDK_VERSION = 23
model {
repositories {
libs(PrebuiltLibraries) {
// prebuilt binaries mirroring Android.mk
libstuff {
headers.srcDirs.add(file("jni/stuff/include/stuff"))
binaries.withType(SharedLibraryBinary) {
sharedLibraryFile = file("jni/stuff/lib/libstuff.so")
}
}
// ...several more of these actually exist in build.gradle and are working
cares {
headers.srcDirs.add(file("jni/c-ares/include"))
binaries.withType(SharedLibraryBinary) {
// StaticLibraryBinary and staticLibraryFile doesnt work despite sample code, at least not for com.android.tools.build:gradle-experimental:0.6.0-alpha5, this builds even though its a static-lib
sharedLibraryFile = file("jni/c-ares/lib/libcaresARM.a")
}
}
}
}
android {
compileSdkVersion = COMPILE_SDK_VERSION
buildToolsVersion = TOOLS_VERSION
defaultConfig.with {
applicationId = APP_PACKAGE_NAME
minSdkVersion.apiLevel = MIN_SDK_VERSION
targetSdkVersion.apiLevel = TARGET_SDK_VERSION
versionCode = VERSION_CODE
versionName = VERSION_NAME
buildConfigFields {
create() {
type "int"
name "VALUE"
value "1"
}
}
compileOptions.with {
sourceCompatibility = JavaVersion.VERSION_1_7
targetCompatibility = JavaVersion.VERSION_1_7
}
}
signingConfigs {
create("appRelease") {
storeFile file('sign.jks')
storePassword '...'
keyAlias '...'
keyPassword '...'
storeType "jks"
}
}
} // end android
android.lintOptions {
abortOnError = false
}
android.packagingOptions {
exclude 'META-INF/NOTICE'
exclude 'META-INF/LICENSE'
exclude 'META-INF/services/javax.annotation.processing.Processor'
}
android.ndk {
moduleName = "native"
toolchain "clang"
toolchainVersion "3.5"
platformVersion = MIN_SDK_VERSION
ldLibs.addAll('atomic', 'android', 'log', 'OpenSLES')
abiFilters.addAll(["armeabi", "armeabi-v7a"])
CFlags.addAll(["-mfloat-abi=softfp", "-mfpu=neon", "-O3", "-DCARES_STATICLIB", "-Wno-c++11-long-long"])
cppFlags.addAll(["-I${file("jni")}".toString(),
"-I${file("jni/c-ares/include")}".toString(),
"-I${file("jni/coffeecatch")}".toString()])
stl = "stlport_shared"
}
android.sources {
main {
jniLibs {
dependencies {
}
}
jni {
dependencies {
library "libstuff"
library "cares"
// ...
}
source {
srcDir "jni"
}
}
// java {
// dependencies {
// compile files("libs/httpmime-4.4-beta1.jar")
// compile files("libs/FlurryAnalytics-5.1.0.jar")
// }
// }
}
}
android.buildTypes {
debug {
ndk.with {
debuggable = true
}
}
release {
minifyEnabled = false
ndk.with {
debuggable = true
}
}
}
android.productFlavors {
create("arm") {
ndk.with {
abiFilters.add("armeabi-v7a")
ldLibs.addAll([file("jni/stuff/lib/libstuff.so").toString(),
file("jni/c-ares/lib/libcaresARM.a").toString()])
}
}
create("fat") {
// compile and package all supported ABI
}
}
} // end model
repositories {
mavenCentral()
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:support-v4:23.+'
compile 'com.android.support:appcompat-v7:23.+'
compile 'com.android.support:support-v13:23.+'
compile 'com.android.support:support-annotations:23.+'
compile 'com.squareup:otto:1.3.8'
compile 'com.github.machinarius:preferencefragment:0.1.1'
compile 'org.apache.httpcomponents:httpclient-android:4.3.5.1'
compile 'com.fasterxml.jackson.core:jackson-core:2.5.+'
compile 'com.fasterxml.jackson.core:jackson-annotations:2.5.+'
compile 'com.fasterxml.jackson.core:jackson-databind:2.5.+'
compile 'com.jakewharton:butterknife:7.0.1'
compile 'com.google.guava:guava:19.0'
}
allprojects {
tasks.withType(JavaCompile) {
options.compilerArgs << "-Xlint:deprecation" << "-Xlint:unchecked"
}
}
Out of frustration, I switched back to the non-experimental branch, and even with the old build.gradle file it is now failing to find that same jar file. So is it a problem with Android Studio 2.0 Preview 6?
Has anyone else experienced this, or have a solution for it? It would be so convenient to finally have NDK debugging work right in Android Studio, and if it weren't for this last hurdle, I think I would be there.
Short of re-writing the code that depends on that jar file, I am at a loss for what else to try. I am also open to suggestions for the format of my build.gradle file above, since the documentation for these new features is very sparse still, and some of the samples seem to be already out-of-date with regard to the proper syntax.
WHAT AM I MISSING?
You can see that the C and Cpp (mobile:compileNativeArmeabiDebugArmSharedLibraryNativeMainCpp), steps are happening just fine, but then the Javac fails. This jar file approach has worked fine for the past 2 years or so for the http-mime lib from apache, so I don't understand why suddenly this is a problem.
:mobile:mergeArmDebugAndroidTestAssets
:mobile:generateArmDebugAndroidTestResValues UP-TO-DATE
:mobile:generateArmDebugAndroidTestResources
:mobile:mergeArmDebugAndroidTestResources
:mobile:processArmDebugAndroidTestResources
:mobile:generateArmDebugAndroidTestSources
:mobile:copyArmeabi-v7aDebugArmSharedLibraryStlSo
:mobile:compileNativeArmeabi-v7aDebugArmSharedLibraryNativeMainC
:mobile:compileNativeArmeabi-v7aDebugArmSharedLibraryNativeMainCpp
:mobile:linkNativeArmeabi-v7aDebugArmSharedLibrary
:mobile:nativeArmeabi-v7aDebugArmSharedLibrary
:mobile:stripSymbolsArmeabi-v7aDebugArmSharedLibrary
:mobile:ndkBuildArmeabi-v7aDebugArmSharedLibrary
:mobile:ndkBuildArmeabi-v7aDebugArmStaticLibrary UP-TO-DATE
:mobile:copyArmeabiDebugArmSharedLibraryStlSo
:mobile:compileNativeArmeabiDebugArmSharedLibraryNativeMainC
:mobile:compileNativeArmeabiDebugArmSharedLibraryNativeMainCpp
:mobile:linkNativeArmeabiDebugArmSharedLibrary
:mobile:nativeArmeabiDebugArmSharedLibrary
:mobile:stripSymbolsArmeabiDebugArmSharedLibrary
:mobile:ndkBuildArmeabiDebugArmSharedLibrary
:mobile:ndkBuildArmeabiDebugArmStaticLibrary UP-TO-DATE
:mobile:processAndroidArmDebugMainJniLibs UP-TO-DATE
:mobile:androidArmDebug
:mobile:compileArmDebugJavaWithJavac
:mobile:compileArmDebugJavaWithJavac - is not incremental (e.g. outputs have changed, no previous execution, etc.).
Yes, I know the apache libs are deprecated, but this is legacy code that should work despite that fact, and will be updated in the future.
A general way to do the include you're looking for is this in the dependencies.
compile fileTree(dir: 'libs', include: ['*.jar'])
However, I'm not certain that will solve this particular problem. I've always had success with putting the jar in the libs directory at the top of the directory structure.
If you need to have the jar in a different location, then this works for me:
repositories {
flatDir {
dirs '<relativePathToJar>'
}
}
model { ... }
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
}

Resources