Would like to know if a lot of warning can increase the website build time using 'task: VSBuild#1' and 'msbuildArgs' as input
Would like to know if a lot of warning can increase the website build time using 'task: VSBuild#1' and 'msbuildArgs' as input
Agree with KrzysztofMadej. A large number of warnings will increase the compiler's compilation time. When the compiler encounters a warning, it needs to do some simple actions and warning positioning and analysis, so that it can give a meaningful warning prompt in the log.
For a scenario we often encounter, when compiling the project to reference the assembly, the correct compilation will directly find the matching assembly, but if the assembly is not found, the compiler will try to go to some msbuild/extension, framework folder to search for the required dll files. These additional operations will undoubtedly increase the time of the compiler.
Is there any property for 'msbuildArgs' through which we can suppress
them?
You could use msbuildArgs /p:WarningLevel=X supress the warning level for those C# warnings (e.g. CS0618):
Warning
Level Meaning
-------- -------------------------------------------
0 Turns off emission of all warning messages.
1 Displays severe warning messages
2 Displays level 1 warnings plus certain, less-severe warnings, such
as warnings about hiding class members
3 Displays level 2 warnings plus certain, less-severe warnings, such
as warnings about expressions that always evaluate to true or false
4 (the default) Displays all level 3 warnings plus informational warnings
For those MSBuild warnings, it can't be suppressed.
You could check this thread for some more details.
Related
We have a large C++ project with warnings as errors enabled. We would like to deprecate some old APIs, and naturally our first thought was to turn to the [[deprecated]] language feature. This however triggers a -Wdeprecated-declarations warning, which is turned into an error and fails the build.
Now, we know we can disable the error for that particular warning via -Wno-error=deprecated-declarations. But still the build log would be full of compiler warnings, making it much harder to spot true compiler errors.
I wonder then if people have better solutions to deal with C++ deprecations in practice, in real-world large projects?
Well, you can't have your cake and eat it too: If you don't want usage of deprecated functions to throw an error (which can be fine) but neither to see the warnings - why deprecate them in the first place ?
You can suppress single warnings by number (see here for a VC++ solution: https://stackoverflow.com/a/7159392/20213170),
but the correct way is really just getting rid of the deprecated functions calls and update you API.
This is a naive approach, but couldn't you just do something like :
#ifdef WARNING_DEPRECATED_ON
# define ATT_DEPRECATED __attribute__ ((deprecated))
#else
# define ATT_DEPRECATED
#endif
You can locally have one commit where you deprecate the api, verify that commit doesn't build, then have another commit that removes the uses of the deprecated api.
If you can't push a failing build, at that point you can squash those two local commits into one "remove deprecated api" commit.
But still the build log would be full of compiler warnings, making it much harder to spot true compiler errors.
This isn't completely true. There are a whole bunch of -Wdeprecated-declarations warnings, but any other error fails the build. It's not hard to ctrl-f "error:" in the build log.
I have heard from someone that big projects with a large number of warnings in code builds significantly slower than ones with a small amount of warnings (of course, it is intended that the compiler's set to have high level warning-sensitivity).
Is there any reasonable explanation, or maybe anyone can share their experience about this topic?
On GCC compiler (e.g. gcc for C or g++ for C++) warnings do take a small amount of CPU time. Use e.g. gcc -ftime-report if you want a detailed report of compiler timing. Warning diagnostics do depend upon the optimization level.
But optimizations (especially at high level, like -O2 or more) take much more time than warnings. Empirically, optimized compilation time is proportional to the compilation unit size and to the square of the size (e.g. in number of Gimple instructions, or in lines of C code) of the biggest function. So if you have huge functions (e.g. some function of ten thousand lines in some generated C code) you may want to split them into smaller pieces.
In the early days of MELT (a GCC plugin and GCC experimental branch -GPLv3+ licensed- implementing a DSL to extend GCC, that I have developed and am still working on), it generated huge initialization functions in C (today it is less the case, the initialization is split in many C++ functions; see e.g. gcc/melt/generated/warmelt-base.cc from the MELT branch of GCC as an example). At that time, I plotted the compilation -O2 time versus the length of that initialization function and measured the compilation time vs its length. You could also experiment with manydl.c code. Again, the square of biggest function length is an experimental measure, but might be explained by register allocation issues. Also, J.Pitrat also observed that huge generated C functions -by his interesting CAIA system- are exhausting the compiler.
Also, warnings are output, and sometimes, the IDE or the terminal reading the compiler output may be slowed down if you have a lot of warnings.
Of course, as commented several times, compiler warnings are your friends (so always compile with e.g. gcc -Wall). So please improve your code to get no warnings at all. (In particular, initialize most of your local variables - I usually initialize all of them; since the compiler could optimize by removing some initializations if it can be proven that they are useless).
BTW, you could customize GCC with e.g. MELT to add your own customized warnings (e.g. to check some coding rules conformance).
Also, in C++ with weird templates, you could write a few dozens of lines which take many hours to be compiled (or even crash the compiler because of lack of memory, see this question).
NB. In 2019, GCC MELT is dead, its domain gcc-melt.org disappeared but the web pages are archived here.
It depends a lot on what the warnings actually are.
For an example, if there are lots of "variable is unused" warnings and "condition in 'if' is always true/false" warnings, then that may mean there's a lot of unnecessary code that the compiler has to parse and then remove during optimisation.
For other warnings there may be other consequences. For example, consider a "variable is self initialising" warning caused by something like int i = i;. I'd imagine this could add a whole pile of complications/overhead (where the compiler attempts to determine if the variable is "live" or can be optimised out).
This will likely depend extensively on the compiler, and how it is implemented.
That being said, there are two sure sources of slow-down:
Printing the warnings themselves is a non-trivial task, it requires extensive formatting, potentially accessing back the file, plus all those notes (macro expansion, template instantiation), and finally pushing that to an I/O device.
Emitting said warnings, with all those macro expansion and template instantiation data, might be non-trivial too. Furthermore, if collected first and only emitted at the end of the compilation process (instead of being streamed as they are produced), then the growing memory consumption will also slow you down (requiring more pages to be provided by the OS, ...)
In general, in terms of engineering, I do not expect compiler writers to worry much about the cost of emitting diagnostics; as long as it is a reasonable cost, there seems to be little incentive in optimizing a couple milli-seconds when a human intervention is going to be required anyway.
Who cares if your build takes 10% longer due to the compiler printing tons of warnings? The problem is the code you're being warned about, not the extra time it takes. Besides, 10% is probably a huge overestimate for the overhead of printing even very large numbers of warnings.
I've been wondering if it is possible to enable any debug checks for libc++. One of my favorite things about MSVC's STL is that it catches some otherwise hard to find bugs right from the get go (though I wish it were easier to disable for speed). After peeking in the headers I tried:
#define _LIBCPP_DEBUG_LEVEL 2
However, this leads to build errors ('__get_db undeclared'). Any insights on whether this is a work in progress, or if there is a different expected way to enable these checks?
This is definitely a work in progress.
There's a (very old) status page here that I need to update.
The idea is that users will interact with it by setting the preprocessor symbol _LIBCPP_DEBUG
Just defining it will give basic tests, setting it to a number > 1 will give more extensive tests.
However, as you have found, it is currently non-functional.
It appears some progress was made on this in the meantime. At least there is some documentation now that doesn't state that the debug mode is horribly broken.
As stated in the docs I link, the debug mode shall be controlled by defining _LIBCPP_DEBUG to either 0 or 1; the macro _LIBCPP_DEBUG_LEVEL appears to be some internal switch.
However, looking at question like this one, spurious compilation errors can and do still happen.
Visual C++ features #pragma warning that among other things allows to change the warning level of a specific warning. Say warning X has level 4 by default, then after
#pragma warning( 3, X )
it will have level 3 from that point.
I understand why I would temporarily disable a warning, turn a warning into an error or turn on a waring that is off by default. But why would I change a warning level?
I mean warning level of a specific warning works together with the compiler "warning level" option /W, so I currently can't imagine a setup in which I would want to change a level of an individual warning since the warning being emitted or not will depend on the project settings.
What are real-life examples of when I really need to change a warning level of a specific warning in C++?
When you want to run on level 3 or 4, but you want to see/not see a specific message, you can change its level. Sure, the pragma might have no effect if the warning level isn't what you think, but that's life with pragmas.
It is much easier to take the one or two level 4 warnings you want detected and use the pragma to bring them into level 3 than it is to use /W4 and disable (/Wd####)the all the warnings you don't care about.
An example of where I use this is error C4996 where I move it from being a level 3 warning to level 4. For instance, the VS compiler warns that sprintf may be unsafe and suggests you use the non-portable sprintf_s function instead. You can get lots of these warnings and rather than wading through all of these to find the real errors, I prefer to just prevent them being issued.
I know I could define a macro for sprintf (and loads of other functions) instead, which would maintain portability, and strictly that should be done, but in a large project, tracking down and fixing all these warnings is some effort, for probably very little return.
In some cases when you are working with legacy code and due a newer compiler becoming more sensitive you may want to turn down the warning level for those modules to avoid thousands of warnings. Also in some cases when you interact with generated code you would like to turn down the warning level. e.g. ANTLR generates C-code that you treat as a black box so you don't want warnings then.
My experience is to treat warnings and errors and strive to produce code without warnings. I know that this might seem like a stupid or overly strict approach, but it really does pay off in the long run. Trust me!
I've inherited a large C++ codebase for several Windows applications that successfully is in use by many customers.
The codebase is large, >1mill LOC.
The codebase has a history of 15+ years.
The codebase is in some areas dominated by C programming style and/or not very modern C++ style, e.g. not using Standard C++ collections and algorithms.
The codebase has unfortunately only been compiled with warning level 2 (/W2 in Visual C++). I would like to increase to level 3 (/W3) to increase security and prepare for 64-bit.
The most problematic point in the increase to warning level 3 are the many warnings received involving signed/unsigned mismatches and I recognize that it will be a very large task to resolve all those for the existing codebase.
What would be a good approach to ensure and enforce that new code committed to the codebase are compiled with the increased warning level?
In more general terms the question could be rephrased to how you enforce increased programming quality into new committed code. If you don't do anything, new code has, in my experience, a tendency to be affected and styled similar to existing code, rather than being improved to more modern standards.
I would even go as far as going to warning level 4 (/W4).
Since you're using Visual Studio, it's quite easy to suppress bothersome warnings like signed vs unsigned comparision:
#pragma warning(disable:NNNN)
Where NNNN is the number of your warning. Now put all those disabled warnings in a header file (say, "tedious_warnings.h") and force-include that header file everywhere - Project Properties -> C/C++ -> Advanced -> Forced Include File.
Later on, or better, ASAP, remove the force include and work your way through the warnings, since most of them are quite easy to fix (size_t instead if int, etc).
Perhaps you could create new code in separate DLLs or Libraries. That way you can enforce your higher warning level (and I would say go for /W4 and be prepared to turn off a few of MS's dafter warnings rather than settle for /W3) without having to wade through 1000s of warnings from the old code.
Then you can start working on cleaning up the old code, a bit at a time, when there is time -- making sure you have suitable unit tests in place to avoid breaking it by accident of course.
you may not like the answer...
remove the warnings by correcting the issues.
i'm very picky about warning levels; even i ignore warnings which i don't need to correct, especially when the warning level is high and build times are high. meanwhile, new ones slip in (in large codebases). removing them incrementally doesn't work very well, in my experience -- they tend to get ignored if the noise is too high, or it is not enforced.
you need to reduce the warning noise so people can see the warnings they add (at the warning level you desire).
to reach the compliance level you want/need, make it a priority.
if you don't know whether the conversions/comparisons are valid, you can always use a template function with an error action (assert, throw, log) to perform the logic when in doubt.
it can be a slow/tedious process, but it's also a good way to learn the codebase.
i typically start at the libraries highest in the tree, or those which are reused most often. once a library meets a standard, maintain that standard.
If you are going to make code modifications as a result of the new stricter warning level, write adequate tests that protect against introducing new problems/bugs. Write the tests using the new warning level. Do this before you start to change the codebase and verify correct functionality. Then you can rerun the updated code against the same test case.
I would use an incremental approach.
The first step would be to modify the old files and add the required pragma action to deactivate the warning in the code.
The second step is to build a commit-hook that will refuse any committed file that contain the specific pragma pattern that discards all those "old" warnings.
This means that any modified file should be warning free.
However, let us be frank, developers always find ways to game the system.
My approach has been to go with the highest warning level you can and fix all the warnings that come up - you may even find some bugs in the process.
You should set this up using vsprops files so that all projects are compiled with the same warning level and any changes you make to these settings change in all projects.
A more incremental approach is to go with the highest warning level you can and then disable almost all warnings, leaving you with only a small number of warnings to consider at once - fix those and then switch on another warning, and so on until you are free of warnings.