-
Notifications
You must be signed in to change notification settings - Fork 4
Home
There are a lot of powerful open source libraries available written in C/C++, and I like to take advantage of these.
In recent past, each library I added came with baggage. Since I was building for iOS and Android, each one had to be cross-compiled because sadly there is no apt-get install libpng
on mobile platforms. The problem was: there was no automation for building these external libraries.
I began looking at the tools that were available and stumbled upon cmoss, a collection of scripts for building various open source libraries for iOS and Android. It was a good start, but it needed a bit of tweaking and it was a hassle to add libraries not on the list, and also maintaining a collection of bash scripts is not the most elegant solution. This was when the idea for AmigoMake was born.
AmigoMake is the build system we use here at AmigoCloud, both for external libraries and our own code. When I began writing AmigoMake the initial idea was just to automate and manage external libraries, but then it became clear how I could integrate the system with our own code as well.
Before, I had makefiles in multiple directories that explicitly defined all the source files. Adding or removing files in our code base was a tad annoying. I thought about how I never had this issue with my Java code: just add a new class and the IDE handles it. I wanted AmigoMake to work in a similar fashion: I only want one makefile where I specify dependencies and build parameters and not list all the files in a directory that end in .c or .cpp. AmigoMake will find the source files and build a header dependency tree, and then it will call clang/gcc for you with the correct flags. In fact, there's no need to stick to the include/src directories. AmigoMake will correctly resolve regardless of the directory structure, and additionally has an option to export all the headers.
For Android in particular this made my life a lot easier. I could now integrate most open source libraries with a few lines of python code using the NDK standalone toolchain. I no longer had to search how to build a particular library for Android and find/write a proper Android.mk; instead, I could now easily cross-compile anything compatible, and have a shiny new shared library within minutes!
- C/C++ Code Compilation
- gcc and clang support
- iOS, Android, x86 target support
- header dependency tree(recompile only updated files)
- External Libraries
- easy to wrap make, cmake, and others
- dependency handling
- multiple libraries can be merged into one static or shared lib
- included examples
- proj4, libpng, libjpeg, gmock
- sqlite, freetype, minizip, bzip
- openssl, cURL, libicu, boost
- Makefiles written in Python
- AmigoMake packages specify a directory
- no need to add individual files
- support to exclude sub-directories and files
- Import custom python code if needed
- AmigoMake packages specify a directory
- Easily Extensible
The following would allow the user to build a static library from all C/C++ files (recursively located) in the directory where the makefile is placed.
# AmigoMakefile
from cpackage import CPackage
def init(platform, params):
global package
package = CPackage('./', CPackage.STATIC_LIB, 'Test')
def build(platform, params):
package.build(platform)
def clean(platform, params):
package.clean(platform)
There are two actions supported in this example: build, and clean
Another more complex multi-platform example with libpng as a dependency and support for the --all flag:
from cpackage import CPackage
from ios_platform import IOSPlatform
from x86_platform import X86Platform
from android_platform import AndroidPlatform
import packages
def configure(params):
pass
def init(platform, params):
global package
installdir = "../external/install/" + platform.unique_name() + "/"
png = packages.Png("1.2.53", params.rootdir)
png.set_install_dir(platform, installdir)
lib_type = CPackage.SHARED_LIB
if isinstance(platform, IOSPlatform):
lib_type = CPackage.STATIC_LIB
package = CPackage('./', lib_type, 'TestPackage')
package.set_deps([png])
def build(platform, params):
package.should_build_deps(params.all)
package.build(platform)
def clean(platform, params):
package.clean(platform, params.all)
from external_cpackage import ExternalCPackage
class LibPNG(ExternalCPackage):
def __init__(self, version, rootdir):
super(LibPNG, self).__init__(version, rootdir)
self.set_zip_name("libpng-" + version + ".tar.gz")
self.set_url("ftp://ftp.simplesystems.org/" +
"pub/libpng/png/src/libpng12/" +
self.zip_name())
The following would the need to be added to the makefile:
png = LibPNG("1.2.53", params.rootdir)
png.set_install_dir(platform, package.install_dir(platform))
package.set_deps([png])
By default all depencies are always built. To use the --all flag the following line needs to be added:
package.should_build_deps(params.all)