matplotlib takes the goodness of the Matlab plotting API (and more!) and puts it in Python. It’s an astonishingly identical API. And now you want to compile it on Cygwin. You’ve scoured the Usenets. You’ve scoured your pots and pans. And it’s impossible. Or is it?
(This has been tested on matplotlib-0.98.5.2, February 21, 2009, on an absolutely up-to-date Cygwin. Expect to improvise more and more for later and later versions. Feel free to add any additional tips or questions to the comments section. This is the magic of webbogs.)
Well, it probably isn’t, since the matplotlib people can do it or otherwise it wouldn’t be in their setup.py. But things break, and manly administrators like us need to fix them.
Grabbing the source.
First, run easy_install, which will automatically find the right .tar.gz file from SourceForge. At that point, abort with Ctrl-C and copy and paste the URL. We won’t be using easyinstall because we’ll be fidgeting around in the building files.
Now choose a directory. wget and untar the file into this directory.
Normally, we’d run
python setup.py install and go grab a cheesecake. Not
so fast. You’ll get errors aplenty.
As proof, run
python setup.py install. It will raise an IndexError in
setupext.py in trying to read from your /usr/lib/tkConfig.sh in the
parse_tcl_config. It seems to expect a different format
than what’s actually present. Fortunately, the
function is Good Enough. All we have to do is force the function to
guess_tcl_config code path:
To swallow this exception, add “IndexError” to the comma-delimited
list beneath that try-block. In other words, turn
(ConfigParser.NoSectionError, ConfigParser.NoOptionError): into
except (ConfigParser.NoSectionError, ConfigParser.NoOptionError,
IndexError):. Exception swallowed!
Now run python setup.py install again like you did before. We’ll need to make sure we have all the dependencies, so let’s see what the library sniffer picks up. Install anything, via Cygwin, that it can’t find.
Two notable dependencies it won’t pick up: libX11-devel and pkg-config. Make sure you have these before running the library sniffer because you’ll need to save up your insanity for this build. Keep running setup.py and keep installing until you resolve all the dependencies.
An initial failure in building C extensions.
Here’s the crux of the problem with setup.py: You’ll get weird fork resource errors when setup.py tries to compile the C/C++ extensions. Happily enough, Pete Harris noticed that this doesn’t happen if you manually run gcc/g++. A mystery, one that can’t be solved with Cygwin’s rebase, and one that we don’t have time for.
A simple solution is to simply mimic setup.py’s calls to gcc from our own prompt. setup.py (distutils, to be exact) is smart enough to not recompile when it’s not necessary, which makes this fast and easy to implement. The only tricky part is getting setup.py to spit out all its gcc forks, not just the one it dies on.
To review: How do we get setup.py to tell us all the gcc commands it’s going to run, without actually running them?
Squeezing a build script out of distutils.
For that, we turn to
python setup.py --dry-run build > a.txt or,
python setup.py -n build > a.txt. We’re piping this to
a.txt because there’s a lot of junk to remove. It should look like
this. Once setup.py finishes, open a.txt in your favorite text
editor, which we’ll call “Emacs”, and delete everything around the
Within this chunk, there are messages to the user such as “building such-and-such” or “creating such-and-such”. Delete those. And slap a sh shebang at the top to get a file like this, which you can save to matplotlib-clean-build.sh if you so choose. Now you have a build script.
At this point, you’re eager to run the script and see all that glorious gcc output, a crimson-violet rainbow of warnings and C++ templates and library paths. But we have more to do.
Invalid file paths.
For some reason, there are paths to old files in this output, files
that have since then been renamed. In particular: src/backend_agg.cpp,
src/image.cpp, and src/path.cpp. These do not exist. Find the
occurrence of each and add an underscore the file name. For example,
it should be
src/path.cpp. Warning: stick to
.cpp files only. The .o files, which are intermediate output filenames
that nobody cares about, are fine.
On the very last line, when g++ tries to build _tkagg.dll, change -ltk8.4 to -ltk84. Similarly, change -ltcl8.4 to -ltcl84. Cygwin maintainers and matplotlib developers have different ideas about how these two libraries should be named in your /usr/lib.
To recap: distutils thinks there should be files where there are none because they were renamed. We are here to fix it.
Now run the build script with ./my-build.sh and then run python setup.py install, which will copy the Python files and your built extension—that you lovingly built by hand! it’s your children!—to all the right places.
Most likely, though, you’ll encounter other errors that I never ran into. Google and smart guessing are your friends.
The worst enemies of build errors are: reading, Googling, logical reasoning, acking or grepping, a good text editor, lathering, rinsing, and repeating.