How image installs work [was Re: The image question]
Jordan K. Hubbard
jkh at brierdr.com
Thu Mar 8 20:13:50 PST 2007
On Mar 8, 2007, at 4:21 PM, Yves de Champlain wrote:
> Sorry, but I really have a hard time following you here and reading
> this leaves me with a deep feeling of deeply missing the whole point.
> I understand that the current image implementation is a step in
> walk to something else that will someday be "the real thing".
> Like, for example, say "port activate foo" would trigger a
> mechanism to activate the right dependencies and deactivate
> conflicting ones ?
> Of course, I could say that it could also be done with tarballs
> instead of hard links and you could say that I really missed the
> whole point. But anyway, my original question was "can someone
> explain ?" rather than "can we dump this crap ?".
OK, so, let me see if I can explain the basics of "image mode".
First, as I think it's fairly clear, image mode basically says that
when a port installs itself, it does not install to its
"canonical" (or "activated") location, it installs to a location
where it can be unique as a portname/portversion tuple. That is to
say that if you install libjpeg, it doesn't actually install to /opt/
local/lib/libjpeg.dylib, /opt/local/include/jpeg.h, and so on, it
installs those bits instead under /opt/local/var/db/dports/software/
jpeg/6b_1/opt/local/. That means several things. One, let's say
you have an alternate jpeg library, one optimized for very specific
scenarios, that claims the same include and dylib files because it
was designed as a drop-in replacement for its popular libjpeg
cousin. Let's also say you have some non-macports aware software
which simply links with whichever dylib is in /opt/local/lib and uses
it. With image mode, you could trivially "install" both but only
activate one or the other as needed, perhaps flipping back and forth
to see which jpeg library was truly the most usable. With
traditional software installs, you would have to go through the much
more labor-intensive process of actually installing and de-installing
the different versions of libjpeg in order to swap them (and you'd
need to keep the original software builds or packages around for the
re-installs). With activate/deactivate, it just needs to make some
links and things just work - no need to keep the original packages,
no need to sweat the details of uninstalling. There are similar
scenarios with postfix and sendmail, where each claims some of the
same files (like /opt/local/bin/sendmail, which is "real sendmail" in
one case and a look-alike wrapper in the other) and the two cannot co-
exist. With image mode, you can flip back and forth if you need to
without having to rip either one completely out of your system. That
is what Linux does with their /etc/alternatives mechanism, which is
why I raised that example earlier.
That is all fairly simplistic, however, and one might justifiably
argue that having activate/deactivate as a discrete step from install/
uninstall is convenient but it doesn't fundamentally address any
problems you couldn't solve some other way. The real value of image
mode, and where we still need to "finish the job", is in allowing the
possibility of non-fragile dependencies. Software, particularly
open source software, breaks the API/ABI contract with other software
that depends on it all the time. As long as those deps are hard-
wired to the canonical installation location for that software, you
don't have a lot of options. Let's use libjpeg as a (less good)
example again. Say I have an important piece of software which
depends on libjpeg, and at the time I build that software libjpeg is
at version 6b.1, so now I have a dependency on /opt/local/lib/libjpeg.
62.dylib. A year later, libjpeg revs to version 6c.1 and, in order
to achieve some really important goals, need to break its API
contract with older software. So now I have /opt/local/lib/libjpeg.
63.dylib, which is fine since dylibs do have versioning, but I can't
actually install that new libjpeg port without uninstalling the old
one because there are other non-versioned files in that port, like /
opt/local/include/jpeg.h and the compat symlink /opt/local/lib/
libjpeg.dylib. Since the software that depends on the older version
is important to me, too important to throw away, I'm forced to rename
these files in the new port if I want them to co-exist with the old
one, and that leads to several problems. One, software which is
actually not affected by the API changes (let's say they didn't
change *everything*) has to be modified to use the new libjpeg
because you've renamed /opt/local/include/jpeg.h to something else.
Two, I've now obfuscated the new jpeg whereas the old and now
obsolete version is the one with the filenames that "make sense".
And none of that is even the hardest part. There are tools which
CAN'T be versioned the same way dylibs can (say, bison makes an
incompatible change or tclsh gets versioned) and there's literally no
good way to deal with the scenario above if you run into it across
upgrades. It's not just a matter of crufting things up, it's also
running into "you can't get there from here - some of your software
has to go!"
With image mode, all that can change. You NEVER have port A depend
on port B (version n)'s "activated" location, you have it depend
directly on the image location (/opt/local/var/db/dports/software/
$portname-B/$portversion-B/...) and things continue to work no matter
how many versions of port B you have lying around. It also decouples
the dependency from whatever the user may choose to have activated
for their own convenience - the user no longer has to worry about/
deal with weird spontaneous breakage just because they wanted to
speculatively install something that looked cool.
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the macports-users