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.
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
Related
PROBLEM SUMMARY
We took a crack at using cotire, the Compile-Time Reducer, as our precompiled header system due to the extremely long compile times caused by usage of the Boost C++ template library. We are getting poor to dangerous results-- the precompiled headers seem to be constantly rebuilt, and are occasionally masking build problems. Specifically, back-to-back builds result in differing hashes of the actual cotire precompiled headers themselves, and, when attempting incremental builds, the precompiled headers are rebuilt every time, even when no header material has changed.
BACKGROUND
The project is a Linux CMake build using g++ 6.3.1, which produces, as its artifacts, an installable shared-library and several executables. Possibly of note, we have no interest in using unity builds, due to constant requirements for rapid-iteration development. However, the project is very large, hence the interest in cotire.
It is worth noting that, to avoid unexpected interactions while troubleshooting this issue, we have disabled ccache, the compiler cache. (Our intent is to eventually enable ccache if and only if we get consistent, expected results from cotire, or after we give up and remove cotire.)
The project uses C++03 (though building with 11 did not change our results for purposes of this question) and relies extensively on the Boost C++ library. Specifically, we make constant use of Boost Signal-Slot, boost::bind, boost::function, and quite a few of the iteration capabilities. Boost implements all of these via extensive template meta-programming and variant self-inclusion.
It is possible, though not entirely straightforward, to "blacklist" header files from cotire, excluding them from the generated precompiled headers. We attempted to blacklist various subdirectories within Boost itself (Boost includes some 900 different header files, so we mostly restricted ourselves to its immediate subdirectories). This seemed to produce improved results-- blacklisting certain parts of Boost resulted in back-to-back clean builds that produced matching precompiled header hashes.
Unfortunately, after a more significant delay-- perhaps ten minutes-- a third attempt to do a clean build resulted in a different hash for the precompiled header.
At this point, our working theory was that various special preprocessor symbols such as __TIME__ and __DATE__ were somehow getting mangled into cotire's input. Searching for these in Boost's headers does indeed produce a number of hits in wave, spirit, etc. Presumably this causes cotire to believe that the headers have changed in some way, because it attempts to rebuild the entire precompiled header with every build (though not with every compilation unit; we tentatively believe we have it integrated into the build process correctly).
QUESTION
Has anyone successfully used cotire with gcc/g++ and Boost? Were any unusual steps required, as opposed to using cotire in a project without Boost?
We are interested in cotire specifically; results from, for example, Visual Studio's precompiled header system might be interesting but are unlikely to be helpful. However, if you are troubleshooting similar issues and wish to provide your observations here, please feel free to do so.
I have shared code given to me that compiles on one linux system but not a newer system. The error is uint32_t does not name a type. I realize that this is often fixed by including the <cstdint> or stdint.h. The source code has neither of these includes and I am trying to seek an option that doesn't require modifying due to internal business practices that I can't control. Since it compiles as is on one machine they don't want changes to the source code.
I am not sure if it matters but the older system uses gcc 4.1 while the newer one uses gcc 4.4. I could install different versions of gcc if needed, or add/install library/include files on the newer machine, I have full control of what is on that machine.
What are my options for trying to compile this code on my machine without modifying the source? I can provide other details if needed.
I am not sure if it matters but the older system uses gcc 4.1 while the newer one uses gcc 4.4
GCC stopped including <stdint.h> some time ago. You now have to include something to get it...
I realize that this is often fixed by including the <cstdint> or stdint.h. The source code has neither of these includes and I am trying to seek an option that doesn't require modifying due to internal business practices that I can't control...
I hope I am not splitting hairs... If you can't modify the source files, then are you allowed to modify the build system or configuration files; or the environment? If so, you can use a force include to insert the file. See Include header files using command line option?
You can modify Makefile to force include stdint.h. If the build system honors CFLAGS or CXXFLAGS, then you can force include it in the flags. You last choice is probably to do something like export CC="gcc -include stdint.h".
The reason I am splitting hairs is OpenSSL and FIPS. The OpenSSL source files for the FIPS Object Module are sequestered and cannot be modified. We have to fallback to modifying supporting scripts and the environment to get some things working as expected.
If you really don't want to amend the file you could wrap it. Suppose it's called src.c create a new file src1.c:
#include <stdint.h>
#include "src.c"
And then compile src1.c.
PS: The problem may arise because compilers include other headers in their header files. This can mean some symbols 'officially' defined in other headers are quietly defined when you include a header that isn't specified as including it.
It's an error to write a program relying on a symbol for which the appropriate header hasn't been included - but it's easy to do and difficult to spot.
A changing compiler or version sometimes reveals these quiet issues.
Unfortunately, you can't force your code to work on a newer compiler without modifying something.
If you are allowed to modify the build script and add source files to the project, you might be able to add another source file to the project which, in turn, includes your affected file and headers it really needs. Remove the affected source files from the build, add the new ones, and rebuild.
If your shared source is using macro magic (e.g. an #include SOME_MACRO, where SOME_MACRO can be defined on the command line), you might be able to get away with modifying build options (to define that macro for every compilation of each file). Apart from relying on modifying the build process, it also relies on a possible-but-less-than-usual usage of macros in your project.
It may be possible to modify the standard headers in your compiler/library installation - assuming you have sufficient access (administrative) to do so. The problem with this is that the problem will almost certainly re-emerge whenever an update/patch to the compiler/library is installed. Over time, this approach will lock the code into relying on an older and older compiler/library that has been superseded - no ability to benefit from compiler bug fixes, evolution of standards, etc. This also severely limits your ability to share the code, and ability of others to use it - anyone who receives the code needs to modify their compiler/library installation.
The basic fact, however, is that your shared code relies on a particular implementation (compiler/library) that exhibits non-standard behaviour. Hence it has failed with an update of that implementation - which removed those non-standard occurrences - it is likely to fail with other implementations (porting to different compilers in future, etc). The real technical solution is to modify the source, and #include needed headers correctly. The real business solution is to make a business case justifying the need for such modifications, citing inefficiency - which will grow over time - in terms of cost and effort needed to maintain the shared code whenever it needs to be ported, or whenever a compiler is updated.
look at the second last line of code above your error, you'll find everything above that terminates with a , and only use a ; on the last entery
I'm using Cygwin32 on Win7 64. I have g++ and libstdc++ installed. The C++ includes are located at /usr/lib/gcc/i686-pc-cygwin/4.8.2/include/c++/tr1/ - but nowhere under /usr/include.
Is it reasonable to place them, by symlink, under /usr/include? If not, why? And if so, why isn't this done by default And what should the symlink be? /usr/include/c++/ ? Something else?
Note: Yes, I know I can add them to the compiler flags; I'm asking whether it's reasonable to do more than that.
There shouldn't be any need, if you are talking about standard C++ includes. The g++ version destined to use them should know about that location, and since you might have different gcc versions around (for example, MinGW's one), it is better to leave it as it is just to not confuse other compilers.
If your compiler is having troubles finding its own includes, well, that's entirely another matter.
If you are curious about how and why this location is determined, read here, specifically under the option --enable-version-specific-runtime-libs ... it says something about "using several gcc versions in parallel". You can also check the actual configure script under libstdc++-v3 source code directory...
In my personal experience, when you are creating a single library for a bunch of platforms, you simply want (cross-) compilers as independent as possible. If every compiler puts its includes in /usr/include/c++ ... well, that can end bad. In fact, under that particular scenario, it could be reasonable for each compiler to hide its specific header and library files as well as possible...
Just add them to your environment variable CPPFLAGS (or in your makefile):
CPPFLAGS='-I/usr/lib/gcc/i686-pc-cygwin/4.8.2/include/c++/tr1 -I/whatev'
I would like to start using boost in an embedded environment. I can live without boost libraries that require compilation for quite sometime. I suppose just moving boost directory into appropriate place in our code base will do the trick
Am I right about it or it is more involved than that?
How to get rid of header files for the libraries that are not being used?
Are there any gcc version dependencies in boost libraries. E.g. can use gcc-4.1.1 with the latest?
Am I right about it or it is more involved than that?
That will do it.
How to get rid of header files for the libraries that are not being used?
Why bother? They're not going to be compiled into the program. When you deploy your distribution won't be any different whether you remove them or not.
Are there any gcc version dependencies in boost libraries. E.g. can use gcc-4.1.1 with the latest?
vOv - That's a very old version. Boost takes things a lot further than most, more that I think they should most of the time, trying to make sure it works with old and/or broken compilers. You're really pushing it though.
I have not tried it myself, but if you compile Boost with a directory prefix, then I suppose you could move the directory later. I can't see a big problem with that or at least one that can't be fixed quickly.
As for getting rid of header files for libraries that aren't use, look into the bcp utility for the version with which you are using:
http://www.boost.org/doc/libs/1_49_0/tools/bcp/doc/html/index.html
It is "a tool for extracting subsets of Boost" -- exactly what you are looking for.
As for your last question, I think it depends on what version of Boost you are using. I've never had a problem with gcc dependencies...it seems their requirements are fairly liberal. I don't think you need to be worried too much about it unless you plan to use a version of gcc that is "much" older (than the Boost you plan to use). I would guess 'old' here is old enough that you don't need to worry -- any number that I would say would be merely a guess...
Hope this helps!
I have an annoying problem which I might be able to somehow circumvent, but on the other hand would much rather be on top of it and understand what exactly is going on, since it looks like this stuff is really here to stay.
Here's the story: I have a simple OpenGL app which works fine: never a major problem in compiling, linking, or running it. Now I decided to try to move some of the more intensive calculations into a worker thread, in order to possibly make the GUI even more responsive — using Boost.Thread, of course.
In short, if I add the following fragment in the beginning of my .cpp file:
#include <boost/thread/thread.hpp>
void dummyThreadFun() { while (1); }
boost::thread p(dummyThreadFun);
, then I start getting "This application has failed to start because MSVCP90.dll was not found" when trying to launch the Debug build. (Release mode works ok.)
Now looking at the executable using the Dependency Walker, who also does not find this DLL (which is expected I guess), I could see that we are looking for it in order to be able to call the following functions:
?max#?$numeric_limits#K#std##SAKXZ
?max#?$numeric_limits#_J#std##SA_JXZ
?min#?$numeric_limits#K#std##SAKXZ
?min#?$numeric_limits#_J#std##SA_JXZ
Next, I tried to convert every instance of min and max to use macros instead, but probably couldn't find all references to them, as this did not help. (I'm using some external libraries for which I don't have the source code available. But even if I could do this — I don't think it's the right way really.)
So, my questions — I guess — are:
Why do we look for a non-debug DLL even though working with the debug build?
What is the correct way to fix the problem? Or even a quick-and-dirty one?
I had this first in a pretty much vanilla installation of Visual Studio 2008. Then tried installing the Feature Pack and SP1, but they didn't help either. Of course also tried to Rebuild several times.
I am using prebuilt binaries for Boost (v1.36.0). This is not the first time I use Boost in this project, but it may be the first time that I use a part that is based on a separate source.
Disabling incremental linking doesn't help. The fact that the program is OpenGL doesn't seem to be relevant either — I got a similar issue when adding the same three lines of code into a simple console program (but there it was complaining about MSVCR90.dll and _mkdir, and when I replaced the latter with boost::create_directory, the problem went away!!). And it's really just removing or adding those three lines that makes the program run ok, or not run at all, respectively.
I can't say I understand Side-by-Side (don't even know if this is related but that's what I assume for now), and to be honest, I am not super-interested either — as long as I can just build, debug and deploy my app...
Edit 1: While trying to build a stripped-down example that anyway reproduces the problem, I have discovered that the issue has to do with the Spread Toolkit, the use of which is a factor common to all my programs having this problem. (However, I never had this before starting to link in the Boost stuff.)
I have now come up with a minimal program that lets me reproduce the issue. It consists of two compilation units, A.cpp and B.cpp.
A.cpp:
#include "sp.h"
int main(int argc, char* argv[])
{
mailbox mbox = -1;
SP_join(mbox, "foo");
return 0;
}
B.cpp:
#include <boost/filesystem.hpp>
Some observations:
If I comment out the line SP_join of A.cpp, the problem goes away.
If I comment out the single line of B.cpp, the problem goes away.
If I move or copy B.cpp's single line to the beginning or end of A.cpp, the problem goes away.
(In scenarios 2 and 3, the program crashes when calling SP_join, but that's just because the mailbox is not valid... this has nothing to do with the issue at hand.)
In addition, Spread's core library is linked in, and that's surely part of the answer to my question #1, since there's no debug build of that lib in my system.
Currently, I'm trying to come up with something that'd make it possible to reproduce the issue in another environment. (Even though I will be quite surprised if it actually can be repeated outside my premises...)
Edit 2: Ok, so here we now have a package using which I was able to reproduce the issue on an almost vanilla installation of WinXP32 + VS2008 + Boost 1.36.0 (still pre-built binaries from BoostPro Computing).
The culprit is surely the Spread lib, my build of which somehow requires a rather archaic version of STLPort for MSVC 6! Nevertheless, I still find the symptoms relatively amusing. Also, it would be nice to hear if you can actually reproduce the issue — including scenarios 1-3 above. The package is quite small, and it should contain all the necessary pieces.
As it turns out, the issue did not really have anything to do with Boost.Thread specifically, as this example now uses the Boost Filesystem library. Additionally, it now complains about MSVCR90.dll, not P as previously.
Boost.Thread has quite a few possible build combinations in order to try and cater for all the differences in linking scenarios possible with MSVC. Firstly, you can either link statically to Boost.Thread, or link to Boost.Thread in a separate DLL. You can then link to the DLL version of the MSVC runtime, or the static library runtime. Finally, you can link to the debug runtime or the release runtime.
The Boost.Thread headers try and auto-detect the build scenario using the predefined macros that the compiler generates. In order to link against the version that uses the debug runtime you need to have _DEBUG defined. This is automatically defined by the /MD and /MDd compiler switches, so it should be OK, but your problem description suggests otherwise.
Where did you get the pre-built binaries from? Are you explicitly selecting a library in your project settings, or are you letting the auto-link mechanism select the appropriate .lib file?
I believe I have had this same problem with Boost in the past. From my understanding it happens because the Boost headers use a preprocessor instruction to link against the proper lib. If your debug and release libraries are in the same folder and have different names the "auto-link" feature will not work properly.
What I have done is define BOOST_ALL_NO_LIB for my project(which prevents the headers from "auto linking") and then use the VC project settings to link against the correct libraries.
Looks like other people have answered the Boost side of the issue. Here's a bit of background info on the MSVC side of things, that may save further headache.
There are 4 versions of the C (and C++) runtimes possible:
/MT: libcmt.lib (C), libcpmt.lib (C++)
/MTd: libcmtd.lib, libcpmtd.lib
/MD: msvcrt.lib, msvcprt.lib
/MDd: msvcrtd.lib, msvcprtd.lib
The DLL versions still require linking to that static lib (which somehow does all of the setup to link to the DLL at runtime - I don't know the details). Notice in all cases debug version has the d suffix. The C runtime uses the c infix, and the C++ runtime uses the cp infix. See the pattern? In any application, you should only ever link to the libraries in one of those rows.
Sometimes (as in your case), you find yourself linking to someone else's static library that is configured to use the wrong version of the C or C++ runtimes (via the awfully annoying #pragma comment(lib)). You can detect this by turning your linker verbosity way up, but it's a real PITA to hunt for. The "kill a rodent with a bazooka" solution is to use the /nodefaultlib:... linker setting to rule out the 6 C and C++ libraries that you know you don't need. I've used this in the past without problem, but I'm not positive it'll always work... maybe someone will come out of the woodwork telling me how this "solution" may cause your program to eat babies on Tuesday afternoons.
This is a classic link error. It looks like you're linking to a Boost DLL that itself links to the wrong C++ runtime (there's also this page, do a text search for "threads"). It also looks like the boost::posix::time library links to the correct DLL.
Unfortunately, I'm not finding the page that discusses how to pick the correctly-built Boost DLL (although I did find a three-year-old email that seems to point to BOOST_THREAD_USE_DLL and BOOST_THREAD_USE_LIB).
Looking at your answer again, it appears you're using pre-built binaries. The DLL you're not able to link to is part of the TR1 feature pack (second question on that page). That feature pack is available on Microsoft's website. Or you'll need a different binary to link against. Apparently the boost::posix::time library links against the unpatched C++ runtime.
Since you've already applied the feature pack, I think the next step I would take would be to build Boost by hand. That's the path I've always taken, and it's very simple: download the BJam binary, and run the Boost Build script in the library source. That's it.
Now this got even a bit more interesting... If I just add this somewhere in the source:
boost::posix_time::ptime pt = boost::posix_time::microsec_clock::universal_time();
(together with the corresponding #include stuff), then it again works ok. So this is one quick and not even too dirty solution, but hey — what's going on here, really?
From memory various parts of the boost libraries need you to define some preprocessor flags in order to be able to compile correctly. Stuff like BOOST_THREAD_USE_DLL and so on.
The BOOST_THREAD_USE_DLL won't be what's causing this particular error, but it may be expecting you to define _DEBUG or something like that. I remember a few years ago in our boost C++ projects we had quite a few extra BOOST_XYZ preprocessor definitions declared in the visual studio compiler options (or makefile)
Check the config.hpp file in the boost thread directory. When you pull in the ptime stuff it's possibly including a different config.hpp file, which may then define those preprocessor things differently.