Coding conventions for QtPods

Home / Coding conventions for QtPods

Some of the coding conventions for QtPods seem to be gratuitous and often I am ending up explaining which ideas led to them. I think it is important to not only document things as they are, but also why decisions have been made. The goal is to help people who are contributing to understand and accept the overall appointment. We have thought and discussed countless hours and often we had to make compromises. Recognizing that there may be people with different, reasonable (and less reasonable) needs is essential. Unification and agreement brings a lot of advantages but does not only mean enforcing your rules on others.

Naming

The overall consensus seems to be that pods are called QtFoo officially. Repositories are all lowercase (qtfoo) and do only contain the pod sources, no documentation, tests or examples. Examples go into qtfoo-examples and so on, where qtfoo itself is integrated as a pod. Unless there is a technical limitation, the headers inside are called foo.h (ie. without the prepended “qt”). This is because only official Qt modules are prepended with “Qt”, pods aren’t official Qt modules. Only official Qt classes are prepended with a “Q”, but this also doesn’t apply to us.

There is only one reason we keep the “qt” in the pod and repository name: Pods can always be build outside the scope of QtPods. If they were only available within QtPods, we’d gracefully leave the extra “qt” out. Unfortunately (or fortunately :)), they’re not, so we keep the extra “Qt” to express their affinity to Qt.

File names are all lowercase – thus following the Qt standard. Also, a camel-cased “C++-version” is allowed. These should only be forwarding to the lowercase version. If you take a look at the “QString”-header for instance, it is forwarding to “qstring.h”.

qtfoo.pro
qtfoo.pri
foo.h
foo_p.h
foo.cpp
foo_p.cpp
Foo
veryniceclass.h
veryniceclass.cpp
VeryNiceClass

Class names are camel case, e.g.

class VeryNiceClass {
..
}

Include order

Own includes first, then third party dependencies, then Qt includes. This makes for a better separation of which class relies on another class within the code.

Build system

The build system is qmake. We thought about integrating cmake, but there are difficulties involved: We would need to drop the support for qmake entirely or hack around to integrating cmake-based projects with qmake. On a second note, cmake would be an extra dependency. Politically, qmake still is the standard build system for Qt projects. Although cmake is supported by QtCreator, it does come with Qt itself. There are numerous other build systems supported by QtCreator, for example GNU Autotools. It is well possible to build Qt apps with Autotools, but we didn’t take it for the same reasons we didn’t take cmake.

LICENSE and README.md

We followed the github standard. If you create a new project, github will optionally create those two files, so why fighting against it? If you are incorporating foreign code you will always need to know the license and some information on how to use it, so those two files are being enforced.

Flat directory structure

You can assume that pods and the final application(s) root folders will lie next to each other.

Static libraries vs dynamic libraries

There seems to be a widespread opinion that dynamic libraries are intrinsically better for no sane reason. The truth is, dynamic libraries suffer from many technical problems: You have to keep binary compatibility, dynamic libraries open up a second global variable space (yes, you can have two global variables with exactly the same name and it will compile gracefully, but crash while executing. Using the debugger you will find out that the same symbol may refer to multiple addresses in memory), on some platform versioning can be problematic and there are different, OS-dependend policies on where to find them and which to load. So, after all, you need good reasons to use dynamic libraries. There is no meaningful reason QtPods should use dynamic libraries and by using static libraries we are eliminating so many problems rightaway.

pro- and pri-files

If your project is called qtfoo, QtPods requires exactly two files: qtfoo.pro which is used to build a static library and a qtfoo.pri that will be included in the final application’s pro-file, so it should contain instructions for the final target: It should set include paths and link to third party libraries libraries. This is how a pro should look like:

TEMPLATE = lib
CONFIG += staticlib
TARGET = qtjack

SOURCES += \
    system.cpp \
    buffer.cpp \
    client.cpp \
    driver.cpp \
    parameter.cpp \
    port.cpp \
    server.cpp \
    netslave.cpp \
    netmaster.cpp \
    audioport.cpp \
    midiport.cpp \
    audiobuffer.cpp \
    midibuffer.cpp

HEADERS += \
    system.h \
    System \
    Buffer \
    buffer.h \
    Client \
    client.h \
    Driver \
    driver.h \
    Parameter \
    parameter.h \
    Port \
    port.h \
    Server \
    server.h \
    processor.h \
    Processor \
    ringbuffer.h \
    RingBuffer \
    netslave.h \
    NetSlave \
    netmaster.h \
    NetMaster \
    audioport.h \
    AudioPort \
    midiport.h \
    audiobuffer.h \
    midibuffer.h \
    AudioBuffer \
    MidiBuffer \
    global.h \
    MidiPort

And this is the corresponding pri. The $$PWD variable contains the directory the file is located in, so this is a convenient way to give a general instruction to add the pods root directory to the include path of the final application. I prefer to keep two separate LIBS statements, one for the pods’ static library and one for third party dependencies, but that’s personal taste.

INCLUDEPATH += \
    $$PWD

LIBS += \
    -L../qtjack -lqtjack

LIBS += -ljack -ljackserver -ljacknet

Leave a Reply

Your email address will not be published. Required fields are marked *