Does adding many -isystem include directives slow down the compilation process significantly? - c++

For our software project, we have around 15 third party library dependencies. We suppress the warnings in these third party libraries using the -isystem include directive.
Our software project consists of more than 10 executables and libraries, each having dependencies on a subset of the third party libraries. We compile with clang on mac.
An easy way to disable all third party warnings for all projects in our build system is to include all third party libraries in all projects with -isystem.
The alternative is to separately define for each of our projects the -isystem directive. This is more work to set up and will blow up the configurations of all project files, but only the third party libraries that are actually used are included.
I'd prefer to go with the first option because it's not much work, but I am not sure if this will significantly slow down the compilation process?

This flag will slowdown only standard headers search because prior each standard header is found it will also search it in your directories. So, that it depends on how many such directories you add and how many standard headers you use. For each standard header the impact will be a summ of:
time ls YOUR_DIR >> /dev/null 2>&1
for each your added directory.

Related

What is the proper way to include a source library in a Visual Studio C++ project?

Right now I'm trying to create my first "real" project in C++ using Visual Studio 2019. I need to include a third-party library as a dependency. The instructions on the project homepage simply recommend to include all source/header files directly into the project. My understanding is that it's a bad practice, since the end result would look quite ugly in any VCS.
Thankfully, the library author also provided build scripts that call cl, lib and link with appropriate arguments and produce the coveted foo.lib. I added that file to dependencies in linker options and after some haranguing with compiler/linker options finally got it running.
To my distress, I realised that I've done all those manipulations in Release configuration, which prevented me from using the debugger. I then built the library with /MDd, fixed some compiler options... and got a bizarre compile-time error in vcruntime.h ( fatal error C1189: #error: _HAS_CXX17 and _HAS_CXX20 must both be defined, and _HAS_CXX20 must imply _HAS_CXX17).
At this point, I knew I was doing something terribly wrong, since including a simple library should't require so much manual knob-tweaking. What is the right, canonical way of including third-party dependencies in Visual Studio (and C++ in general)? Assuming the dependency isn't available on Nuget, vcpkg or somesuch.
As I understand from the stuff you did was on Windows. First of all I would recommend you try a linux distro. In windows it is possible to get lib files running, but not easy. It would help if you could send me a link to the library you are using.
The usual approach is to just stick those sources in their own directory and their own Visual Studio project (not solution). This can still build a foo.lib. You won't need many options for this.
Next, you just tell Visual Studio that your own project depends on that other project, and it will then link foo.LIB for you.
Having said that, it sounds like you try to build your two projects with different settings for the C++ version. VS2019 has good support for C++17 and experimental support for C++20, so you can choose. But you need to choose consistently for all your projects.
In larger solutions you can us a .vsprops file for that, which is like an #include for project files. A bit overkill when you have two projects, a lifesaver when you have 150.
It varies a bit how you include 3rd party libraries, sometimes 3rd party libraries have an installation and install themselves like under Common Components sometimes you have to do it manually.
E.g. YourSolution/3rdParty/foo/include
YourSolution/3rdParty/foo/lib
YourSolution/3rdParty/foo/lib/release
YourSolution/3rdParty/foo/lib/debug
Sometimes the libraries have different names then they may be in the same folder.
Once you have that structure go to your project's properties C/C++ and add the include under Additional Include Directories make sure you have configuration "All Configurations" here. Then go to Project properties/Linker/Input and the dependency for Debug Configuration and for the Release Configuration - since usually they are different libraries per configuration. e.g. release/foo.lib and debug/foo.lib (foo.lib foo-d.lib or whatever they are called).
Use the macros to make sure you get the right locations so that they are relative to your solution and project. It is not good having absolute paths. E.g. $(SolutionDir)3rdparty\foo\include
Disclaimer : I am not sure this is the "optimal" way to do it but that is the way I do it.

Is it correct to manually copy header .hpp files into my project_root/boost library?

I was reading the documentation and found it quite vague:
To compile anything in Boost, you need a directory containing the boost/ subdirectory in your #include path.
Since all of Boost's header files have the .hpp extension, and live in
the boost/ subdirectory of the boost root, your Boost #include
directives will look like:
#include <boost/whatever.hpp>
or
#include "boost/whatever.hpp"
depending on your preference regarding the use of angle bracket
includes.
Am I supposed to always create a subdirectory named "boost" in my project root and then manually copy each .hpp file I need from my boost installation/header directory into the project_root/boost directory?
I could also see telling Eclipse to automatically scan my boost root installation/include directory for the headers, thus avoiding the manual copy. Also, I could see making a soft link to the boost root installation/include directory into the project boost folder so as to include everything without having to make a single manual copy.
One difference I see is including the boost header files in my projects versus not including them in my project and referring to them externally
I am not sure which of these strategies is right. Which is the best practice here?
The correct option for smallish development projects is probably the one you suggest here:
"I could also see telling Eclipse to automatically scan my boost root installation/include directory for the headers, thus avoiding the manual copy." (Specifically, adding your boost installation's include directory to your compiler/Eclipse search path.)
That is what the boost documentation means by having a directory containing boost/ in your #include path.
For small individual projects, you don't really want to be messing around creating hand-built links to boost includes for each project if your boost installation rarely changes, unless that's a part of your broader build strategy across projects. I've worked in organisations where this is done for good reasons, basically to enable you to set up different build instances pointing at different versions of boost (or other third party libraries) by just switching some symbolic links, rather than messing around with the make dependencies and paths.
So setting up sym links to boost's include, lib, etc. inside your project might be an option if you want that level of flexibility.
However, manually copying the boost header files into your project each time is not a good way to do it.
It's unusual,- and certainly not good practice-, to copy library headers to your projects, and it's not necessary at all.
Use the -I option to tell the compiler which additional pathes to search for include files.
Concerning Eclipse CDT, you can add the additional include pathes using the C++-Build Options of your project properties.
Referring to them externally.
Copying library files into application projects is nothing but copy-n-pasting code at a higher level. Don't do it. It typically leads to an extremely unstructured software architecture. You should even take the opposite direction: modularise your project's own code to create your own internal libraries, which your project then treats exactly like Boost libraries or the standard library. This is what your application project's files should look like:
#include <your_own_library/whatever.h>
#include <boost/whatever.hpp>
#include <string>
class ApplicationSpecificClass
{
// ...
};
Thinking in terms of libraries and APIs will improve your software-engineering skills significantly. It only requires that you learn more about your build environment and the options featured by your compiler and linker (both to create libraries and to use them). Learning how to use Boost libraries is a good start, because most of them are header-only libraries, which makes everything easier.

Reducing my boost lib folder

Even having already dug through loads of info on the net about this, I am still having some trouble understanding the boost lib files. I have Boost 1.51 installed and the lib folder is 1.7GBs which is just too much. I need to reduce it.
Just to show an example:
http://i.imgur.com/6nXfVEr.png
That is all the regex lib folders. There are 10 of them! I want to delete most of these, but I struggle to understand, which folders I need.
I assume 'libboost' is the static lib (which doesn't require a DLL) and the others are dynamic which do. Does it mean if I use the dynamic libraries I need boost DLLs in my project?
I can also see some are debug and others aren't. Is it necessary to keep both? or can I just always use the non-debug versions for my projects?
Finally, am I right in thinking, to make Visual Studio choose specific libs I go to the:
C/C++ project settings -> Code Generation -> Runtime Library, and change between /MT, /MD, etc?
If I use Multi-threaded (/MT), does that mean I can remove all the debug libs and dlls because this option only uses the static libs?
Thanks for any advice.
I assume 'libboost' is the static lib (which doesn't require a DLL) and the others are dynamic which do.
Yes.
Does it mean if I use the dynamic libraries I need boost DLLs in my project?
Yes.
Finally, am I right in thinking, to make Visual Studio choose specific libs I go to the: C/C++ project settings -> Code Generation -> Runtime Library, and change between /MT, /MD, etc?
Not quite so. Setting /MT or any other similar option will only make your application use the corresponding versions of runtime libraries (e.g. CRT). It does not mean you can only link statically after this, neither does it "select" anything for your own project-specific dependencies.
Whether you link to boost as a static library or DLL depends on which .lib file (libboostXXX or boostXXX) you specify in: Linker -> Input -> Additional Dependencies. Also, you may need to visit Linker -> General -> Additional Library Directories and add a path to your boost/libs folder (and possibly its subfolders) so that you don't have to specify full path for each library you are adding to dependencies.
However, you should always (especially when using static libraries) link to libraries built with the same runtime which you have selected in your main project. If you try to mix different runtimes, you will most likely get pretty cryptic linker errors about double-defined symbols (in system libraries) and such. In the worst case (usually due to a mismatch in some less obvious settings, like preprocessor definitions that change STL options) it will not lead to a linker failure, but to mysterious runtime crashes. Visual Studio 2010 and later, however, does pretty good job of detecting such mismatches (compared to previous VS versions).
Another issue might be that some of the boost headers are using #pragma comment to force linking necessary libraries by a specific name. If you find this a problem and want to specify your dependencies manually (or if it selects something you don't really need to link to), you can add a global preprocessor define BOOST_ALL_NO_LIB to C/C++ -> Preprocessor -> Preprocessor Definitions.
Also, do you really need all of the boost libraries in your project? There's a lot of them, and most are for very special things. In my experience, people usually only need a small subset of boost for their project-specific goals. To create such a subset, containing headers only for the libraries which you really use, and their dependencies, you can use the BCP utility. This would probably reduce your boost/boost folder dramatically. And, of course, you can also delete binaries for the libraries you are not going to use. Also note that most of the general-purpose libraries in boost are header-only and thus don't require linking to any libraries at all.

Where do I put third-party libraries to set up a C++ Linux development environment?

I'm not new in C++ although I'm new in Linux. I'm using CMake to precompile a cross-platform game engine with some third-party components, but I have a lot of doubts about using libraries. My question is how to work with third-party libraries and where to put them. Apt installs libs in their official place (/usr/local, /usr/lib/ ..) but I develop in Windows using local libs that are in a folder in my project dir.
Also, I need a good tutorial to know the rules of how libraries work. For example: when trying to compile my project, luabind is asking for liblua.s0.1, but AFAIK there is no way to generate this library with the source provided by Lua (at least doing make, make install).
I know, this question is fuzzy but I haven't enough experience to be more concise.
Update: After reading some answers, a more concise question is the following. If I install all third-party libraries, how can I distribute my program? How do I manage dependencies without using a large readme?
Where to put libraries
The best solution is to use your Linux distribution's packaging system (apt-get, yum, or similar) to install libraries from distro-provided packages wherever possible.
If the distro's packaged libraries aren't of a recent enough version, or if you need some nonstandard build options, or if you need a library that your distro doesn't provide, then you can build and install it yourself. You have two main options for where to put the library:
/usr/local (libraries under /usr/local/lib, headers under /usr/local/include). This installs the libraries systemwide and is probably the simplest solution, since you should then be able to build against them without taking any extra steps. Do NOT install libraries directly under /usr, since that will interfere with your distro's packaging system.
Under your project directory, as you did under Windows. This has the advantages of not requiring root access and not making systemwide changes, but you'll have to update your project's include paths and library paths, and you'll have to put any shared library files someplace where the dynamic linker can find them (using LD_LIBRARY_PATH or ld.so.conf - see the link for more details).
How libraries work
See David A. Wheeler's excellent Programming Library HOWTO. I'd recommend reading that then posting any specific questions as new topics.
How to distribute your program
Traditionally, Unix / Linux programs do not include copies of their dependencies. It's instead up to the end user or developer to install those dependencies themselves. This can require a "large README," as you said, but it has a few advantages:
Development libraries can be installed, managed, and updated via the distro's package manager, instead of each source copy having its own set of libraries to track.
There's only one copy of any given library on a system, so there's only one place that needs updating if, for example, a security flaw is found. (For example, consider the chaos that resulted when zlib, a very widely used compression library, was found to have a security flaw, so every application that included an affected version needed to be updated.)
If your program is popular enough (and is open source or at least freely available), then package maintainers for various Linux distributions may want to package it and include it in their distro. Package maintainers really don't like bundled libraries. See, for example, Fedora's page on the topic.
If you're distributing your program to end users, you may want to consider offering a package (.dpkg or .rpm) that they could simply download and install without having to use source. Ideally, from the end user's perspective, the package would be added to distros' repositories (if it's open source or at least freely available) so that users can download it using their package managers (apt-get or yum). This can all get complicated, because of the large number of Linux distros out there, but a Debian/Ubuntu compatible .dpkg and a Red Hat/CentOS/Fedora-compatible .rpm should cover a good percentage of end users. Building packages isn't too hard, and there are good howtos online.
for the first part of your question regarding Windows: there's no real standard place for libraries/headers on Windows, so the easy solution is: create your own. Simply provide a single lib/ and include/ on your system and have all your projects use it (by setting the path in a cmake file that you include everywhere). Put all third party libs in there, for example:
your projects:
d:/projects/projectA
d:/projects/projectB
third party stuff:
d:/api/lib/lua.lib
d:/api/include/lua/....
(you can even use symlinks aka 'directory junctions' if you have different version)
and the corresponding cmake file:
include_directories( d:/api/include )
link_directories( d:/api/lib )
Okay, so this is one of the basic questions and while I myself might not come across very clear on this, here goes:
While building a project, your compiler will need to find the header files of the libraries. The headers must be in the include path.
after compilation is done, the linker will look for the library binaries (files.so or something like that). These must be in the Library path.
That's the basics.
If you have some specific libaries, you can add them to your own project-specific lib/ and include/ directories and add them to the include path and the library path respectively.
Adding these dirs to these paths can be done in many ways, depending upon how you are building the project. I'm sure there is something called LD_PATH involved in all this... But I don't really know the specifics involved with CMake.
A little googling can help you do the above with CMake.
Hope that helps,
jrh
If you are installing the libraries with a package manager, they will probably all end up in the right place. If not you can get the compiler to search for the by providing the an additional search path using the -L <path> flag. You should be able to pass this extra flag to CMake.
Incidentally the -I <path> can be used to add an extra directory to search for include files.

Conditionally disable warnings with qmake/gcc?

I am involved with a software project written in Qt and built with qmake and gcc on Linux. We have to link to a third-party library that is of fairly low quality and spews tons of warnings. I would like to use -W -Wall on our source code, but pass -w to the nasty third-party library to keep the console free of noise and clutter so we can focus on our code quality.
In qmake, is there a way to conditionally add CFLAGS/CXXFLAGS to certain files and libraries?
Jonathan, I think the problem is where your source files are including header files from 3rd party libraries, and you want to switch off the warnings for the latter.
Kevin, i think you can use pragmas to control warnings : gcc diagnostic pragmas
You could add these before and after any #includes for 3rd party libs.
What if you include your library using -isystem.
In the project file e.g.:
QMAKE_CXXFLAGS += -isystem /usr/local/boost_1_44_0
Normally, you'd build the third-party library in a separate directory from your own code, so you would have a different makefile for it, so you could put a different set of flags for that compilation.
If you've mixed the third-party library code with your own code, you have set yourself up for a maintenance nightmare.
Kevin,
qmake CONFIG+=debug QMAKE_CXXFLAGS_WARN_ON=-w QMAKE_CFLAGS_WARN_ON=-w
should do
(use CONFIG+=release if you wish...)
As Martin wrote adding the include directory via
QMAKE_CXXFLAGS += -isystem ...
suppresses warnings just in the respective headers. No need to disable warnings for any source files of your project (or even project-wide) or mess with #pragmas or wrappers files.
Note that if you're using QtCreator you'll still (i.e. additionally) want add the directory to INCLUDEPATH so the indexer picks up the headers.