Re: Resource framework, relocatability (was Re: Glib: a Win32 discussion)

On Apr 17, 2011, at 1:33 AM, Damjan Jovanovic wrote:

On Fri, Apr 15, 2011 at 7:45 PM, Alexander Larsson <alexl redhat com> wrote:
On Fri, 2011-04-15 at 08:49 -0700, Kevin Fox wrote:
On Fri, 2011-04-15 at 06:01 -0700, Alexander Larsson wrote:
On Fri, 2011-04-15 at 14:18 +0200, Damjan Jovanovic wrote:

Of course, some files are inherently made to be external, read by
applications. Such files are hard to relocate, like application
desktop files, icon themes, widget themes, plugins, custom mimetype
descriptions, dbus service files. I don't really know what to do
with these.

A library can discover its current path by calling dladdr() on *nix
and MacOS X, and GetModulePath() on Windows. The library then loads
resources relative to that path.

Yes, thats is doable on many OSes, but its still kinda ugly, as it
implies that the relative paths to the files are kept, and thus implies
that things are stored in typical unix style hierarchies, etc. It is
much cleaner to just have a single file.

It doesn't solve the inherently hard things listed above though, because
the problem for them is that *other* things than the library itself
loads these files.

Usually the tool used to solve this problem though is a file system.

An appdir like structure is a good compromise between other things
needing to easily access the data and having all the stuff in one
location that can be easily copied and moved around.

Another option might be to simply tar (but not [bg]zip) up the library
and related files and change the dynamic linker to mmap the correct
subsection of the file instead of the whole thing.

An appdir doesn't solve the issue here. Its not that its hard to load
the file from the relocated file that makes it problematic. Its the fact
that the "other" app doesn't even know about the existance of the file.

Now that I've read up on it, MacOS appdirs do solve that issue, as
follows. Each appdir has a file called info.plist where you list all
your resources. Most/all of the filesystem is monitored for changes by
a service called Launch Services. When it finds a new appdir forming
or changing in the filesystem, it (re)loads its info.plist, and
updates its list of all resources in the system and where each is.
When an application wants to find some resource, it does an RPC to
Launch Services, and gets told where those resources are.

For instance, let us take a desktop file as an example. Applications
typically install their desktop files in /usr/share/applications. That
way "other" applications like the panel, the open with dialog, etc will
find it, because they all look in that directory. There are some env
vars you can set globally to manually make other apps look in a some
specific other directory, but this is quite limited and doesn't work for
random relocation of apps.

The panel keeps track of desktop file unique IDs for desktop files
that are on it and queries Launch Services for the actual location at
launch time. Double-clicking on eg. a PDF file would query Launch
Services for applications that can open the PDF mime type.

The same thing happens for the other types of files i mentioned above.
dbus looks only for service files in /usr/share/dbus-1/services, gtk
looks for themes in /usr/lib64/gtk-3.0/3.0.0/theming-engines, etc, etc.
So, anything that has a file of this type is "hard" to relocate.

DBus would query Launch Services for all applications whose info.plist
states they want to launch on session startup. Gtk would query Launch
Services for all appdirs that export a theme.

Also, apps that consume such files are also hard to relocate. Take
nautilus for instance, it looks for extensions
in /usr/lib64/nautilus/extensions-3.0/, but if you relocate it, how does
extensions know where to install extensions?

Nautilus would query Launch Services for... you get the idea :-).

That link I posted earlier suggested that appdirs can be implemented
backward-compatibly on top of the current Freedesktop standards, by
using inotify/UnionFS/FUSE to union-mount special files anywhere in
the system into the current special locations (eg. union-mount all
.desktop files in the system on /usr/share/applications, all DBus
service files on /usr/share/dbus-1/services, etc.).

Well, not quite. LaunchServices handles starting programs and mapping file types to applications. . There is a way to export functionality to other applications called "Services" [1], but it's separate from LaunchServices. Info.plist keys are documented in [2].

None of which has anything to do with either the dynamic linker or loadable modules.  Dynamically linked libraries are generally found using an rpath in OSX; that rpath can be set relative to the executable (or, strating in Snow Leopard, relative to another shared library) using a special macro. There are a few ways to locate loadable modules. The simplest is to include them in the bundle ("application directory") and ask the OS for the path (CFBundle and NSBuncle provide interfaces for querying the bundle in C and Objective-C respectively). There is a plugin registration facility [3] that can be used for loadable modules, but is intended for third-party plugins of the sort common for web browsers. There's also some environment variables (which can be set with an Info.plist key or with a launcher script), LD_LIBRARY_PATH, DYLD_LIBRARY_PATH, and DYLD_FALLBACK_LIBRARY_PATH which control both the loading of dynamic libraries and dlopen.

Dbus works just fine on OSX. There's nothing wrong with the "well known place" approach for system services; Apple's own services use it extensively. There's no real need for dbus, of course; OSX has its own, better, notification, configuration management, and resource location facilities. I hope to find time this summer to write gdbus and gsettings backends that use  them.

That said, Damjan's basic point that application directories work very well in OSX is absolutely correct. 

John Ralls

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]