Notable Quotes From Non-Programmers

Nokia just announced a line of phones running Android, which don’t actually make use of Google services. It’s a pretty bad idea, but I like the quote coming from the management suite:

“While apps that use only AOSP should run on the X phones directly, any apps that for example integrate with location or store services will need porting, a process that Stephen Elop said should take a few hours.”

It’s this kind of detachment from developers that got Microsoft into trouble in the first place with all of their attempts to develop and to capture smartphone mindshare. With a divorced-from-reality quote like that, who would actually want to bother porting their app to the “Microsoft Android App Store”? It’s like Captain Picard saying “Make it so.”, except in that case, shit actually gets done.

Go big or go home, make the Windows Phone platform strong enough and big enough to compete for app revenue, or don’t bother. A move like this is just reheated Symbian strategy. I do not see how this is competitive at all, in a market flooded with low- and mid-range Chinese competitors that do already access the full range of Google services.

qmake SUBDIRS Project Automatic Dependencies

Here’s what I searched for, before figuring out how to get SUBDIRS dependencies working using qmake:

“qmake export compiler flags”
“qmake export defines”
“qmake export includepath”
“qmake build dependent projects”
“qt creator automatically build dependent libraries”

Problem 1: Detecting Dependency Changes

Qt Creator has some weird behaviors. As in, it doesn’t properly do dependent library builds all of the time, particularly when you’re using a SUBDIRS project template. I noticed that I would always have to right-click a project and “Run qmake” before running “Build X Project”, which was annoying. And I noticed that libraries wouldn’t automatically build and link to their consuming executables. It didn’t make sense, as I had used the “Add Library” option to add configuration blocks, like the following, to the executable project files that needed them:

win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../SomeLibrary/release/ -lSomeLibrary
else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../SomeLibrary/debug/ -lSomeLibrary
else:unix: LIBS += -L$$OUT_PWD/../SomeLibrary/ -lSomeLibrary

INCLUDEPATH += $$PWD/../SomeLibrary/source
DEPENDPATH += $$PWD/../SomeLibrary/source

win32:CONFIG(release, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../SomeLibrary/release/SomeLibrary.lib
else:win32:CONFIG(debug, debug|release): PRE_TARGETDEPS += $$OUT_PWD/../SomeLibrary/debug/SomeLibrary.lib
else:unix: PRE_TARGETDEPS += $$OUT_PWD/../SomeLibrary/libSomeLibrary.a

Once that block was in place, I figured all would be good. However, all that Qt Creator would do is tell me was that libSomeLibrary.a wasn’t available, if I’d run a Clean on all of the projects, rather than just building and linking it for me. As in, make would know the library file was missing (via the TARGET_PREDEPS setting), but it would be too stupid to just build that target. And it wasn’t clear that any changes to SomeLibrary were being built and linked into the consuming executable, since SomeLibrary wasn’t getting autobuilt as a dependency. It seemed like old SomeLibrary code was getting linked instead, and only the executable’s changed code was getting recompiled before the link. This was a dependency nightmare in the making.

On all of these particular points, the qmake manual does not clarify that SUBDIRS projects are essentially a completely different beast, and require different rules to set up.

Not so useful.

The way to properly define dependencies in a SUBDIRS project is to use a master Project file that looks something like:

cache()

TEMPLATE = subdirs

SUBDIRS += \
    ConsoleTest \        # an "app" project
    SomeLibrary \        # a  "lib" project
    SomeExternalLibrary  # a  "lib" project

# ConsoleTest.subdir is implicitly set to "ConsoleTest".

SomeLibrary.subdir         = SomeLibrary
SomeExternalLibrary.subdir = external/SomeExternalLibrary

# Here's where you build up the hierarchical relationship between components.

SomeLibrary.depends = SomeExternalLibrary
ConsoleTest.depends = SomeLibrary

This is all you need to do. The next time the project file is parsed and qmake is run to generate the platform-specific Makefiles, it will generate the dependencies properly. No more weird builds and dependency problems. As much as I appreciate Qt’s awesome software, this is something they really need to clarify how to get working in their manual.

Problem 2: Exporting DEFINES and INCLUDEPATH

In addition to the above, the method to set up the various projects to export the qmake DEFINES and INCLUDEPATH flags used to build them was not clear from the documentation.

What you want in a hierarchical project configuration, ideally, is that the whole project rebuilds if any of the library sources, includes, included folders, or compiler DEFINES changes. You want any library consumers to use the exact same settings used to build the libraries, and you want this to happen if the setting changes in a single, authoritative place (preferably the library build configuration). The only reference I could find to “library dependencies” in the qmake manual is not clear as to its mechanism for propagating this information, particularly the INCLUDEPATH and DEFINES settings.

After reading a handful of other references (1), (2), I finally figured out how to do this. It turns out that qmake has a lot of power to it, but that power is buried in bad documentation. (Why does no one invest in documentation? It’s an excellent opportunity to generate goodwill.)

The trick is twofold:

For each library project, you need to split the declaration of DEFINES and INCLUDEPATH into a Defines.pri file at the same level as the .pro Project file, for example:

/SomeLibrary
/SomeLibrary/SomeLibrary.pro
/SomeLibrary/Defines.pri

In Defines.pri, add the DEFINES and INCLUDEPATH settings:

DEFINES += SOME_COMPILER_SETTING

message(Including $$_FILE_ from $$IN_PWD)
INCLUDEPATH += $$IN_PWD/source

In SomeLibrary.pro, add

include(Defines.pri)

In any other project, include the DEFINES and INCLUDEPATH settings using a similar include:

include(/SomeLibrary/Defines.pri)

You should then see something like "Including /SomeLibrary/Defines.pri from /SomeLibrary" show up in the General Messages window in Qt Creator, when the project files are reparsed, meaning that the dependent project pulled in these settings properly. In this way, any changes made to the Defines.pri will get propagated to the consuming projects.

So that’s it. Good luck.

Update

After some experimentation, you still need to “Add Library” the static library configuration blocks to the .pro project file of any consuming executables, for some reason when I tried moving these configuration blocks from the executable .pro files to the library .pri files, qmake started getting stuck in an infinite loop.

Omitting these configuration blocks will also cause the executables not to link. I don’t think I’m going to investigate this more closely, since solving the includeable DEFINES/INCLUDEPATH problem took care of a bigger build consistency issue. (But maybe I’ll come back to it.)

Old Habits

For the record, it turns out C++ fixed the inconsistency in C of forward-declared functions taking no parameters possibly allowing parameters to be passed. But I still declare those functions and class methods with a (void) parameter list anyway.

Old habits die hard.

old-habits

Reference.

Better Time Synchronization with VirtualBox Guest Additions

The time synchronization using the VirtualBox Guest Additions is too gradual by default. One of my machines drifted until there was a discrepancy of almost 20 minutes. Apparently, 20 minutes is the threshold at which a hard resync is performed. But this isn’t what I expected from the Guest Additions. I expected the guest system time to track the host system time precisely, and it didn’t seem like this was happening. I also don’t want gradual resynchronization, as it just takes too long to shift the clock back into a usable state.

When the clock is seriously skewed, building software goes awry, because the make command starts detecting filestamps from the future, and other weird things.

According to the VirtualBox Manual, you can tune the time synchronization parameters by either setting properties on the virtual machine configuration using vboxmanage, or by specifying the parameters to VBoxService itself. I chose the latter option, though I’m sure the former is probably easier.

The startup file that controls VBoxService on Ubuntu is /etc/init.d/vboxadd-service. It is possible to edit this file to force more frequent synchronization, by changing the line:

daemon $binary > /dev/null

to:

daemon $binary "--timesync-set-start --timesync-set-on-restore 1 --timesync-set-threshold 5000" > /dev/null

In addition, I pushed the niceness level of the task downwards, so that even under pressure, the VBoxService isn’t competing with normal tasks to do its job. In the same file, I changed the line:

start-stop-daemon --start --exec $1 -- $2

to:

start-stop-daemon --start --nicelevel "-5" --exec $1 -- $2

For the impatient: Running the VBoxService command by hand will also do an immediate clock-sync, along with generating some output you would rarely see:

/etc/init.d$ sudo /usr/sbin/VBoxService --timesync-set-start
VBoxService 4.3.6 r91406 (verbosity: 0) linux.amd64 (Dec 18 2013 16:45:21) release log
00:00:00.001752 main Log opened 2014-02-09T12:38:04.424360000Z
00:00:00.002533 main OS Product: Linux
00:00:00.002776 main OS Release: 3.8.0-35-generic
00:00:00.003015 main OS Version: #52~precise1-Ubuntu SMP Thu Jan 30 17:24:40 UTC 2014
00:00:00.003255 main OS Service Pack: #52~precise1-Ubuntu SMP Thu Jan 30 17:24:40 UTC 2014
00:00:00.003498 main Executable: /opt/VBoxGuestAdditions-4.3.6/sbin/VBoxService
00:00:00.003499 main Process ID: 1864
00:00:00.003500 main Package type: LINUX_64BITS_GENERIC
00:00:00.004203 main 4.3.6 r91406 started. Verbose level = 0

In my case, the guest clock will now drift no more than 5 seconds before a hard-resync with the host clock.