Closed probonopd closed 5 years ago
Interestingly, this is contained in
sudo apt-get install libglib2.0-dev
Why on earth would we need a -dev
package to run appimaged
?
Interestingly, a self-built libappimage does not show a dependency on libgobject-2.0.so
:
me@host:~/libappimage/build$ ldd ./src/libappimage/libappimage.so
linux-vdso.so.1 (0x00007ffeb23a7000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f14cc07b000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f14cbe77000)
libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007f14cbc5a000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f14cb8cc000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f14cb6b4000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f14cb2c3000)
/lib64/ld-linux-x86-64.so.2 (0x00007f14cc618000)
However, inspecting it with strings does make it a likely candidate for having introduced this dependency "secretly":
me@host:~/libappimage/build$ strings ./src/libappimage/libappimage.so | grep goblibgobject-2.0.so
libgobject-2.0.so.0
libgobject-2.0.so.0.0
In fact, there are even more "hidden dependencies":
me@host:~/libappimage/build$ strings ./src/libappimage/libappimage.so | grep -e "^lib.*so.*"
libpthread.so.0
libdl.so.2
libz.so.1
libstdc++.so.6
libgcc_s.so.1
libc.so.6
libappimage.so.1.0
librsvg-2.so.2 # What about this? We cannot assume it to be everywhere
libcairo.so.2 # What about this? We cannot assume it to be everywhere
libgobject-2.0.so # What about this? We cannot assume it to be everywhere
libgobject-2.0.so.0 # What about this? We cannot assume it to be everywhere
The same is true for appimaged
which uses libappimage
internally:
me@host:~$ strings squashfs-root/usr/bin/appimaged | grep -e "^lib.*so.*"
(...)
libstdc++.so.6
libgcc_s.so.1
(...)
librsvg-2.so.2 # What about this? We cannot assume it to be everywhere
libcairo.so.2 # What about this? We cannot assume it to be everywhere
libgobject-2.0.so # What about this? We cannot assume it to be everywhere
In fact, it's even way worse than that. If we make the "hidden dependencies" to real dependencies, and then check with ldd
, we see that libappimage
and hence appimaged
now depend on a whole lot of stuff indirectly:
# "Unhide" the "hidden dependencies"
me@host:~/libappimage/build$ /isodevice/Applications/patchelf --add-needed librsvg-2.so.2 --add-needed libcairo.so.2 --add-needed libgobject-2.0.so ./src/libappimage/libappimage.so
# Check the real dependencies
me@host:~/libappimage/build$ ldd ./src/libappimage/libappimage.so
linux-vdso.so.1 (0x00007ffe98b28000)
libcairo.so.2 => /usr/lib/x86_64-linux-gnu/libcairo.so.2 (0x00007f348923c000)
libgobject-2.0.so => /usr/lib/x86_64-linux-gnu/libgobject-2.0.so (0x00007f3488fe8000)
librsvg-2.so.2 => /usr/lib/x86_64-linux-gnu/librsvg-2.so.2 (0x00007f3488db0000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f3488b91000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f348898d000)
libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007f3488770000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f34883e2000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f34881ca000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f3487dd9000)
libpixman-1.so.0 => /usr/lib/x86_64-linux-gnu/libpixman-1.so.0 (0x00007f3487b34000)
libfontconfig.so.1 => /usr/lib/x86_64-linux-gnu/libfontconfig.so.1 (0x00007f34878ef000)
libfreetype.so.6 => /usr/lib/x86_64-linux-gnu/libfreetype.so.6 (0x00007f348763b000)
libpng16.so.16 => /usr/lib/x86_64-linux-gnu/libpng16.so.16 (0x00007f3487409000)
libxcb-shm.so.0 => /usr/lib/x86_64-linux-gnu/libxcb-shm.so.0 (0x00007f3487206000)
libxcb.so.1 => /usr/lib/x86_64-linux-gnu/libxcb.so.1 (0x00007f3486fde000)
libxcb-render.so.0 => /usr/lib/x86_64-linux-gnu/libxcb-render.so.0 (0x00007f3486dd1000)
libXrender.so.1 => /usr/lib/x86_64-linux-gnu/libXrender.so.1 (0x00007f3486bc7000)
libX11.so.6 => /usr/lib/x86_64-linux-gnu/libX11.so.6 (0x00007f348688e000)
libXext.so.6 => /usr/lib/x86_64-linux-gnu/libXext.so.6 (0x00007f348667c000)
librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f3486474000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f34860d6000)
libglib-2.0.so.0 => /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0 (0x00007f3485dc0000)
libffi.so.6 => /usr/lib/x86_64-linux-gnu/libffi.so.6 (0x00007f3485bb8000)
libgdk_pixbuf-2.0.so.0 => /usr/lib/x86_64-linux-gnu/libgdk_pixbuf-2.0.so.0 (0x00007f3485994000)
libgio-2.0.so.0 => /usr/lib/x86_64-linux-gnu/libgio-2.0.so.0 (0x00007f34855f6000)
libpangocairo-1.0.so.0 => /usr/lib/x86_64-linux-gnu/libpangocairo-1.0.so.0 (0x00007f34853e9000)
libpangoft2-1.0.so.0 => /usr/lib/x86_64-linux-gnu/libpangoft2-1.0.so.0 (0x00007f34851d3000)
libpango-1.0.so.0 => /usr/lib/x86_64-linux-gnu/libpango-1.0.so.0 (0x00007f3484f86000)
libcroco-0.6.so.3 => /usr/lib/x86_64-linux-gnu/libcroco-0.6.so.3 (0x00007f3484d4b000)
libxml2.so.2 => /usr/lib/x86_64-linux-gnu/libxml2.so.2 (0x00007f348498a000)
/lib64/ld-linux-x86-64.so.2 (0x00007f3489998000)
libexpat.so.1 => /lib/x86_64-linux-gnu/libexpat.so.1 (0x00007f3484758000)
libXau.so.6 => /usr/lib/x86_64-linux-gnu/libXau.so.6 (0x00007f3484554000)
libXdmcp.so.6 => /usr/lib/x86_64-linux-gnu/libXdmcp.so.6 (0x00007f348434e000)
libpcre.so.3 => /lib/x86_64-linux-gnu/libpcre.so.3 (0x00007f34840dc000)
libgmodule-2.0.so.0 => /usr/lib/x86_64-linux-gnu/libgmodule-2.0.so.0 (0x00007f3483ed8000)
libselinux.so.1 => /lib/x86_64-linux-gnu/libselinux.so.1 (0x00007f3483cb0000)
libresolv.so.2 => /lib/x86_64-linux-gnu/libresolv.so.2 (0x00007f3483a95000)
libmount.so.1 => /lib/x86_64-linux-gnu/libmount.so.1 (0x00007f3483841000)
libharfbuzz.so.0 => /usr/lib/x86_64-linux-gnu/libharfbuzz.so.0 (0x00007f34835a3000)
libthai.so.0 => /usr/lib/x86_64-linux-gnu/libthai.so.0 (0x00007f348339a000)
libicuuc.so.60 => /usr/lib/x86_64-linux-gnu/libicuuc.so.60 (0x00007f3482fe3000)
liblzma.so.5 => /lib/x86_64-linux-gnu/liblzma.so.5 (0x00007f3482dbd000)
libbsd.so.0 => /lib/x86_64-linux-gnu/libbsd.so.0 (0x00007f3482ba8000)
libblkid.so.1 => /lib/x86_64-linux-gnu/libblkid.so.1 (0x00007f348295b000)
libgraphite2.so.3 => /usr/lib/x86_64-linux-gnu/libgraphite2.so.3 (0x00007f348272e000)
libdatrie.so.1 => /usr/lib/x86_64-linux-gnu/libdatrie.so.1 (0x00007f3482527000)
libicudata.so.60 => /usr/lib/x86_64-linux-gnu/libicudata.so.60 (0x00007f348097e000)
libuuid.so.1 => /lib/x86_64-linux-gnu/libuuid.so.1 (0x00007f3480777000)
At the very least, the dependencies must be made explicit (so that they show up in ldd
) so that tools like linuxdeploy
and linuxdeployqt
will have a chance to bundle the dependencies (e.g., here). We will have to see how large appimaged
becomes then.
https://artifacts.assassinate-you.net/artifactory/appimaged/travis-112/appimaged-x86_64.AppImage has 2.9 MB as opposed to 0.7 MB before. Do we think this is still acceptable? What functionality do we gain that was previously unavailable?
Bundling this stuff is painful: https://github.com/AppImage/appimaged/pull/78. g_type_check_instance_is_fundamentally_a
is caused by bundling usr/lib/libgobject-2.0.so
needs yet another workaroud and more stuff to be bundled.
Now we are at 3.8 MB.
So, can we link libgio-2.0.a
statically to get around this?
https://github.com/AppImage/libappimage/blob/master/src/libappimage/utils/IconHandle.cpp
This is where those libraries are used. As you could imagine they are for creating thumbnails.
Can you make them properly linked instead of dlopen()
ed?
dlopen()
should only be used for optional features (like libnotify) where we can degrade gracefully in case the library is not there.
As you could imagine they are for creating thumbnails.
Can you elaborate a bit? Which functionality do those libs do that cannot be achieved by other means?
Basically all the image manipulation done in libappimage
.
Do we really need to manipulate images other than moving and copying them around? E.g., are we using those libraries to write the metadata required by the XDG Thumbnailer standard? Could we use other tools that can be statically linked to do the same?
Do we really need to manipulate images other than moving and copying them around?
The thumbnails spec says:
image format for thumbnails is the PNG format, regardless in which format the original file was saved
So yes if we want to do thumbnails generation right we must do image manipulation. By example to transform svg icons into png.
Makes sense, but I think we could move the image conversion to AppImage generation time (=appimagetool
), and ensure that .DirIcon
is compliant to the thumbnails spec?
We could possibly even embed the needed metadata with some dummy padding which we could then edit using fast string manipulation at integration time.
Example: appimagetool writes .DirIcon
as a thumbnailer-compliant PNG with e.g., Thumb::URI=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx(...)
which we could then replace when the AppImage is being integrated.
appimaged
performance?What do you think? Of course we would need to update the AppImageSpec accordingly.
I think we could move the image conversion to AppImage generation time
That could be done and will fix the issue for the newly created AppImage but what about the old ones?
This could help performance but the produced files we will be larger.
Actually I like the idea of doing this at build time. And yes we should make a room in the AppDir for thumbnails. The AppIcon may not be always a good candidate i.e. when it's an svg file.
It's .DirIcon
, and that's what's specified by ROX Filer. All you can do is put a proper icon there, but I wouldn't bother investing too much work into this.
Furthermore, I am pretty sure the thumbnail standards don't have "multiple files" features or so. And that's not needed either if you ask me.
You can IMO render an SVG if needed to there at build time, for instance.
The AppIcon may not be always a good candidate i.e. when it's an svg file.
Do you mean the .DirIcon
? Then let's define that people need to use a thumbnailer-suitable one.
what about the old ones?
Do whatever appimaged
did in pre-libappimage days (=nothing?).
We will remove all the image manipulation feature and the libs loaded using dl.
.DirIcon
will be used as thumbnail if it's a png
file. Otherwise I purpose to use a placeholder icon.
appimagetool
should receive this feature.
:+1: if you agreed
I agree, once
.DirIcon
(one should always give developers reasonable time before one changes something)appimagetool
has gained that functionalityIn the meantime, we can live with the status quo (now that we have a workaround for appimaged
).
What about the Thumb::URI=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx(...)
stuff? Do we need to mandate those placeholders too?
Part of the standard, so yes. We noticed quite late. I think that's also supposed to make things work on KDE, isn't it?
Yes.
Then we need to define what exact placeholders with what exact length we require in the .DirIcon
.
There is a PR on the AppImageSpec to make the .DirIcon
follow the Thumbnails Format Specification.
appimagetool
issue created https://github.com/AppImage/AppImageKit/issues/958
The current implementation is actually better than the older (which actually does nothing). And uses the 'do nothing' feature as fallback. So until the appimagetool
receive such feature and a while after have no need to touch the code.
As as side effect when we use Thumb::URI=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx(...)
and friends, we may bring back Thumbnail copying into runtime.c
because it is going to be much simpler to implement properly then (using only copying and string manipulation).
I've been working on this, as we thought building and linking libcairo
and and librsvg
is possible. Also it's possible to do the same with libgobject
but linking this library statically is the mother of all chaos. glib
is required by a large amount of apps therefore they will be linking to it if in a single application you use to different versions of glib (one statically linked and other dynamically) a crash is certain. So, this is a NO-GO.
@probonopd would you please provide more information about the system where you are getting those errors. So I could try improving the dl opening process.
A far as I can see the solution to this is to move all image processing code to appimagetool and leave to libappimage
just the copy file and set thumbnail metadata features.
There is no reason to link libgobject
, it's not used directly AFAIK. It's just a dependency of rsvg.
The source of the error is libgobject
not being found.
ERROR: appimage_register_in_system : Unable to load libgobject-2.0.so.
Even if we link librsvg
statically libgobject
will be missing.
What needs it? Can't we get rid of what needs it?
There is no reason to link librsvg
statically.
Err, why not? Linking it and its dependencies statically, I mean.
librsvg
links to libgobject
. Get rid of libgobject
means losing thumbnails generation of svg .DirIcon
@probonopd
glib is required by a large amount of apps therefore they will be linking to it if in a single application if you use to different versions of glib (one statically linked and other dynamically) a crash is certain. So, this is a NO-GO.
Update: libcairo
also depends on libgobject
therefore we will not be able to perform any image manipulation.
Err, why not? Linking it and its dependencies statically, I mean.
It must be linked statically? Please tell me why. Seriously, it's not needed to link it statically. We can ship the .so
files.
Thumbnails generation and proper icons deployment (icons being deployed on the right folder according to their size) are features that didn't exists before libappimage-1.0.0
. Therefore my proposal is to be more silent on this kind of errors and use the old libappimage
behavior (just copy the file) as fallback.
As far as I can remember we do just copy the file if something goes wrong. But it may need a review. What do you think?
Not sure if we need a fallback, it's just more complexity... but I'd be okay with that, as long as I don't have to maintain that... There should be a warning though.
I think we should just dynamically link this and call it a day.
Dynamic linking is ok if we can make an AppImage bundle that does not run into issues like this one: https://github.com/AppImage/appimaged/issues/82
https://github.com/RazrFalcon/resvg is not an option? They write
librsvg is heavily tied to GNOME, which makes it painful to distribute outside the Linux ecosystem
;-)
Seems like a valid suggestion, the library looks good at a first glance. I'm pretty sure we had a look at it already, though, and there was a reason not to use it... But I don't remember. @azubieta please check whether switching to that library is an option.
resvg
also requires pango
. Optionally it could use Qt5 as back-end but it's the same situation
see: https://github.com/RazrFalcon/resvg/blob/master/BUILD.adoc#cairo-backend
Isn't pango about fonts which we don't need? Could it be disabled?
Only if we build it ourselves. And that doesn't eliminate the need for the GNOME libs, there's still gobject deps in cairo.
In any case, then we need to make a proper appimaged AppImage that bundles all dependencies in a way that makes the whole thing work; as a proof-point that build products using libappimage can be AppImage'ified properly.
Not a fan of the rendering quality, but I've checked ImageMagick (libmagick6) and it doesn't seem to depend on RSVG or other GNOME dependencies. Its SVG extra codec rather has a direct dependency on libxml2, so I guess they implement their own SVG parser. That's the only real alternative to RSVG I know that can render vector graphics properly to raster graphics.
> lddtree /usr/lib/x86_64-linux-gnu/ImageMagick-6.9.7/modules-Q16/coders/svg.so
svg.so => /usr/lib/x86_64-linux-gnu/ImageMagick-6.9.7/modules-Q16/coders/svg.so (interpreter => none)
libMagickCore-6.Q16.so.3 => /usr/lib/x86_64-linux-gnu/libMagickCore-6.Q16.so.3
liblcms2.so.2 => /usr/lib/x86_64-linux-gnu/liblcms2.so.2
liblqr-1.so.0 => /usr/lib/x86_64-linux-gnu/liblqr-1.so.0
libglib-2.0.so.0 => /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0
libpcre.so.3 => /lib/x86_64-linux-gnu/libpcre.so.3
libfftw3.so.3 => /usr/lib/x86_64-linux-gnu/libfftw3.so.3
libfontconfig.so.1 => /usr/lib/x86_64-linux-gnu/libfontconfig.so.1
libexpat.so.1 => /lib/x86_64-linux-gnu/libexpat.so.1
libfreetype.so.6 => /usr/lib/x86_64-linux-gnu/libfreetype.so.6
libpng16.so.16 => /usr/lib/x86_64-linux-gnu/libpng16.so.16
libXext.so.6 => /usr/lib/x86_64-linux-gnu/libXext.so.6
libX11.so.6 => /usr/lib/x86_64-linux-gnu/libX11.so.6
libxcb.so.1 => /usr/lib/x86_64-linux-gnu/libxcb.so.1
libXau.so.6 => /usr/lib/x86_64-linux-gnu/libXau.so.6
libXdmcp.so.6 => /usr/lib/x86_64-linux-gnu/libXdmcp.so.6
libbsd.so.0 => /lib/x86_64-linux-gnu/libbsd.so.0
librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2
ld-linux-x86-64.so.2 => /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
libbz2.so.1.0 => /lib/x86_64-linux-gnu/libbz2.so.1.0
libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1
libltdl.so.7 => /usr/lib/x86_64-linux-gnu/libltdl.so.7
libgomp.so.1 => /usr/lib/x86_64-linux-gnu/libgomp.so.1
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1
libxml2.so.2 => /usr/lib/x86_64-linux-gnu/libxml2.so.2
libicuuc.so.60 => /usr/lib/x86_64-linux-gnu/libicuuc.so.60
libicudata.so.60 => /usr/lib/x86_64-linux-gnu/libicudata.so.60
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6
liblzma.so.5 => /lib/x86_64-linux-gnu/liblzma.so.5
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6
Not sure how trivial it is to ship that library, though. It's a fair bit more complex than librsvg/libcairo, since it has this dynamic codec support thing. But, on the other hand, we don't have to build it, I guess; we can just ship it as it is.
It's definitely worth investigating shipping of libmagick, I guess with a plugin for linuxdeploy we could get proper results. I'd love to have RSVG as an optional dependency, though, since its SVG rendering quality is outstanding, I use it all the time through rsvg-convert
. I'd implement it as a "let's link to libmagick, then try to load RSVG dynamically; if it's there, let's use it, otherwise just use ImageMagick" or so.
We found at https://github.com/AppImage/appimaged/issues/82 that we can safely use libcairo
and librsvg
. @probonopd is proposing linking the libs directly to libappimage and not using dlopen
. I guess that it's safe path to go and will allow us to remove a lot of fragile 'dlopen' related code.
@TheAssassin are you okay with it ?
If it works reliably, yes, sure. I'd like to keep the dlopen
code for now (as in, keep it in the codebase, even if it won't be used directly any more), though. I posted on IRC an idea how to allow for using different backends, that way everyone can build libappimage against the libraries that work best for them. Through dynamic loading, though, we can implement a mechanism to use the "best available backend" for the job then, taking the bundled one (whatever that is) as fallback.
We can discuss that separately, though. Let's fix this first.
issue fixed by #118 Will close it, please reopen if required.
Getting lots of
ERROR: appimage_register_in_system : Unable to load libgobject-2.0.so
.Is this dependency coming from
libappimage
? I don't remember having seen it in pre-libappimage
days.