A while back, I started a project to wrap the ImageMagick MagickWand API in a layer of rustic (tm) abstractions. By a while, I mean way back in June of 2013. I made a few commits to the project, then got distracted by my career (as tends to happen) and the project languished. It’s now been brought to my attention that the library no longer compiles and the binding tool that I used won’t even generate the base bindings any more!
In this post, I will provide some notes on how to setup a rust installation and generate bindings for C libraries. Hopefully this will help me be more responsive to Wand of Rust requests in the future!
Step One, Enter the World of Rust
The first step to getting things rolling is to get the most recent version of the rust language built and installed on your system. These instructions are for Linux, though they should work for other UNIX-like operating systems. If you are using windows as your development platform, go away.
The official Rust site has documentation on the process of getting started, which I will somewhat parrot here.
- Head over to the rust git repository and clone the master branch.
- Make sure your system has the following prerequisites:
- g++ 4.4 or clang++ 3.x (on aptitude as clang)
- python 2.6 or later (apt package python2.7)
- perl 5.0 or later (probably already on your system)
- gnu make 3.81 or later (likely already installed - see build-essential package)
- curl (come on… I know you have curl installed)
- Once the rust repository has finished synchronizing, cd into it and do the usual dance:
- ./configure (this can take several minutes)
- make && make install (this can easily exceed an hour)
Hopefully everything went smoothly with the build steps above. This process can take some time, as the compiler and standard library are non-trivial pieces of software.
After the installation finishes, you should now have a
rustpkg command on your path.
Step Two, Fetch the ImageMagick library
Since we are working with bleeding edge everything, why stop at the wrapped library? :-)
The version that I found already installed on my system was 6.6.9-7, already nearly 18 months old.
The latest version of ImageMagick at the time of this writing is 6.8.8-1, so head over to the build from source page and follow along with the directions. This component built easily for me; hopefully you have an equally pleasant experience. Be sure to take note of the ldconfig step, as you may have an older version of the libraries already present in the library cache.
Verify that everything installed properly by compiling the example program listed on the MagickWand C API page, listed here for convenience:
Please note that the build instructions on the ImageMagick website did not work for me.
The instructions listed there used
pkg-config to generate the appropriate c flags, but
this left undefined references to the MagickWand function calls. Instead, you will want
to build the test program above with the following:
If the program successfully builds and prints usage without a coredump, things are good!
Step Three, Fetch the rust-bindgen Repository
Head over to the rust-bindgen github project page and clone the repository.
Unfortunately, the version of libclang that is packaged in the ubuntu repositories is too old to build rust-bindgen against. You will know this problem if attempting to build yields this error.
The outdated version of Clang means that we must venture into frightful territory…
Step Three and a Half, Build libclang From Source
God help us…
To begin with, head on over to the official Clang Getting Started Guide. Follow these directions precisely. I chose to install the optional Clang Tools repository as well.
I also hit this problem when running
configure on the llvm project:
For some reason, the configure script didn’t know to look in
/usr/bin for g++.
Anyway, to fix this problem, just explicitly set the C++ compiler:
With this in place, things should configure correctly. Continue following the
directions from the Getting Started Guide. While the instructions don’t mention it
explicitly, be sure to
make install after the build finishes. This installs static
libraries in a system-wide location (
/usr/local/lib/libclang*.a), but does not
place the shared libraries anywhere. There is probably a make command or a configure
flag to fix this, but I chose to just copy the .so from the build directory:
Note that this is probably poor practice.
Now that we have a modern version of libclang.so on our system, we should be able to build rust-bindgen without incident!
Step Four, Generate the Bindings!
We’ve come a long way dearest reader, and now the time for celebration is upon us! Let’s generate the base bindings for the MagickWand library.
First, head over to wherever you placed the bindgen binary generated above. The bindgen utility takes a number of flags, nearly all of which we will be using.
For the impatient, here’s the final command we use:
Now for the curious, a bit of explanation as to what all this means. The first thing we use is
MagickWand-config program to generate the apropriate library commands as well as the
include paths. This gets around a platform portability issue in which ImageMagick libraries
have different naming conventions. See this issue
for more details on that. Next, we specifically tell clang where its libraries are. By default,
clang knows to search in the appropriate location, but since we are using
to specify alternative include paths we need to provide it ourselves. You’ll want to update
this if your clang installation is non-standard.
Finally, we specify the header file we would like to generate the bindings for (the MagickWand API in this case) and indicate that bitfields are allowed.
With that, the bindings have been generated!