I'm entering month 3 of trying to build an Android project that uses boost for serialization.
So, I am compiling Boost 1.49 with Serialization, along with about 8 other libraries such as date_time, filesystem, iostream, etc..
Before now, trying to just build Serialization without those libraries lead to some errors to the tune of no such file or directory: assert.hpp in archive.o. So! There are dependencies between libraries when building boost. Got it.
Now, when I go to include the static libraries in my Android project, will I want to include each of those dependent libraries as well, or can I just link to the Serialization library that I'm really interested in? My guess is that I'll have to link to Serialization and each dependent static library, as well, but I'd like to know for sure. (Not having to include them all would save me a lot of time, trial, and error).
Is there an easy way to see what the dependencies between boost libraries are, so I'll know in the future when building boost what I'll actually need to compile Serialization, or which libraries to include in a project (if more than just the ones I want)? Getting boost to finally compile has been something of a 'spray and pray' approach.
Related
I have a modularized application architecture with 3 module layers.
A core library module at the bottom and an application library module and my application on top of it. Each builds it's own native shared library. But not only the java code but also the C++ code in them also depends on each other.
So my "application.so" must link to "library.so" and "core.so" and on the other hand "library.so" must link "core.so" just like you expect from any layered architecture.
I can see in the file system that the shared so libraries all end up in the same build directory but i can't find a way to make them link each other. "find_library" is not going to work. And just naming them in "target_link_libraries" is not going to work either.
EDIT: With
buildFeatures {
prefabPublishing true
}
prefab {
infosqueezer {
headers "src/main/cpp/include"
}
}
i was able to generate an aar. But i'm not able to include it into the the other module. Both debug and release aar's are generated in the "library/build/output/aar/" directory. The modules are in the same project so i just need to reference by file somehow.
I'm using
implementation project(path: ':library')
but it does not pickup the so file. Also the AAR does not contain any "libraryConfig.cmake" or "library-config.cmake" that the find_package command would need to find the link library.
Also the whole prefab process seems to be terrible. I just want to split the in project source code to reduce compile time and dependencies. Prefab is adding so much and surely a good idea to distribute indpendent libraries but overkill for internal libraries.
All i need is just a way to reference the generated "library.so" file in another module.
I know it's Android but do they really make everything so terrible complicated?
There is no supported way to depend on native libraries from other modules in the same project with externalNativeBuild (at least in part because it will lead to worse build performance, see below).
As described your project should have a single gradle module for its native code if you want the best build performance (and want to be on a supported usage model).
If you really want these to be separate, the only way to do this that works with AGP is for them to be separate projects. I don't think you should do that.
Also the whole prefab process seems to be terrible.
This isn't what it's meant for. Screw drivers make terrible hammers.
I just want to split the in project source code to reduce compile time and dependencies.
Splitting gradle projects into more modules usually makes compile times worse, not better. I can't think of any reason that it would improve build performance for native projects, and it can easily make it much slower since invoking CMake is not cheap and splitting modules up multiplies that cost.
Here is what I want to do:
There is a project written in c/c++ that I want to compile and deploy to an Android device.
I want every library that this project references to be statically linked to the whole compilation so that I can get a self contained binary (or a couple of them).
Question 1: After searching I found that there are more or less two types of libraries, dynamic and static. My question here is, do I have to provide the static libraries or is the gcc toolchain able to somehow compile them from the headers?
Question 2: When searching about static linking I only found examples of using flags only for a finite amount of libraries and for object files. I want a recursive function. That is "for every library reference within the project link the static version of it. If there is not such version, compile and link it (is this possible?)
Libraries cannot be compiled from headers. You need the sources of all libraries you need. Usually, such sources come with their build scripts, and these scripts may allow choosing static or shared target. Unfortunately, in some cases only one target type is supported.
Typically, we build third party libraries separately, using their build scripts (some involve standalone toolchains, others may use CMake to configure, yet others - and their share increases as Android platform grows in popularity - provide Android.mk build scripts and are compiled with convenient ndk-build command.
At any rate, the app that uses these libraries must include explicit references to all these libraries, usually by adding include $(PREBUILT_STATIC_LIBRARY) to its Android.mk. But if you have many libraries in one directory, you can use gnu-make wildcards, e.g.
LOCAL_LDLIBS += -Ljni/libs $(patsubst jni/libs/lib%.a,-l%,$(wildcard jni/libs/lib*.a))
I would like built a closed source android library using the Gradle. My library has some dependencies to open source projects. How should I structure my library? Can I use gradle?
Can I use gradle?
Short answer:
Yes.
Long answer:
I would assume that your library is packaged as aar (contains resources and compiled bytecode).
First thing you need to know is that at the moment of writing this post there is no way to create fat-aar libraries, which means that you'll have to distribute dependencies of your library separately. The most convenient way to do that, in my opinion, is to generate pom.xml file and publish your library on Maven repository (maven plugin can do all of that), so clients will just fetch all dependencies themselves. Since it is a "private" library, that could be your company's closed repo by access rights (in simple words - create special user for your repo and share password with interested parties).
One downside here is that all dependencies will be exposed in pom.xml and you won't be able to obfuscate them. Personally, I don't think that this is an issue.
Moreover, you get the huge advantage of being able to deploy build automatically and let clients use snapshot versions of the library. This is extremely helpful when you're trying to fix issues and want to deliver them to users fast. On client's side, all they need to do is either just update version in their build.gradle or just re-sync project in case if they were using snapshot.
Second thing. Since your library is closed source, you need to run proguard to obfuscate everything but public interface of your library (all public methods which are exposed to end user).
Remember, that even after obfuscation your code still can be decompiled and all string literals are still there. So, although it was said million times already, avoid storing any critical data in the library (such as passwords, keys, etc.). It is not as hard to extract it as you might think it is: https://www.youtube.com/watch?v=X28Oogg2Q3k
Third thing. I highly suggest you to create internal test project (as a gradle submodule) which will use your library, so you will be sure that you're not making any breaking changes.
Hopefully this answer made things at least a bit easier for you.
I have an Android project which includes NDK code. From this code, I need to call functions from other libraries built with NDK, which I have in the jniLibs folder:
jniLibs/armeabi/libtess.so
jniLibs/armeabi-v7a/libtess.so
...
if I try to load these libraries from java, as System.loadLibrary("tess"), it works fine.
However, when I try to link my NDK library to it by adding this to build.gradle:
ndk {
moduleName "myJNILib"
stl "stlport_shared"
ldLibs "log", "tess"
}
it cannot find it.
And of course, if I don't link against it, it cannot compile myJNILib, since it can't find the symbols.
Is there anyway to make this work using gradle? Or I really need to build my library outside of gradle if I want to link with other prebuilt libraries?
What I think you'll want to do is mostly rely on the natural NDK building... stuff... I'm not sure what a good word for that is.
Anyway, you'll want to follow this tutorial. It worked for my own stuff pretty neatly. You'll also, more than likely, want to read this introduction to Android.mk files. It's very helpful for debugging and making sure you're linking correctly.
You may run into two problems in doing this:
Undefined symbol errors, which can be an absolute pain. More than likely you will want to eliminate that dependency. I spent hours on this problem and finally concluded that the file must just not be there. Somehow.
You may also run into it not being able to find an extension of the file you're working on (Ergo, it may say that foo1.so can't find the library foo2.so.# despite you having linked foo2.so. You may have to compile a .a library if that happens, but that may not be the best solution.).
Well, I hope that helps!
So, I have a little C library. I want to make this library available to other devs that develop native C code in android (other libraries, native apps etc).
What's the best way to go? I don't really have much clue yet, trying to figure all this out.
I've read that there are two paths to go with the NDK: using Android.mk and using create-standalone-toolchain -- is this correct? How does each one of these works? Is there a third way without the NDK, and should this be used now that the NDK is available?
**
This may have been asked before, but I understand things have changed since the release of the NDK, as a lot of posts I find seem obsolete.
this question can have a Huge answer, I will try to be as brief as possible.
Using the Android NDK, make a new android project, create a JNI folder, and create an Android.mk file, in it, make two libs, one being your lib, exported as a shared lib and the other, a jniwrapper that will test it. Here is an example of how it was done by a guy for his own lib.
You can make a shared lib by compiling with the standalone toolchain, here is an article on the subject and also take a look at the curl Readme for android, it explains how to compile curl for Android using the standalone toolchain, I believe it's the better way to do it, and also to easier for you since you will use the cross-compiler in a regular fasion...