System include not completely consistent across distributions - c++

Short question
How should I deal with needing different includes on different distributions?
More details
In some C++ code, I am including ioctl like this:
#include <sys/ioctl.h>
And from that I use different things, including TCSETS2. Following the includes of sys/ioctl.h on Arch Linux, I found that TCSETS2 is defined in asm-generic/ioctls.h. So far so good.
Now, when building on Alpine Linux, it complains about TCSETS2:
error: 'TCSETS2' was not declared in this scope
Looking at the includes again, TCSETS2 is also defined in asm-generic/ioctls.h. However, this time sys/ioctl.h does not end up including generic/ioctls.h.
How should I deal with that? Should I include both, hoping that it does not break the compilation on some distributions? Something like below?
#include <asm-generic/ioctls.h>
#include <sys/ioctl.h>
Or is it bad practice?

TCSETS2 is undocumented here
suggesting that it's an implementation specific feature. From the comments, switching to TCSETS which is in the documentation resolved the issue.

Related

Arduino: Why same library is included multiple times

I couldn't rationalize the reason that why (dependency) library is required when this very library has already been included in the required library itself. For example:
If I want to use SD.h, in the example code, SPI.h is required:
#include <SD.h> // SPI.h is already included in SD.h
#include <SPI.h> // why include it here once more
...
however, if we go into the SD.h and related files, the SPI.h has already been included.
and this is not the only one, ILI9488.h, XPT2046_touchscreen.h, etc. all requires SPI.h when include them.
I have found someone on another topic said at arduino.cc that "if this is not included in the sketch, it (SPI.h) will not be compiled, besides, it is good to tell others that SPI.h is a dependency of the library you included" and I found the last part is especially unreasonable.
Maybe I understood him wrong, but it compiles, and they all worked great without including the SPI.h, of course, provided that I never used any of the methods from SPI.h.
However, I am sure I am missing something. I just don't know it and it haunting me ever since my code is working without including the SPI.h.
I appritiate if anyone can provide my some insight about this. Thanks in advance.
Arduino doesn't have makefiles so the Arduino builder scans for #include directives to add the required libraries.
Old version of the build system required to list all libraries in the main ino file. That is why the examples list all the main header files of the libraries used.

Including <thread> results in the following compile error: 'fabsl': is not a member of '`global namespace'

For the long time, standard libraries were giving me headache by throwing compilation errors simply by including them. For the long time, I've gone around it by reimplementing the parts that I needed, or with some #define for cstdio.
Now I need to include the library, and I don't really see any ways around it. Yet again, I see no way of doing it either - any clues of dealing with that? I have tried the following:
#ifndef _CRT_FUNCTIONS_REQUIRED
#define _CRT_FUNCTIONS_REQUIRED 1
#endif // !_CRT_FUNCTIONS_REQUIRED
#include <thread>
And a few such variations, but to no avail.
EDIT - fixed:
I had created a "Math.h" header, breaking any headers relying on the standard C++ library "math.h". After renaming the header (and it's references) the code compiled.
I had created a Math.h header file. Renaming it fixed the problem.
It appears to be a good idea to avoid using file names from the C++ standard library, who would've said it.

'strtoll' and many others "not a member of 'std'"

strtoull,strtof,strtold,vsnprintf,wcstoll,wcstoull,wcstof, and wcstold are not members of 'std.' The problem is I don't use any of these functions. I didn't even know they existed. they are in file basic_string.h, which I also didn't know I was using. I'm using VS2015 so I assume I am compiling using the VSC++ 14.0 compiler.
I see that there over a dozen similar questions but I can only find two common errors: not using the C++11 flag and not #includeing . I have had the C++11 flag set and #include <algorithm> changes nothing. this question makes me curious,though. I thought the order of #includes didn't matter. I tried system libraries <> first and 3rd party libraries second "" and also vice-versa and observed no difference.
I also tried #include "stdafx.h" as some other answers indicated, but no such file exists.
not sure what to include here because I finally got to the point where the IDE identifies no errors in my code. again, all the issues are in "basic_string.h." here are my includes:
#include <iostrream>
#include <string>
#include <cstring>
#include <sstream>
#include <map>
#include "curl/curl.h"
#include "curl/easy.h"
this may be a continuation of my other question here, which I will update now.
edit 1: I have included <cstdlib>,<cstdio>,and<cwchar> and I see no difference. I'm curious why it's having issues with functions I've never used in files I've never touched.
I totally forgot I ran a repair on VS2015 yesterday and here are the results. I'm not sure if these are optional modules or core issues or what. "Windows Software Development Kit" sounds important but I am not developing for a windows machine(though I am developing on Win7).
edit 2: someone asked for minimal reproducible code. here is the whole file sans comments:
#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <sstream>
#include <map>
#include <cstdio>
#include <cwchar>
int main(int argc, char *argv[])
{
return 0;
}
just realized I don't need all the includes for nothing(because i commented all functional code out) so I will now see which one is causing the issue.
edit 3 : cstring,cstdlib,cstdio, cwchar, and the two curl headers are the only headers that will not cause this issue. I can include all six of them at once without issue. any other #include that was mentioned in the OP or the previous edit will cause the same ...is not a member of 'std'error. However, I don't think I had any of the <c...>included before I started having this issue.iostream,string,sstream,map each (individually even) cause this issue. are we still looking at a complete VS2015 reinstall?
edit 4: As one user suggested, I tried to make a new project but this is what happened. I was really hoping we wouldnt get to this point because I'm not sure how much you all will be able to help. Basically,we have some complicated build setup which I don't understand. The other guy who works here also does not understand the setup. The one person who knows is out on paternity leave. I'm developing on one machine and building/debugging on a server. However, I was poking around the settings and I saw a different diagram that has a second server in the mix and I'm not sure how that plays into it. After that, it is deployed to a different machine. Anyway I selected the same options as the current project but I can't even create a blank one. I'm not sure if this failure is because of this complicated system or because my VS2015 is messed up. Either way I can't fix this as it is so I think I will work on repairing VS2015 (which already had issues once) while monitoring this thread to see if this new project error reveals something important. thanks a lot to all who helped so far
edit 5: I'm taking next week off. I won't be able to give any updates till the 3rd for anybody who still cares. I'm going to repair and then reinstall
Those functions are in the namespace std if you include the correct standard headers, which are <cstdlib>, <cstdio> and <cwchar>. "basic_string.h" is not a standard header; it is probably some implementation specific header. "stdafx.h" is what Visual Studio uses for precompiled headers (it's not in the standard either) and the order in which you include headers can matter although it usually shouldn't.
I see that there over a dozen similar questions but I can only find... not #includeing
That appears to be the problem.
In order to use standard functions, the header which declares those functions must be included. The listed functions cannot be used because the corresponding headers haven't been included.
For example, strtoull is declared in <cstdlib>, which has't been included according to your quoted list of includes.
The problem is I don't use any of these functions. I didn't even know they existed. they are in file basic_string.h
If the error indicates that basic_string.h uses those functions, and that's the list of headers that basic_string.h includes, then basic_string.h is buggy.
I'm curious why it's having issues with functions I've never used in files I've never touched.
You either use basic_string.h, or you use some header that in trurn uses basic_string.h. The error message should tell you how the inclusion takes place.
I have ... #include <algorithm>
Including <algorithm> lets you use the declarations from that header. It doesn't let you use declarations from other headers.
I also tried #include "stdafx.h" as some other answers indicated, but no such file exists.
If your project is configured to use pre-compiled "stdafx.h", then you must include it. If it is not configured to use it, then you must not include it. Pre-compiled headers must be included before anything else in your file.
it was a problem with my Include directories in VisualGDB Properties-->Makefile settings. I was adding a new directory for each library I got. I reinstalled VS2015, but that did nothing because the culprit was a project option. I copied the default* include directories and that was it.
*someone on my team provided me with a list of the default include directories

In xcode when including cmath get error: '::acos' has not been declared, etc

I get the following errors when trying to build a small and simple project that includes <cmath> in Xcode:
cmath: '*' has not been declared
'::acos' has not been declared
In file included from /Xcode4/Projects/libraryLAFMath/Classes/libraryLAFMath.cp
In file included from /Xcode4/Projects/libraryLAFMath/Classes/libraryLAFMath.h
'::acos' has not been declared in /Xcode4/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator4.1.sdk/usr/include/c++/4.2.1/cmath
...
The error log complains about all the other math functions as well, sin, pow, etc, not just acos. I looked inside cmath source code and it references the globally defined corresponding math functions from math.h, ie ::acos etc. Since the root error complains about the non-existance of ::acos one would assume that math.h can't be found, but a) it exists, and b) I'd get a different error complaining that math.h can't be found.
The source code is as follows:
libraryLAFMath.cp:
#include "libraryLAFMath.h"
libraryLAFMath.h:
#include <cmath>
struct libraryLAFMath {
void test() {
double a = std::acos(0);
}
};
Now, I have another project from an outside source that uses cmath and compiles fine. I tried comparing build settings between these two projects but they are pretty much the same. I am using LLVM GCC 4.2 compiler, but get similar result when using GCC 4.2, so it's not a compiler settings issue I believe.
I'm new to Xcode development and any help is appreciated.
There is a file I have in my project named Math.h with a capital M, and it seems the compiler gets confused and tries to include Math.h instead of math.h.
I posted this answer on an alternate thread on the topic, but thought it worth including here as well:
I had this problem - it was driving me crazy but I tracked down the cause, and it was a little different than what I've seen reported on this issue.
In this case, the general cmath header (or math.h - the error and solution occur in C++ or C) had architectural environment switches to include architecture specific math subheaders. The architecture switch (environment variable) hadn't been defined, so it was punting and not actually including the headers that truly defined the math functions.
So there was indeed a single math.h or cmath.h, and it was included, but that wasn't enough to get the math functions. In my case, rather than define the architectural variable, I instead found the location of the correct sub math headers and added them to my compile path. Then the project worked!
This seems to be an issue that comes up a lot when porting Linux projects to OS-X. I'd imagine it might occur anytime a project was moved betwee platforms such that the standard library headers are arranged differently.

How should I detect unnecessary #include files in a large C++ project?

I am working on a large C++ project in Visual Studio 2008, and there are a lot of files with unnecessary #include directives. Sometimes the #includes are just artifacts and everything will compile fine with them removed, and in other cases classes could be forward declared and the #include could be moved to the .cpp file. Are there any good tools for detecting both of these cases?
While it won't reveal unneeded include files, Visual studio has a setting /showIncludes (right click on a .cpp file, Properties->C/C++->Advanced) that will output a tree of all included files at compile time. This can help in identifying files that shouldn't need to be included.
You can also take a look at the pimpl idiom to let you get away with fewer header file dependencies to make it easier to see the cruft that you can remove.
PC Lint works quite well for this, and it finds all sorts of other goofy problems for you too. It has command line options that can be used to create External Tools in Visual Studio, but I've found that the Visual Lint addin is easier to work with. Even the free version of Visual Lint helps. But give PC-Lint a shot. Configuring it so it doesn't give you too many warnings takes a bit of time, but you'll be amazed at what it turns up.
There's a new Clang-based tool, include-what-you-use, that aims to do this.
!!DISCLAIMER!! I work on a commercial static analysis tool (not PC Lint). !!DISCLAIMER!!
There are several issues with a simple non parsing approach:
1) Overload Sets:
It's possible that an overloaded function has declarations that come from different files. It might be that removing one header file results in a different overload being chosen rather than a compile error! The result will be a silent change in semantics that may be very difficult to track down afterwards.
2) Template specializations:
Similar to the overload example, if you have partial or explicit specializations for a template you want them all to be visible when the template is used. It might be that specializations for the primary template are in different header files. Removing the header with the specialization will not cause a compile error, but may result in undefined behaviour if that specialization would have been selected. (See: Visibility of template specialization of C++ function)
As pointed out by 'msalters', performing a full analysis of the code also allows for analysis of class usage. By checking how a class is used though a specific path of files, it is possible that the definition of the class (and therefore all of its dependnecies) can be removed completely or at least moved to a level closer to the main source in the include tree.
I don't know of any such tools, and I have thought about writing one in the past, but it turns out that this is a difficult problem to solve.
Say your source file includes a.h and b.h; a.h contains #define USE_FEATURE_X and b.h uses #ifdef USE_FEATURE_X. If #include "a.h" is commented out, your file may still compile, but may not do what you expect. Detecting this programatically is non-trivial.
Whatever tool does this would need to know your build environment as well. If a.h looks like:
#if defined( WINNT )
#define USE_FEATURE_X
#endif
Then USE_FEATURE_X is only defined if WINNT is defined, so the tool would need to know what directives are generated by the compiler itself as well as which ones are specified in the compile command rather than in a header file.
Like Timmermans, I'm not familiar with any tools for this. But I have known programmers who wrote a Perl (or Python) script to try commenting out each include line one at a time and then compile each file.
It appears that now Eric Raymond has a tool for this.
Google's cpplint.py has an "include what you use" rule (among many others), but as far as I can tell, no "include only what you use." Even so, it can be useful.
If you're interested in this topic in general, you might want to check out Lakos' Large Scale C++ Software Design. It's a bit dated, but goes into lots of "physical design" issues like finding the absolute minimum of headers that need to be included. I haven't really seen this sort of thing discussed anywhere else.
Give Include Manager a try. It integrates easily in Visual Studio and visualizes your include paths which helps you to find unnecessary stuff.
Internally it uses Graphviz but there are many more cool features. And although it is a commercial product it has a very low price.
You can build an include graph using C/C++ Include File Dependencies Watcher, and find unneeded includes visually.
If your header files generally start with
#ifndef __SOMEHEADER_H__
#define __SOMEHEADER_H__
// header contents
#endif
(as opposed to using #pragma once) you could change that to:
#ifndef __SOMEHEADER_H__
#define __SOMEHEADER_H__
// header contents
#else
#pragma message("Someheader.h superfluously included")
#endif
And since the compiler outputs the name of the cpp file being compiled, that would let you know at least which cpp file is causing the header to be brought in multiple times.
PC-Lint can indeed do this. One easy way to do this is to configure it to detect just unused include files and ignore all other issues. This is pretty straightforward - to enable just message 766 ("Header file not used in module"), just include the options -w0 +e766 on the command line.
The same approach can also be used with related messages such as 964 ("Header file not directly used in module") and 966 ("Indirectly included header file not used in module").
FWIW I wrote about this in more detail in a blog post last week at http://www.riverblade.co.uk/blog.php?archive=2008_09_01_archive.xml#3575027665614976318.
Adding one or both of the following #defines
will exclude often unnecessary header files and
may substantially improve
compile times especially if the code that is not using Windows API functions.
#define WIN32_LEAN_AND_MEAN
#define VC_EXTRALEAN
See http://support.microsoft.com/kb/166474
If you are looking to remove unnecessary #include files in order to decrease build times, your time and money might be better spent parallelizing your build process using cl.exe /MP, make -j, Xoreax IncrediBuild, distcc/icecream, etc.
Of course, if you already have a parallel build process and you're still trying to speed it up, then by all means clean up your #include directives and remove those unnecessary dependencies.
Start with each include file, and ensure that each include file only includes what is necessary to compile itself. Any include files that are then missing for the C++ files, can be added to the C++ files themselves.
For each include and source file, comment out each include file one at a time and see if it compiles.
It is also a good idea to sort the include files alphabetically, and where this is not possible, add a comment.
If you aren't already, using a precompiled header to include everything that you're not going to change (platform headers, external SDK headers, or static already completed pieces of your project) will make a huge difference in build times.
http://msdn.microsoft.com/en-us/library/szfdksca(VS.71).aspx
Also, although it may be too late for your project, organizing your project into sections and not lumping all local headers to one big main header is a good practice, although it takes a little extra work.
If you would work with Eclipse CDT you could try out http://includator.com to optimize your include structure. However, Includator might not know enough about VC++'s predefined includes and setting up CDT to use VC++ with correct includes is not built into CDT yet.
The latest Jetbrains IDE, CLion, automatically shows (in gray) the includes that are not used in the current file.
It is also possible to have the list of all the unused includes (and also functions, methods, etc...) from the IDE.
Some of the existing answers state that it's hard. That's indeed true, because you need a full compiler to detect the cases in which a forward declaration would be appropriate. You cant parse C++ without knowing what the symbols mean; the grammar is simply too ambiguous for that. You must know whether a certain name names a class (could be forward-declared) or a variable (can't). Also, you need to be namespace-aware.
Maybe a little late, but I once found a WebKit perl script that did just what you wanted. It'll need some adapting I believe (I'm not well versed in perl), but it should do the trick:
http://trac.webkit.org/browser/branches/old/safari-3-2-branch/WebKitTools/Scripts/find-extra-includes
(this is an old branch because trunk doesn't have the file anymore)
If there's a particular header that you think isn't needed anymore (say
string.h), you can comment out that include then put this below all the
includes:
#ifdef _STRING_H_
# error string.h is included indirectly
#endif
Of course your interface headers might use a different #define convention
to record their inclusion in CPP memory. Or no convention, in which case
this approach won't work.
Then rebuild. There are three possibilities:
It builds ok. string.h wasn't compile-critical, and the include for it
can be removed.
The #error trips. string.g was included indirectly somehow
You still don't know if string.h is required. If it is required, you
should directly #include it (see below).
You get some other compilation error. string.h was needed and isn't being
included indirectly, so the include was correct to begin with.
Note that depending on indirect inclusion when your .h or .c directly uses
another .h is almost certainly a bug: you are in effect promising that your
code will only require that header as long as some other header you're using
requires it, which probably isn't what you meant.
The caveats mentioned in other answers about headers that modify behavior
rather that declaring things which cause build failures apply here as well.