Libraries are Evil

We all know that reading books can be dangerous, but this is not why software libraries are evil 😉

There is a different reason for this.

Let’s assume we have module we like to create a library from:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
module libx;

struct X {
    version(B) {
        int y = 42;
    }
    int z = 3;
}

void doX(ref X x) {
    version(B) {
        x.y = 13;
    }
    x.z = 5;
}

The module libx provides a structure X and a function doX. However, they behave both different depending on the compiled version (you can think of B as e.g. a debug version).

Now to the program using the library:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int main() {
    import libx;
    import std.stdio;

    X myX;
    version (B) {
        writeln("y ", myX.y);
    }
    writeln("z ", myX.z);
    doX(myX);
    version (B) {
        writeln("y ", myX.y);
    }
    writeln("z ", myX.z);
    return0;
}

Even though our program is aware of the different versions, if we build the library and the program using it with different versions, this will lead to really hard to debug errors.

You could argue that the problem is the multi-version library. However, this issue is even worse for compiler options. Just think about the options defining the layout of structures in memory, i.e. for aligning and padding of the members.

I want you to be able to sleep at night, so don’t even start thinking about dynamic link libraries 😉

Summary: If you want a program to be working, do not use pre-compiled libraries. Always compile with the same compiler in one run and statically link every object together.