Tag Archives: Linux

A tale of three build systems

TL;DR

While we’re still 30s behind hand-written make, I totally would use any of the two over hand-written Makefiles.

As you might have noticed, meson is the new kid on the block. Step by step I am currently converting some projects to it, spearheading Shotwell. Since Shotwell only “recently” became an autotools project, you may ask why. Shotwell had a hand-written makefile system. This made some tasks that would have been incredibly easy with autotools, such as mallard documentation handling, more complicated than it should be. Since autotools provides all the nice features that you want for your GNOME environment, it made sense to leverage that.

Number games

Here are some numbers from the various transition phases. All taken on my i5 X201 laptop.

Conditions:

  • We build from a fresh git checkout (or git clean -dxf)
  • All builds are generated on the same machine with make -j $(($(nproc) + 2))
  • In the case of Meson, the ccache cache was emptied before

Shotwell 0.22

Configure:
real	0m0,011s
user	0m0,004s
sys	0m0,004s

Compile:
real	5m15,892s
user	17m30,392s
sys	1m10,984s

Shotwell 0.23.0

Shotwell’s makefile had a subtle rule issue that caused the plugins to be compiled several times over with valac. Also it was calling pkg-config with each compiler call, so after fixing that, we get these numbers for the compile step:

real	2m1,760s
user	6m31,788s
sys	0m26,788s

Shotwell master

Autotools

autogen.sh (including configure run):

real	0m32,315s
user	0m26,900s
sys	0m0,984s

Compiling:

real	2m25,164s
user	7m47,380s
sys	0m29,028s

Meson

mkdir build && meson build

real	0m1,529s
user	0m1,056s
sys	0m0,304s

ninja -C build

real	2m9,369s
user	7m17,276s
sys	0m33,660s

 

The time of the year…

Springtime is releasetime!

Monday saw a couple of new releases:

Shotwell

Shotwell 0.26.0 “Aachen” was released. No “grand” new features, more slashing of papercuts and internal reworks. I removed a big chunk of deprecated functions from it, with more to come for 0.28 on our way to GTK+4 and laid the groundworks for better integration into desktop online account systems such as UOA and GOA.

GExiv2 also received a bugfix release with its main highlight of proper documentation generation.
 

Rygel

In Rygel, things are more quiet. Version 0.34.0 moved some helpful classes for configuration handling to librygel-core and a couple of bugs were fixed. GSSDP and GUPnP also saw a small bugfix release.

Updates

Quiztime

First, a wrap-up of the last Quiztime. For an excellent explanation of the issue, read this comment. Also note that this is not the most nice way to do plugins with C++, it’s a boiled down piece of code I debugged.

Shotwell

I’m not sure if there is some confusion about the current development model of Shotwell. I noticed that some distributions seem to try to pick up the current development branch (0.25.x). I strongly advise against that at this point in time. It has just seen a major change in the Menu handling code and might still have severe usability regressions.

While I appreciate any testing of the code, I would really not have the current unstable version of Shotwell stuck in a released distribution. If you want to try those releases on Ubuntu, there is an unstable PPA available.

So to sum up: Shotwell follows the “traditional” version scheme of “Odd is unstable, even is stable” and roughly tries to stick to the GNOME release schedule.

Quiztime II

So, following up from the last quiztime which was about the importance of explicit linking, another case from the wonderful world of shared libraries.

This time we study the implications of dlopen, its parameters and C++. Consider the program and module below. If you run that, it will crash somewhat obscurely in libstdc++. Why?

#0  0x00007f687b2eb126 in std::ostream::sentry::sentry(std::ostream&) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#1  0x00007f687b2eb889 in std::basic_ostream >& std::__ostream_insert >(std::basic_ostream >&, char const*, long) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#2  0x00007f687b2ebd57 in std::basic_ostream >& std::operator< <  >(std::basic_ostream >&, char const*) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#3  0x00007f687a6f01a0 in Impl::print (this=0x558a9bc1f2e0, str="Hello") at module.cc:24
#4  0x0000558a99de3d1b in main (argc=1, argv=0x7ffca28cf538) at main.cc:31
#ifndef INTERFACE_H
#define INTERFACE_H
 
#include <string>
 
class IInterface {
    public:
        virtual ~IInterface() {};
        virtual void print(const std::string& str) = 0;
};
 
#endif // INTERFACE_H
</string>
#include "interface.h"
 
#include <iostream>
 
class Impl : public IInterface {
    public:
        Impl();
        virtual ~Impl();
        void print(const std::string& str);
};
 
extern "C" {
void *entry_point(void)
{
    return new Impl;
}
};
 
Impl::Impl() {};
Impl::~Impl() {};
 
void Impl::print(const std::string& str)
{
    std::cerr < <"Some text to print\n";
    std::cerr << "Got passed this: " << str << "\n";
    std::cerr << "=====\n";
}
#include <dlfcn .h>
#include <iostream>
 
#include "interface.h"
 
extern "C" {
typedef void *(*EntryFunction)(void);
};
 
int main(int argc, char *argv[])
{
    IInterface *iface;
    EntryFunction f;
 
    void *lib = dlopen("./module.so", RTLD_NOW | RTLD_DEEPBIND);
    if (lib == nullptr) {
        std::cerr < < dlerror () << "\n";
        return 1;
    }
 
    f = (EntryFunction) dlsym (lib, "entry_point");
 
    if (f == nullptr) {
        std::cerr << dlerror () << "\n";
        return 1;
    }
 
    iface = reinterpret_cast<IInterface *>(f());
 
    while (true) {
        iface->print ("Hello");
    }
}
</iostream></dlfcn>
.PHONY: all clean
all: main module.so
 
clean:
	rm -f main
	rm -f module.so
 
main: main.cc
	g++ -g -o $@ $< -ldl
 
module.so: module.cc
	g++ -g -o $@ -shared $< -fPIC

Quiztime!

Say you have a shared library with versioned symbols that has the function init(int *param) defined in two versions, where new_init is made the default for init (that’s what the  @@ means):

#include "shared1.h"
 
void new_init (int *param)
{
    *param = 0;
}
 
void old_init (int *param)
{
    *param = -1;
}
 
__asm__(".symver new_init,init@@VERS_2");
__asm__(".symver old_init,init@VERS_1");

Say you have a second shared library that provides a function do_something() uses that init from the first shared library:

#include "shared1.h"
 
int do_something ()
{
    int var;
    init (&var);
 
    return var;
}

And you have an app that just prints the result:

#include "shared2.h"
 
#include <stdio .h>
 
int main(int argc, char *argv[])
{
    printf ("Result: %d\n", do_something ());
 
    return 0;
}</stdio>

And all of this is cobbled together with the following Makefile:

all: app
 
libshared.so: shared1.c shared1.h
    cc -o $@ $< -shared -fPIC -Wl,--version-script=version.script
 
libmoreshared.so: libshared.so shared2.c
    cc -o $@ shared2.c -shared -fPIC
 
app: libmoreshared.so app.c
    cc -o $@ -L. app.c -lmoreshared -lshared

What’s the output of

LD_LIBRARY_PATH=. ./app

Update: Try to answer it without compiling and running it at first.
Update2: I forgot the version.script, sorry.

VERS_1 {
    local:
        old_init;
};
 
VERS_2 {
    local:
        new_init;
} VERS_1;

More updates

SystemD conf 2016

I will be giving a presentation at this year’s systemd conf in Berlin. If you ever wondered what the hell I am doing during the day, there’s your chance to get a glimpse 🙂

GUPnP going 1.0!

Parts of GUPnP (that is its core, GSSDP and GUPnP itself) will see a 1.0 release together with the next GNOME release. They are quite stable API-wise and functionality-wise now and I think it’s time to give them a proper blessing for that.

After that, master will become more unstable in regards of API, as there are some long-standing bugs and fixes that need an API change as well as new features to be added, such as proper IPv6 support, support for more recent versions of the UPnP standard (UDA 1.1, UDA 2.0), a more GIO-like async API,…

Rygel

We’ve been digging up some annoying age-old bugs or regressions deep down in Rygel for some corner-cases (Did you know that renderer unmute was broken since 2013?)

Shotwell

Some more usability fixes on their way, but the big roadblock of RAW import performance is still proving to be quite annoying. Bit like a hydra, really. You cut of one RAW developer, three new seem to disappear.

Project Lazarus: GtkTerm

I took GtkTerm and poked a bit at its source, mainly for two reasons

  • Dry-run some GTK modernisation that will be necessary in Shotwell as well (GAction etc.)
  • It’s the least worst (sic) of the graphical serial terminals I tried. At least it seems to cope way better with odd USB <-> Serial adapters than t rest of the bunch
  • I use it

Ok, that’s three reasons.

If you want to have a look, head over to its repository at https://github.com/phako/gtkterm

About a decade too late…

I’m currently working on adding DVD sharing to Rygel and while doing that, I resurrected a tool I wrote in 2005 to aid the tedious process of authoring DVDs on Linux. Today I cleaned it up a bit, gitified it and pushed it to github: https://github.com/phako/authorg

Please be warned that it might kill your data if you don’t read the message boxes carefully and cancel in time (and I mean that seriously, not as a standard disclaimer).

Raspberries and Rygel

First I have to apologize for the delay. I initially announced this in my GNOME.Asia talk almost two months ago.

TL;DR:

Raspbian and hardware-accelerated video decoding in Rygel without X. Follow brief instructions on http://rygel-project.org/raspbian/

What’s this problem?

There are already several solutions in the wild that combine Rygel and the Rasbperry Pi, be it Guacamayo or stock Raspbian. While Guacamayo provides easy server and audio renderer images, none of the existing solutions provide a video renderer.

Why’s that? Well, the RPi is (intentionally) slightly underpowered to do video decoding on the CPU. Howerver, it supports video decoding in hardware.

The issue here is that Raspbian is based on wheezy which only comes with GStreamer 0.10 while the support for hardware-based video decoding on the RPi in gstreamer-omx was only added recently to GStreamer 1.0.x. And since this is wheezy, the Rygel package that comes with it is too old to use GStreamer 1.0.

So let’s just grab the packages from sid armhf, should be working, no?

No it doesn’t. Rasbpian is basically a recompilation of Debian for ARMv5 with hard float ABI, while Debian itself is using ARMv7. So we can’t just copy packages.

So?

Well the good news is that we don’t need to do all the heavy recompiling of GStreamer. Someone already did that for us. This work is available at http://vontaene.de/raspbian-updates/ (from the raspberrypi.org forum).

And what exactly are you doing now?

We provide a Debian repository with Rygel’s packages backported to Raspbian. That’s a bit boring, you say? Indeed. This is only the beginning. There will also be a set of instructions to convert a Rasbian installation into a hardware-accelerated DLNA renderer. The first step to this is a meta-package called raspbian-dlna-renderer which depends on all the other important packages necessary for a complete environment.

What’s working right now?

First, add the following repositories to your /etc/apt/sources.list

deb http://rygel-project.org/raspbian wheezy/
deb-src http://rygel-project.org/raspbian wheezy/

deb http://vontaene.de/raspbian-updates/ . main

The packages on rygel-project.org are signed with my private GPG key, key id 7696ECBF. Then run apt-get update && apt-get install raspbian-dlna-renderer to get all updated and necessary packages.

I’ve modified /boot/cmdline.txt to get a screen that is as empty as possible by adding silent and logo.nologo to the kernel parameters.

You can then launch Rygel as user and play files on the RPi using Helium, gupnp-av-cp from GUPnP Tools or any other DLNA control point.

What’s next?

A next version of the meta-package will probably add auto-starting Rygel as a system service – Maybe we’ll even provide a ready-to-go image…

GNOME.Asia 2013

DSCF0524_RAF_embedded

A bit late for the “I’m back from this year’s GNOME.Asia” post, but well. This was the fist GNOME.Asia event I attended and even my first time in asia and it was a very interesting experience that needs repeating. It was nice to meet all those people from around this part of the world who never make it to the european conference and I was particularly pleased to meet Jiro who enabled i18n support in the GUPnP tools and to learn about the <Super>M shortcut to get the message bar. Unfortunately I couldn’t join the city tour on Sunday since I was already heading back to London then.

I did a talk on DLNA (who would have guessed that) in GNOME and some of the things that might come: Slides of the talk. I’m afraid the blog post on setting up a hardware-accelerated DLNA renderer on the Raspberry Pi that I announced during the talk is still not written, sorry about that.

A big thanks to the the cheerful local team, the GNOME.Asia people and of course the sponsors who made all this possible and thanks to the GNOME foundation for sponsoring my attendence.

sponsored-badge-simple