Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The mess that is ctime, time.h, sys/time.h

I hope some Linux die-hard can answer me how I should write portable (POSIX) code when working with time functions.

  • Some SO threads suggest that including ctime would be the right thing to do when writing C++ code, whereas you would still include time.h for C code. However, they both define the same function, albeit in a different namespace. Technically you should be able to specify both.

  • One SO post suggested that one should AVOID using the sys/* based includes alltogether..

  • .. while this thread implies that sys/time.h must be included before sys/resources.h is included, in particular for BSD-based platforms.

  • This post says including sys/time.h improves portability. I imagine the poster thinks that it allows you to link more 3rd party libaries that use particular functions like gettimeofday.. however..

  • gettimeofday() has been discouraged, and is now currently enjoying deprecated status, so I should use clock_gettime() instead. This clock_gettime() is defined in time.h, see https://linux.die.net/man/3/clock_gettime..

  • .. if one installs and links with libavutil (e.g. as part of ffmpeg-dev) it becomes clear that time.h was created to drive people nuts. Ffmpeg (and some other libs) has it's own time.h, and even timeb.h. It turns out that if ANY .c or .cpp anywhere in your build stack ever includes a time.h, with the include path holding multiple valid entries (including the one for ffmpeg), it may refer to the wrong one, and the declarations are simply replaced. @ FFmpeg, the reasoning seems to be that an ugly hack is sufficient to fix the problem. I haven't been that lucky yet. Also, Php-izing all sources does not sound like a solution at all.

  • Another time.h exists in usr/include/i386-linux-gnu/bits on my system, so this isn't an ffmpeg-only phenomenon either. Simply referring to usr/include/i386-linux-gnu as an include path thus becomes deadly, which is odd when referring to system includes.

  • I've rewritten my CMake scripts, taking care to use dedicated include folder specs for most of the targets. I've tried including all sorts of permutations of time.h/ctime and sys/time.h in a precompiled header that is referred to throughout the codebase. I still get errors like:

error: field ‘st_atim’ has incomplete type ‘timespec’, struct timespec st_atim;

error: ‘::time’ has not been declared

etc..

So, for a C++ setup linking with many 3rd party dependencies, what is the correct way to make sure everything keeps compiling w.r.t. including time.h? Should I pin the time.h include for the system to the specific platform I'm compiling to? Should I go over all targets that possibly need time.h? Dancing elephants and confetti lie ahead.


Update: The issue seems to be related to the version of C++ as was hinted at in the comments below. I've since updated gcc to 8.3.0 (from 5.4), and I've given up on supporting older c++ compatibility below c++11 on linux. After updating and rebuilding all 3rd party packages (including ffmpeg), I now no longer have the issue I described, but that doesn't mean it's fixed in the sense that it can't occur again for someone else. In fact I think the issue is mainly with how ffmpeg compiles on older compilers and without c++11 explicitly requested, so I'm leaving it open.

like image 800
StarShine Avatar asked Mar 26 '19 00:03

StarShine


1 Answers

I recommend you consider Howard Hinnant's date library that has been accepted into the next version of the C++ standard library (C++20):

https://github.com/HowardHinnant/date

It should work on any platform that supports C++11 onwards.

The Standard version is documented here: https://en.cppreference.com/w/cpp/chrono

like image 195
Galik Avatar answered Sep 20 '22 18:09

Galik