Android Build & General Arch Discussion

Hey!

I’ve been playing around with compiling a version of graphviz for android, mostly as use as a layout engine by using it as a library. This project is entirely for fun (at the moment). I have gotten the core & a small selection of plugins (dot layout and most of the text-based renderers) built using the NDK. There are some small hacks to bundle the layout plugins to make up for the fact that I don’t know how to handle dynamic plugin loading (yet).

The docs say that graphviz can be used as a library, but based on the code, it seems like this use case is secondary to using it as a command line utility. Is this understanding correct? Has there been talk of creating a “library only” build of graphviz?

The current build size is 3.8MB using Oz and around 4MB with O2, which isn’t terrible, but the play store has limits for apk size that make it a good idea to make libraries as small as possible. There are two things that I have identified as both increasing the size of the binary.

  1. The command line interface is tightly coupled with the execution engine. There’s a bunch of text associated with the interface that could be stripped out in a pure library implementation. In addition, the command line interface directly relies on the implementation details of one of the layout engines, which is a bit odd.

  2. While the layout engine system is plugin based, the implementation of the most common layouts (and I think, a bunch of renderer impl details) are embedded in the core binary. This seems kind of weird to me.

I’m trying to understand these design choices better so I don’t miss anything when I go hacking things up, and also because I enjoy design discussions :slight_smile:

I’m also interested in whether there’s interest in supporting an android build “for real”. Right now I have it set up in an android project that builds via gradle and has some (probably terrible) CMake file modifications, both of which make it unsuitable for integrating into your build system directly. There’s definitely a way to invoke the NDK toolchain to build Cmake stuff, but I am no more an expert in building C/C++ as I am in C itself. I’m happy to learn, but I’m not sure it’s worth it for me unless someone else wants it. I also might need a bit of help making sure any solution I come up with isn’t terrible.

Anyway, thanks anyone who replies. I know it’s kinda rambly and I appreciate the patience.

The arm64 build of the dot command in macOS is 35k. I’m not sure if I’m looking at the right things but most of the layout and rendering plugins seem reasonable in size, under 1MB. The largest are neato. I didn’t investigate but guessing it pulls in other numerical libraries.

-rwxr-xr-x@ 1 north  staff  1434032 May 30 08:57 libgvplugin_neato_layout.6.dylib
-rw-r--r--@ 1 north  staff  5833912 May 21 13:33 libgvplugin_neato_layout.a

Both Graphviz’ Autotools and CMake build systems attempt to be pretty thoroughly agnostic to the target platform. In both, you should be able to run a compilation that only builds libraries. If there’s something that doesn’t compile when targeting Android, please let us know. Though we only have CI for Linux, macOS, and Windows, we take patches for pretty much any other platform.

@scnorth
I feel very silly now. It turns out the the aar has Multiple copies of the native binary AND the android jvm code, which explains why it’s so big.

I think the dot plugin size can be fixed by me learning more about how to author better builds. I have a hack that I think is causing it to grab a bunch of stuff it doesn’t need.

I’m still confused by the dot and neato layout plugins though. They just seems to add a record to a layout that is entirely dependent on the implementation provided by “dotgen” and “neatogen”. Those, in turn, require significant dependencies be added to make them work. That seems kind of weird to me because it means you’re forced to compile a bunch of stuff you don’t need if your never going to use those plugins. What am I missing?

@smattr

“. In both, you should be able to run a compilation that only builds libraries. If there’s something that doesn’t compile when targeting Android, please let us know. Though we only have CI for Linux, macOS, and Windows, we take patches for pretty much any other platform.” Like I said, I did get it to build, though it was not as easy as just following the build instructions provided.

In terms of “building only libraries”, I’m not actually sure how to set that up correctly given the build instructions provided on the site on either linux (ubuntu WSL) or windows through VS, but I also didn’t try for too long before deciding to just dump what I needed into the android studio project and hack the CMake files to work from there.

In general I can say that the number of build and build configuration options is pretty overwhelming, and having the auto-config doesn’t (seem to) help when you’re targeting a platform you’re not currently running on. It is, however, complete and “eventually comprehensible”, even to a newcomer.

I will work on trying to get an android command line build to work next, Thanks!

Yeah, the website instructions assume you’re trying to build everything. Now that I try building selectively with Autotools, I can’t figure out how to do it, so perhaps I’m mistaken there. With CMake you should be able to selectively build targets fine though, e.g. cmake … --target xdot.

I don’t know much about Visual Studio, sorry.

Yes, partly due to the array of environments Graphviz has supported over the years. For your use case, you probably want to set almost every option off.

Right, you’re doing cross-compilation. This should work in the Autotools or CMake build systems. I don’t know about MS Build and I suspect not.

A meta question: what are you trying to achieve? If you disable all the layout plugins including the base ones, you’ve effectively thwarted Graphviz’ ability to do anything.

Thank you for your reply! I very much appreciate it. I don’t have much else to say about the build advice other than “thank you”. I think MS build might have cross compile support, but I also suspect using it would be more difficult than cmake anyway. Also MSBuild definitely isn’t supported by android studio, so I’ll probably stick to CMake. :stuck_out_tongue:

A meta question: what are you trying to achieve? If you disable all the layout plugins including the base ones, you’ve effectively thwarted Graphviz’ ability to do anything.

I think the practical answer to that is “create the smallest possible footprint”. If I know that I will never use the xdot layout, building it into the binary seems wasteful. I think the big theoretical buzzword would be “decoupling”.

Theoretically (and I have no idea if this is actually possible), it would be great to be able to include plugins as independent project dependencies via gradle/maven (or whatever package manager you want), and then have the core be a very tiny library who’s job is only to handle dispatch to the plugins. If a developer wants to rely entirely on a plugin set they’ve developed, they shouldn’t need to include the “base” ones.

I think that my expectation for a plugin system is that the plugins contain the business logic / implementation details rather than the central executable. For instance, I expected the actual logic of the xdot layout algorithm to be in the plugin, not just a hook back into the core graphviz executable.

However, I also think I may just not quite understand the structure. The “core” providing facilities that plugins use is 100% expected. I think I might be confused between the “xdot engine” and the “xdot layout plugin”. If multiple plugins need the engine to produce a baseline layout that is then further customized by the plugin, that seems valid (though it calls into question whether the engines themselves should be plugins of some sort).

Ah I think the missing clue here is how expansive the plugin architecture of Graphviz is. A couple of non-optional parts (dot_layout, neato_layout) are themselves implemented as plugins. This leads to some nice uniformity. But if indeed you succeed in disabling them, Graphviz will no longer be capable of anything non-trivial.