How image installs work [was Re: The image question]

Jordan K. Hubbard jkh at
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.

- Jordan

-------------- next part --------------
An HTML attachment was scrubbed...

More information about the macports-users mailing list