I'm currently using ant to build Android projects but it simply doesn't cut it for larger projects and maintaining different deliverables is becoming a pain.
Two alternatives I'm looking at are Facebook's Buck (http://facebook.github.io/buck/) and Gradle that Google is backing with Android studio (http://tools.android.com/tech-docs/new-build-system/user-guide).
Besides trying them out and reading up on their coverage I would like to ask you fine Stackoverflow people for your recommendations. Preferably if you've used either tool for a while, with bonus points for Buck since it didn't get that much coverage.
Important points are
build speed, specifically for dev builds
multiple deliverables from same code base
ease of use
I'm open to other alternatives as well. What do you suggest and why?
As I put front and center in the Buck documentation: "Buck is a build system for Android that encourages the creation of small, reusable modules consisting of code and resources."
By design, Buck encourages you to create small modules so that you can easily compose a new app out of your existing building blocks. This means that maintaining multiple deliverables is straightforward: it eliminates boilerplate without requiring you to organize your repository into a predefined structure. You can also create ad-hoc build steps to suit your needs with Buck via macros and genrules. (A more formalized extension system is in the works.)
We also care a lot about speed, particularly the speed of incremental builds. Because Buck has a strong concept of dependencies, we can often avoid rebuilding intermediate artifacts. Other build systems also try to do this (like Ant), but frequently sacrifice correctness, as a result. We don't.
We recognize that IDE support is important. Certainly Google's collaboration with Gradle gives them a leg up there. However, Buck has a command to generate an IntelliJ project from the dependency graph defined in Buck build files, and we have broken ground on our own IntelliJ plugin, so this is something that we also care deeply about.
Finally, bear in mind that Buck is used to build Facebook, Facebook Messenger, and Instagram for Android. Buck is not going away. Further, the code for all three apps (and reduced versions of the apps, for even faster development cycles) lives in one Git repository at Facebook, so those of us working on Buck internally are sensitive to the needs of large codebases that support multiple deliverables.
Long-term, the new Gradle build system will be the standard, and it looks very good.
However, it looks like it's not quite ready for use in non-trival projects yet. For instance, it looks like it doesn't support apklib dependencies yet.
This is understandable, and reflected in the fact that the current version is 0.3
I'm looking forward to seeing it evolve.
For a project that needs to be build today, I'd use Maven. Actually, I'm in the process of moving a client's build from Eclipse-only to Maven right now, so that they can have a repeatable build process, good dependency management, and CI.
The new Gradle build looks like it will be more flexible, but right now Maven handles apklibs. Since Gradle can use Maven dependencies, I'm expecting that we'll be able to move from Maven to Gradle easily in the future.
I don't know anything about Buck. However, that in itself is a red flag. I'd hesitate to use a build system that few people know anything about. That doesn't mean that it's not good - it may be great. But using it now is probably a gamble.
Here is a gradle plugin OkBuck which can let you start using BUCK base on your current Android Studio + Gradle build system with only 10 lines of configuration. Check it out.
OkBuck can let you build your project both with gradle and buck, with all advantages of gradle and buck.
I would add the following advantages of Buck:
Exopackage, i.e. incremental apk build; just check the table with build time on that page
Network cache. If you have several developers working with an app, you won't need to rebuild components which are already built by other developers.
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.
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.
My server needs to keep building a large amount of Android projects. All of them are almost identical except for minor change on manifest.xml or any resource file (if it's better for the task) for each build. To reduce cost and improve efficiency, I try to implement incremental build. My planned procedures are:
after the first successful build, skip all the previous
procedures (aapt to generate R.java, adle to make java, etc.)
directly call aapt to make resource files, e.g., *.ap_
call apkbuilder to make classes.dex and usigned.apk
make signed.apk
So my question is whether the above solution is possible? And any clue about how to implement it?
This isn't necessarily a solution for your particular requirements but perhaps it will provide you with some useful pointers.
I have an Antlib that I use for building Android projects. You probably won't want to use it yourself as it has some drawbacks, but it should serve as an example of how to perform the various steps to build an Android app using Ant. In particular, it shows how to call the various Android SDK tools from Ant and how to use the Ant uptodate task and Ant's if and unless attributes to avoid processing files that haven't changed.
The source for the Android Ant macros is here (the Antlib documentation might help you to make sense of what it's doing).
I'm evaluating whether to use Ant or Maven to automate my build process for Android development. I've been trying to read online to make an informed decision, but haven't found many specifics that relate to Android development. Based on your experience:
What are the main differences ?
I've read some people saying they have different purposes ? What would those be ?
What would make you pick one over the other ?
What are the strong points and weaknesses of each ?
Which is easier to setup and maintain ?
Is there one that is proffered/most used in the community ?
I found a similar question What benefits does Maven give (over ant) for building android projects?, but he was asking about the
benefits of Maven over Ant and, first, I don't even know the Ant benefits and, second, he just got one answer that didn't make things clear for me.
I use Intellij, just in case it makes any difference though I hope it doesn't.
If you can use Maven, go with Maven. And, don't you dare try to change the standard directories! Heck, even when we use Ant, I insist we setup the directories like Maven. That way, new developers know where things are, or have to trace through the build.xml to find where things are located. The other things is that if you do use Ant, you should also use Ivy. That way, you get the Maven dependency handling within Ant.
The big irony is that once we use Ant and Ivy, and stick to the standard Maven directory structure, moving from Ant to Maven is a cinch. But, the need to move to Maven is lessened too. Our build.xml is clean and simple to understand. All the files are in the right place. Builds are quick, simple, and easy to maintain. Who needs Maven?
The problem is once we've reach this state of Nirvana, is to keep the project from heading back to the State of New Jersey. Developers start carving out exceptions in our build.xml. Don't compile this *.java file. Move this *.xml into our java directory, put test code under the main directory, but we'll put the name test in the file, so we know it's test code... New and complex things are done. And, somehow, we're back in Secaucus.
So, once I've got my Ant project clean and neat enough to move to Maven, I make the leap.
One more thing: Maven makes it very, very simple to copy a project from one computer to another. Maven handles all the dependencies stuff -- even the build stuff. No more, you need AntContrib, or you need to download the hibernate Ant tasks. If you need something, it'll download itself. It's one of the big reasons Maven is so popular with many open source sites.
My big complaint about Maven is that it's so poorly documented. There's a Wiki, but almost no content, and very few manuals.
I've not used Ant or Maven much for Java recently, but I can tell you the main differences between them -- it basically boils down to automated conventions (Maven) vs. absolute flexibility (Ant).
Maven will do almost everything for you, but it's much easier to use if you arrange your projects to suit it. It'll handle dependency tracking and resolution, building, packaging and storing the built packages, while also helping with branch maintenance and release engineering. I find it an awful lot easier to release my (flex) projects that are built with Maven.
Ant is much more flexible. You can do whatever you want, build in whichever way you want. If you have pre-existing projects, you can automate much of what your IDE is doing without changing anything else. It doesn't hand-hold as much as Maven, which also makes it easier to diagnose when things go wrong... You're on your own for dependencies, branches and releases, though. Where we use ant, we use it because we had a project set up which we wanted to automate, and Maven wouldn't adapt to fit it. If you need to do something not supported by Maven, Ant may be your only hope.
Personally, I'd use Maven over Ant if possible, but I'd admit that it's not always possible.
Consider using Gradle!
It combines the best from Maven (convention over configuration) with the best from Ant (the flexibility and the huge library of pre-made tasks).
A Gradle build is written in Groovy, so you have the full power of a scripting language at your fingertips!
There is an Android plugin for Gradle. I haven't used it though, so I cannot tell if it's good or not.
See http://www.gradle.org
I agree with Andrew's answer in its entirety. However, I would note that the maven support is not supplied by the android SDK team. It's provided by a third party. Now, they are an active participant, but it still means that there may be a delay in getting support for the very latest features.
That said, I don't particularly like the ant support provided by the android SDK team. If you run android create project you'll end up with a build.xml that recommends you copy paste chunks of XML in order to customise it. This makes it burdensome to move to a new version of the Android SDK.
Overall, I suspect that moving to maven will be easier to maintain over the long run.
I have an Android code base which uses APIs with settings to get different data for several apps. All apps use the same code base but with one or two design tweaks. So how do I re-use the main code base without having to copy the whole Android project each time?
iPhone uses multiple targets in the same project which works well. If android cant do this do I need to compile binaries of the code base in one project and then import into each new app project? If so how? I'm using Eclipse and am an intermediate Java developer.
Any help much appreciated!
Doug
Check out "Working With Library Projects" from the Android documentation. This should be just what you're looking for: http://developer.android.com/tools/projects/projects-eclipse.html#SettingUpLibraryProject
The current way to approach this issue if you are using Android Studio with Gradle is by using Gradle, Build Type + Product Flavor
http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants
Build Variants
One goal of the new build system is to enable creating different versions of the same application.
There are two main use cases:
Different versions of the same application
For instance, a free/demo version vs the “pro” paid application.
Same application packaged differently for multi-apk in Google Play Store.
This new concept is designed to help when the differences are very minimum. If the answer to “Is this the same application?” is yes, then this is probably the way to go over Library Projects.
Note: This answer is basically obsolete now that one can create .aar libraries with resources. It still works, though, and there may be times when the portability of a .jar is desirable, so I'm leaving it here.
Blumer's answer is a good one, and you should definitely look into Android's idea of library projects. However, there is another alternative. If you have a module that contains only Java code, but no resources of any kind (images, layouts, etc.), you can compile it to a .jar file separately and use the resulting .jar in multiple application projects. It works like this:
Create a new Java project in Eclipse (not an Android project) and move the source code of your module there.
If your module references any classes from the SDK, you'll need to add the Android SDK .jar to the project's classpath (Project > Properties > Java Build Path > Libraries > Add JAR).
When your module is ready to use, bundle up its .class files into a .jar. You can do this manually, or you can look around to figure out how to get Eclipse to do it for you.
Copy your module .jar file into the "libs" directory of your app's main project.
Add the module .jar to the project's classpath (again, Project > Properties > Java Build Path > Libraries > Add JAR).
Now you should be able to build multiple apps using the same .jar, while maintaining only one copy of the module's source code.
Depending on your particular situation, this may or may not work any better for you than the standard Android library mechanism. But it's worth considering as an alternative.
The Android documentation recommends another approach if there aren't too many "different APIs" used.
The idea is to use reflection instead of making direction references to the code. Make sure to use optimized reflection instead of lookups every time.
References
http://developer.android.com/training/multiple-apks/api.html
http://developer.android.com/google/play/publishing/multiple-apks.html#ApiLevelOptions
You might want to consider using a source control system like Subversion (or GIT). Keep your most feature complete version in the trunk, and make branches for your separate versions that use different data sources or require minor layout changes, etc.