Related
I've been able to make a fair amount of progress in trying to add Bazel build files to enable the building of the gennorm2 tool in ICU. Here is my work-in-progress PR using the Bazel target //icu4c/source/tools/gennorm2.
I'm currently getting stuck when running bazelisk build //icu4c/source/tools/gennorm2 --verbose_failures --sandbox_debug with these errors.
They reference functions defined in urename.h. As I understand it, urename.h is also used to rename certain functions by appending a suffix with the version number (_68), but I defined a preprocessor constant U_DISABLE_RENAMING to disable that specific behavior. This only had the effect of changing the names of the undefined function names in the error output, but otherwise not changing it (ex: errors now complain of u_errorName instead of u_errorName_68).
The part that puzzles me is why the error output claims that these symbols are not found. As you can see, the target //icu4c/source/tools/gennorm2 depends on //icu4c/source/common:platform, which in turn depends on //icu4c/source/common:headers, which includes the field hdrs = glob(["unicode/*.h", "unicode/*.h",]), which should be matching
/icu4c/source/common/unicode/urename.h.
In case it helps, this is the verbose log output when running make VERBOSE=1 using the current autotools-based configure + make build on a fresh checkout of ICU.
A teammate was able to take a look and help me reason through the errors and ultimately fix them.
The first thing is to acknowledge that it is indeed a linker error, which can see by noticing the error message references the linker program ld.
This is important because we previously spent time in the wrong place by debugging the compile configs as if the problem happened during the compile phase before the linker phase. (But I learned about one way to debug compile problems is taking the raw GCC command given by --verbose_failures --sandbox_debug and replacing -c with -E and changing the argument of -o to a .txt file in /tmp to save the output what the compiler sees for that file after all the includes are recursively inlined). This means that my attempts to solve the problem by specifying preprocessor defines for the compile-phase were misguided.
The project's documentation on dependencies revealed that I had mis-specified a dependency on one of the targets to specify only the headers (//icu4c/source/common:headers) instead of the relevant definitions and headers (//icu4c/source/common:platform).
After doing that, we solved another problem that was small and interesting. The gennorm2 target depends on code to get the current year (ex: for printing out help messages that include the copyright statement with the year range). As an i18n library, ICU has code to get that, somewhere in //icu4c/source/i18n:icu4ci18n. This creates an excessive amount of code dependencies for an isolated use case (and will cause problems for follow-on work), so we replaced the block of code in gennorm2 calling those calendar year fns (ucal_open, ucal_getNow, ucal_setMillis, ucal_get, ucal_close) with the libc date library function to give us the year as a number, and added linkopts = ["-ldl"] to link in the dl date library.
It there a predefined c++ compiler macro that I can use to tell, whether a file is compiled with "Use Precompiled Headers", "Create Precompiled Headers", "Dont Use Precompiled Headers"?
See #IronMensan 's answer for the purpose of such a macro!
I don't think there is anything, though I certainly understand the desire for one. Whenever I have to build my cross-platform library on a system that dozen't support PCH, it takes forever since a lot of files are pulling in way more than they really need and it would be nice to trim that out. Unfortunately I can't because of how Visual Studio handles PCH. Namely that the inclusion of the PCH must be the first non-comment line of the file. From the way you worded your question, I suspect that you are also working with Visual Studio.
I am not sure if this will work for you but you could try something like this:
#include MY_PCH_FILE
And use
/DMY_PCH_FILE="myfile.h"
on the command line to control what the first include file is. After that you have full control over what gets included and proper header guards along with the optimization in most modern compilers to detect header guards could reduce build times. You can change the definition of the macro for individual file in the build settings of your project, in a similar manor to how you can change the PCH settings for each file.
Though I must admit that I am not sure what you are trying to do and I suspect this is really an XY problem
Visual Studio/MSC does not provide a predefined macro that carries the setting of the /Y[-cdu] compiler switch for inspection from source code.
However, there is a solution to the problem you are trying to solve, i.e. controlling whether or not the first non-comment line of a source file should be #include "<my pch.h>": MSC offers the /FI (Name Forced Include File) compiler switch.
This option has the same effect as specifying the file with double quotation marks in an #include directive on the first line of every source file specified on the command line [...]
This compiler switch can either be specified on the compiler's command line, or on a per-project basis through the IDE's GUI (Project -> Properties: C/C++ -> Advanced: Forced Include File).
With a combination of the /Y[-cdu] and /FI compiler switches you can both control the use and meet the requirements for using precompiled headers, from outside the source code.
In this case, I think you can create manualy yourself the macro.
You can define USE_PRECOMPILEDHDR and FORCED_INCLUDEHDR when you use precompilation like this
#if USE_PRECOMPILEDHDR
#ifndef FORCED_INCLUDEHDR
#include "stdafx.h"
#endif
#else
//..manualy include all your headers
#endif
But as other saying, except if you change for another compiler, you have no reason to use guards for this.
This feature is unlikely to exist. The whole point of precompiled headers is that the headers will be compiled with exactly the same compiler options as when compiling for real. If the compiler were to offer a way for your code to tell the difference, then you could make your code behave differently (at a preprocessor level) depending on whether the compiler is precompiling or actually compiling.
If you're looking to include header files based on whether or not precompiled headers are enabled, you should use an Include Guard instead.
I'm trying to add SVL to my project.
Without it I'm getting hundreds of errors (undefined reference...). After adding -lSVL all errors are gone, but gcc says: "cannot find -lSVL". Everything else (SDL, SDL_TTF, SDL_Mixer...) works fine.
You should inform gcc of the path where libsvl.a is installed, for example:
gcc -lsvl -L/my/path/
Also, pay attention to the case if you work under Linux ("SVL" is different from "svl").
There are two parts to adding an external library; you need to tell the compiler[1] where to find the description of the API (i.e., the header files) and you need to tell the linker where to find the implementation of the API (i.e., the library file(s)).
The list of possible locations of the headers is given by the include path, which with a traditional compiler is added to with the -I option. It takes a directory name to add; the directory is one extra place the compiler will look for header files.
The list of possible locations of the library is given by the link path. It's just like the include path, but is added to with -L. Note that you can also (at least normally) give the full path to the library directly on the command line, but this isn't particularly recommended because it tends to embed more information in the executable than is really needed.
The syntax for MSVC is recognizably similar IIRC.
If you're using an IDE, you'll probably have to set these things in the project options, but as long as you remember that you need to set both include and library paths, you'll be able to find your way through.
[1]Strictly, you're telling the preprocessor, but the preprocessor's output is virtually always directed straight into the compiler proper.
Suppose I have files a.cpp and b.cpp and I get warnings in a.cpp and an error in b.cpp. I fix the error in b.cpp and recompile -- since Visual Studio doesn't have to recompile a.cpp, it doesn't remind me of the warnings it found before.
I'd like to somehow have the warnings persist; however, I don't want it to treat warnings as errors (I'd like it to still compile/run even with warnings). Is this possible?
You could go into the project settings and set all warnings as errors in the C/C++ tab (category: General).
Essentially, you're out of luck. The C++ compilation will discard all of the errors and warnings. Because it only recompiles .CPP files that have a missing .OBJ file (i.e. the ones that had errors and failed last time), you'll only see the errors.
You have a few options. Off the top of my head:
Write a macro that responds to the build complete event. If it sees any warnings, it could delete the .OBJ file. The .CPP file would be compiled again next time. Unfortunately, this means that your program may not run without recompilation.
You could write a macro that works the other way: on build start, look to see if there are any warnings, and then delete the .OBJ file.
Write a VS addin that remembers warnings until the .CPP file is compiled again.
As Hernan already said, add a custom build step that makes a copy of the intermediate file that contains the build results (warnings). Not sure how to do naming for this, but you could create a bat file that gets called as a custom build step.
Why you would want to save warnings is beyond me. Treat them as errors, or ignore them or pragma/disable them.
Rebuild your project or recompile only the a.cpp file. Warnings are output by the compiler, so you won't get warnings for files not included in the current compilation.
You can save your current build output going to the Output pane and pressing Ctrl+S (defaults to output-build.txt if I don't remember bad.)
In your project settings I think build output messages can be saved on files. Check it and tell your results.
Cheers
Given that you don't want to recompile the files that cause the warning, one option you might have is to write a small utility that filters the output of the compiler for warnings and writes them to the .cpp file as a //TODO comment.
Then the IDE will place them in the todo list.
I'm not aware of anything that does this out of the box, but it probably wouldn't be too difficult to whip up.
If you don't want the utility mucking around with the actual source files (and I'm not sure I would), you might want to have it write the //TODO comments to a dummy 'todo.cpp' file and have that file in the project. Then they'll show up in the todo list and since the file is nothing but comments, it won't affect the build. Just make sure the utility is smart about not adding duplicates to the list. A macro could be written to take you from the todo.cpp line to the corresponding actual location of the warning.
I'd strongly recommend running with warnings as errors as much as possible, and certainly in all the code you're writing yourself. It is way eaiser to fix the warnings here and now, than wait until later and try to do them all in one pass.
There are several reasons why you want to run with warnings as errors:
The majority of warnings actually indicate that there is a problem with your code.
If you have a lot of warnings, you won't notice if a new one appears in the middle. I've seen this happen a lot.
If there is a warning which you think is bogus or you for some reason just can't fix it right away, you can switch it off. Use the /w option or suitable #pragma. Note that you can switch it of for only a particular file, or even in a particular place in your code. If you still want a notice when compiling, but a #pragma message there.
If there is code which is outside of your control, but you just have to compile it into your program, switch of warnings for that particular module or source file, or even run it without /WX. Chances are you aren't modifying the code anyway, so point 2 is probably not so relevant.
I really cannot see any valid reasons for not running with /WX (or -Werror).
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.