Working around broken Boost.Thread

21.02.2015 12:42

Debian Wheezy ships with a broken boost/thread.hpp header. Specifically, there's a conflict between a TIME_UTC preprocessor macro that was introduced in C11 and an enum type defined by Boost 1.49 (bug 701377). This results in somewhat cryptic compile errors for all C files that happen to include this header:

/usr/include/boost/thread/xtime.hpp:23:5: error: expected identifier before numeric constant
/usr/include/boost/thread/xtime.hpp:23:5: error: expected ‘}’ before numeric constant
/usr/include/boost/thread/xtime.hpp:23:5: error: expected unqualified-id before numeric constant
/usr/include/boost/thread/xtime.hpp:46:14: error: expected type-specifier before ‘system_time’

I first encountered this when compiling GNU Radio from source, but the problem is not specific to that project. The obvious solution would be to upgrade Boost to a newer version, but this does not appear to be possible on Wheezy without upgrading many other packages. Some web searches reveal that the general consensus regarding the solution seems be to open the /usr/include/.../xtime.hpp header in a text editor and change the offending enum.

This is bad advice. Straightforward editing of files that are managed by the package manager is never a good idea. Your fix will be silently overwritten by any minor Boost package update. Also, when debugging any kind of problem, nobody expects that files shipped in a package have been modified locally. Among other things, this can lead to hard-to-solve bugs that are not reproducible on other, seemingly identical systems.

The correct way to solve this problem (at least until Debian ships a fixed Boost library) is to work around it in the source you are compiling. For instance, including the following on top of every C file that includes boost/thread.hpp removes the conflicting macro:

#include <time.h>
#undef TIME_UTC

The trick is to have this before any other #includes. You want it to be the first time time.h is included in the compilation unit. Since time.h is protected against multiple includes, TIME_UTC won't get redefined later on when it is included for the second time through Boost headers. Of course, then the TIME_UTC macro isn't available anymore, but so far I haven't seen any code that would use it.

I've also made a patch for GNU Radio 3.7.5 that applies this workaround in all necessary places.

Posted by Tomaž | Categories: Code

Comments

A less intrusive solution could be to have another file named time.h in your include path (before the actual one) doing:

#pragma once // Or the standard complying #ifdef/#define equivalent
#include_next <time.h>
#undef TIME_UTC

This way, the wrapping is done automatically and you don't have to chage the other files at all to avoid the bug.

Interesting. I didn't know about #include_next. Just note that it is a GNU cpp extension.

Posted by Tomaž

Add a new comment


(No HTML tags allowed. Separate paragraphs with a blank line.)