Selective renderscript libraries - android

I've been working with renderscript in my project for a while now. In a recent effort to minimize APK size, I started wondering and researching whether the renderscript native libraries (libRSSupport.so and librsjni.so) - often bundled within the APK, can be omitted for build-targets such as x86 and mips, which are not necessary for release versions of the APK? (note: the libs are added to the APK regardless of the value of APP_ABI set within Application.mk)
I have come across blogs (much like this one - http://ph0b.com/android-studio-gradle-and-ndk-integration) seemingly describing how that can be achieved using gradle. But what about projects not using gradle (as my own)? Does anybody know a way -- for example, perhaps an undocumented variable that can be added to the project.properties?
Any help will be appreciated.

You really cannot remove those libraries, as they are needed for the app to run correctly on other non-ARM devices.

Related

NDK on Android Studio keeps rebuilding all the time, takes forever

I have a big Android Studio project that has a separate module which contains native code.
The native build is defined with CMake and includes a bunch of source files of C++ code.
I noticed that since a very recent update (might be Android Studio 3.5), NDK rebuilds everything ALL THE TIME.
It can happen with a small change in Java code, switching flavor in an unrelated module in the project, incrementing version code, etc.
This is a major problem, since it can waste 10 minutes at a time for no reason.
I could not find a reasonable way to profile NDK builds in Android Studio and check what's causing the rebuild or what's taking so long.
Unfortunately the project's build files are too big to attach here. Any pointers for things to look after?
For the C/C++ code that you build with cmake, make sure you point cmake to a directory where it can keep its object files and binary outputs.
Let's say you have a dependency on Game in your top level CMakeLists.txt like so:
# dependency: Game
set ( game_src_DIR ../Game )
add_subdirectory( ${game_src_DIR} ${CMAKE_CURRENT_BINARY_DIR}/game )
Then the second parameter to add_subdirectory specified the place where AndroidStudio will keep the object files.
The debug and release object files will live in different subdirs, as will each dependency, so switching debug/release will not clash.
This appears to have been a regression in behavior from Android Studio 3.4 and has been fixed in Android Studio 4.1 Canary 4. Release notes are here.
Often, it helps to split the AS project such that the C++ part, possibly with its Java wrappers become a separate (library) module. This module will hopefully be more stable, not sensitive to increments of app version code.
Such module should not define many flavors, but have careful matching to the flavors of other modules. Sometimes, it makes sense even to disable "debug" variants for such library. There was an effort of the NDK team to better handle debug vs. release build switching, but this is still tricky.
But if after these improvements, insignificant changes to the project still cause massive rebuild, I would suggest to consider ccache.

Should I rebuild all libs when I upgrade the NDK version?

There's many shared libs(*.so) in my android project. Some of them were built by others, I don't have the source code.
I'm using NDK r10e, and I want to upgrade the NDK version to r13b.
If I don't change the makefile, just build part of the shared libs with NDK-r13b, others built with NDK-r10e were not changed. Is there any problem with capability of the android program?
NDK-r10e use clang-3.5
NDK-r13b use clang-3.8
following configurations are the same:
APP_ABI := armeabi-v7a
APP_PLATFORM := android-19
APP_STL := gnustl_shared
It's generally a good idea, but isn't always required. We try to preserve compatibility across NDK versions since, yes, moving across a compatibility boundary is difficult when you don't have the source to your dependencies, but sometimes bugs can't be fixed without breaking compatibility.
It's generally a good idea because doing so will have the least surprises. We only ever test a version of the NDK against itself. It will also save you a lot of time trying to figure what went wrong when there are compatibility breaks.
A couple examples (by no means a complete list) of things that can go wrong:
The public API surface of the NDK has changed over time. The APIs still exist on the device so that legacy apps continue working, but sometimes APIs are removed from the NDK so that new apps don't use them (there are a handful of reasons this might happen). In these cases, an old library that uses a removed symbol won't be able to be linked against a new library/executable using an NDK that doesn't have those APIs (this actually depends on the behavior of the linker; it's always true for static libraries, I think it's only arm64 for shared libraries).
For upgrading from r10 in particular, there was an ABI break in libc++ (required to avoid nasty interactions with the system) that means that libraries built with r10 and libraries built with r11+ are not compatible. You're using gnustl, so that problem won't affect you, but it's worth mentioning for others that land here.

ndk-build installs libraries even if no change. Can this be changed?

I'm using the Native Development Kit (NDK) in a project of mine, and I'm trying to automate the whole app build procedure with Python.
Whenever ndk-build is called, it copies the prebuilt shared libraries to libs/<abi>/, even if there's no changes in them or they already exist there. This causes problem when I call ant later on, as it detects changed files (the library timestamps are newer) and so rebuilds the apk without any need.
Is there a way to change the ndk-build behaviour so it checks for existing libraries in the libs/<abi>/ folder and if they need updating or some are missing, it will call ndk-build, otherwise, just proceed to the next build step?
I've tried using filecmp in Python, but as the timestamps are different between the prebuilt shared libraries and the installed ones, it doesn't work.
The OP probably doesn't need this any more, but I had the exact same problem, trying to set up a Makefile to build a project, so maybe this will be helpful to someone else in the future as well.
ndk-build is a wrapper around gnu make, that invokes a bunch of Makefiles in build/core directory of the ndk, so, while it's not universally applicable*, for your personal project you can modify those Makefiles to do whatever you want. I found a clean-installed-binaries target that a couple of build/install targets depended on, removing those dependencies fixed the issue with perpetual installs.
In whichever cases that clean target is necessary you can invoke it manually with:
ndk-build clean-installed-binaries.
*Given the time to come up with a clean opt-in solution you can submit a patch to ndk project, and if accepted it will eventually become universally applicable.

How does ADT optimize dead code for Android apps? [duplicate]

So, I've got a handful of "Utility" style classes in some of my projects. I'm curious if I can move them to an Android Library Project that contains all or most of my non-app specific glue code (wrappers and interfaces, mostly).
So, my question is what happens to the files I don't need in that library. I know Android Library Projects basically just copy their code into the other project, so if I say use 25% of the code in my "general purpose" library, will my app actually contain the bytecode for all 100%, or does it properly strip it down to only the stuff I need.
I had some issues with unused classes in Proguard in the past, so I'm just once-bitten, twice shy with the ADT now...
Unfortunately, all your projects will grow when the library is getting bigger - even if most contents of that library are not used. I tested it myself by creating an app A and a library L. If L is a library used in A, the classes.dex file (and therefore the A.apk file) is growing if I add more classes - even if they are not used.
To sum up: Right now I would create a basic library for certain things that are small and that may be used by many projects, and create a new library for every new component that is going to be larger and only is used by some projects. A good candidate for a new library would be a new UI component with multiple images defined in the resources. A good candidate for the base library are commonly-used methods and things like file caches, for example. Compiled code is compressed quite heavily for Dalvik, which you can see here. (The whole presentation is actually fun to watch :-)
Edit: If ProGuard is activated, it will also remove unused code for you. The default proguard.cfg is sufficient. It will not run on the (default) debug built, but when the final .apk is compiled. So it actually is possible!
I have used 3 level deep Android library projects successfully though it is kind of a pain. The primary use-case is when there are a set of resources and classes that you want to share across a few projects. Since I use a version control system, I would rather not use symlinks.
Note that Android Library projects also suffer greatly when dealing with resources. ADT will rebuild R.java once for each library, and each R.java will contain a copy of all resource ids from all libraries. The core problem here is that resources are regenerated for the entire project as a whole, and there is no way to "build a jar" for a dependency as would be expected with normal "libraries". We tried integrating with OpenFeint, and had all kinds of hell dealing with libraries and dependencies. I think we ended up just merging all the OpenFeint source and resource files into our own project and ditching the "Library" project as it was offering little value.
Android Library projects are a clunky way of sharing code between projects and have a number of drawbacks. I've found that everything accomplished with a Library project can also be accomplished with symlinks (symlink source into two projects). I've yet to find a usecase where an Android Library project offered something that wasn't easy to replicate with other, less fragile means.

Debug Android Native located in dependent eclipse project

(ADK 21, NDK r8d, Eclipse Juno)
[I've built several Android apps so decent experience using ADK/NDK etc]
Eclipse project setup:
- AppProject (android, java, no jni)
- LibProject (android, java, Yes jni)
Previously, all of it was in one project - builds fine, runs fine, and native debugging worked great.
Then I split off the "reusable" portion to make a library of common code to use with multiple "AppProject" application front ends. (Everything still builds, links, packs, and runs okay)
However, when I run "AppProject", I can no longer debug the native library.
What is the solution?
Possible option #1:
- Modify "LibProject" Android.mk to export a PreBuilt that is used by AppProject?
- (I would have all the debug symbols so I'm thinking that would work okay)
Would I need to cnature the AppProject as well? In other words, so it has an Android.mk to import the output .so from LibProject
Possible option #2
- http://stackoverflow.com/a/14344377/735533
- that workaround uses ndk-gdb
- I'm hoping for a solution where I can debug LibProject in Eclipse directly when running AppProject
Is there a better way to debug the native code located in the dependent project "LibProject" when running the main application "AppProject"?
Tia
For those curious ...
I tried prebuilts ...
And it definitely seems the be the way to go (test project setup worked)
But the structure of my codebase is a bit heavy on the native/non-native crosstalk and didn't want to take the time (yet) to do a proper reorganization at the moment.
However, restructuring as a prebuilt is on my "Important ToDo" list now
Anywhere, here is my solution.
On Linux (unix flavors) ... use links - the sources are linked into each AppProject from LibProject.
Basically the "LibProject" becomes a sort of "template" during development - it is not built or used as a library directly. Rather, each AppProject becomes self-sufficient, standalone, application with the contents of the library project embedded in its own code tree. Best part is native debugging works like a charm again.
Although it sort of defeats the point of making, there are benefits - one common codebase for the "library" portion ... which is really what I desire for the time being.
Also, conversion to use as a true Library dependency by the Application projects for, say, eventual release builds is an easy switch. Once debugged and ready, the Library can be built separately, packed normally with the application "front ends", and upgraded independently of the applications.

Categories

Resources