Mentions légales du service

Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • master
  • v19.05
  • v20.03
  • v21.05
  • v22.10
5 results

Target

Select target project
  • formations/cpp/gettingstartedwithmoderncpp
  • sbenamor/gettingstartedwithmoderncpp
  • steff/gettingstartedwithmoderncpp
  • sgilles/gettingstartedwithmoderncpp
  • vrouvrea/gettingstartedwithmoderncpp
  • fvergnet/gettingstartedwithmoderncpp
  • jediaz/gettingstartedwithmoderncpp
  • mmalanda/gettingstartedwithmoderncpp
  • bnguyenv/gettingstartedwithmoderncpp
9 results
Select Git revision
  • 112_binder
  • 112_binder_support
  • 112_mr
  • 113_jupytext
  • 113_jupytext_dot_binder
  • 113_jupytext_postbuild
  • 113_jupytext_postbuild_pyproject
  • 124_decl_def
  • 124_test_compilation_ok
  • 126_zotero
  • 129_rephrasing
  • 134_virtual_calls
  • algorithm_rereading
  • ci_nbstripout
  • cppyy
  • develop
  • hands_on
  • jupytext
  • jupytext_in_postbuild
  • jupytext_pyproject_mac
  • master
  • miscellaneous_small_fixes
  • object_rereading
  • procedural_rereading
  • rereading_operators
  • rereading_template_notebooks
  • sebastien_note_2024_day2
  • rc24.03.4
  • rc24.03.5
  • rc24.03.6
  • rc24.03.7
31 results
Show changes
%% Cell type:markdown id: tags:
# [Getting started in C++](./) - [C++ in a real environment](/notebooks/6-InRealEnvironment/0-main.ipynb) - [How to include properly third-party libraries](/notebooks/6-InRealEnvironment/4-ThirdParty.ipynb)
%% Cell type:markdown id: tags:
## Introduction
Any sizable code doesn't exist in a void: it's likely it needs to be built upon some pre-existing libraries.
We have mostly talked about the STL up to this point in this tutorial, but it's likely you will need some other libraries more specific to your field (for instance if you're doing numerical computation you'll probably need a solver from a library).
C++ may be interfaced rather easily with C and Fortran code; however a recurrent issue that is the reason of the current notebook is warnings: even highly recommended and used libraries such as [Boost](https://www.boost.org/) are cluttered with warnings and there is no easy solution:
* Fixing the warnings from the third-party library yourself is a dead-end: you would have to redo-it at each upgrade of the library... and doing it in the first place may not be that easy with a base code you do not know.
* Of course, you may ask the library developers to fix it, or even better provide a **pull request** to do it for them... but they may not be keen to accept it, and argue they know what they're doing and that you should silence the damn compiler warnings. But you really shouldn't: the warnings you want to use or not should be dictated by your own needs, not by third-party libraries'.
* Keeping the warnings is also bad: as already mentioned if you're letting even 10 warnings in your code you may not see the dangerous 11th warning that a change in the code may produce.
## Demo
We will follow here the instructions detailed in a dedicated [README](./4b-Demo/README.md) (in 4b-Demo directory).
The remaining of current notebook is a shortcut if you do not want to run the demo; if you do you may stop reading here and switch to the demo.
## Example
As we shall see, there are two very different mechanisms that are present to work around the issue.
To illustrate them we will tackle a very basic example: a program which calls Boost filesystem library to copy a file. We also purposely add code below that should raise a warning:
%% Cell type:code id: tags:
``` C++17
``` c++
// Does not work as a Jupyter cell: no Boost installed!
#include <cstdlib>
#include <iostream>
#include "boost/exception/diagnostic_information.hpp"
#include "boost/filesystem.hpp"
int main()
{
try
{
boost::filesystem::path source_path("/Codes/ThirdPartyWarning/source.txt");
boost::filesystem::path target_path("target.txt");
boost::filesystem::copy_file(source_path, target_path);
}
catch (const boost::filesystem::filesystem_error& e)
{
std::cerr << "Exception with Boost filesystem: " << boost::diagnostic_information(e) << std::endl;
return EXIT_FAILURE;
}
int a; // variable intentionally left to underline my point about warnings...
std::cout << "Value is " << a << std::endl;
return EXIT_SUCCESS;
}
```
%% Cell type:markdown id: tags:
Compiling this code with clang and `-Weverything` yields more than 1000 warnings at the time of this writing!
This example is tackled in Docker; see the [README](https://gitlab.inria.fr/formations/cpp/gettingstartedwithmoderncpp/blob/master/6-InRealEnvironment/Docker/ThirdPartyWarning/README.md) to see how to use this Docker image which illustrates directly the methods explained below.
%% Cell type:markdown id: tags:
## Indicating the header from those libraries as system ones
The first solution is to tell your build system that the directory in which the third party header files you need to include are system directories; for which compiler will not issue warnings.
This works obviously only if the headers from the third-party libraries are not located in same directories as those of your model, but this seems sensible enough not to be a hurdle.
The trick is to figure out how to give this instruction to your compiler:
%% Cell type:markdown id: tags:
### `clang`or `gcc` compiler
You need to replace the `-I` usually used to indicate the header directories by `-isystem`:
%% Cell type:markdown id: tags:
```shell
clang++ -Weverything -I /Codes/ThirdParty/opt/include simple_boost.cpp -L /Codes/ThirdParty/opt/lib -lboost_filesystem -lboost_system
```
becomes
```shell
clang++ -Weverything -isystem /Codes/ThirdParty/opt/include simple_boost.cpp -L /Codes/ThirdParty/opt/lib -lboost_filesystem -lboost_system
```
%% Cell type:markdown id: tags:
### CMake
You need to add the keyword `SYSTEM` in your target_include_directories. So
```
target_include_directories(simple_boost PUBLIC "/Codes/ThirdParty/opt/include")
```
becomes
```
target_include_directories(simple_boost SYSTEM PUBLIC "/Codes/ThirdParty/opt/include")
```
%% Cell type:markdown id: tags:
I must admit I don't usually go this way and instead use the second option, but I admit it seems quite straightforward.
The few drawbacks I can see are:
* You have to figure out how your build system takes this into account.
* You have to make sure it is portable: another user may not place these third-party headers in the same location as you, and you have to figure out a proper way to indicate where they are. This is by no means overwhelming, but still requires a bit of work. This is especially so if the third party library is directly embedded in your code (might happen, especially if the library is header only).
%% Cell type:markdown id: tags:
## Deactivating the warnings locally with pragmas in your code
%% Cell type:markdown id: tags:
Recently clang and gcc introduced **pragmas** to deactivate selectively warnings in part of your code.
The principle is that around the `#include` itself you provide preprocessor commands to deactivate temporarily the issue.
So for instance to solve the issue with clang, you may replace the include lines of the file by:
%% Cell type:code id: tags:
``` C++17
``` c++
// Replace the two include lines in the program given previously
#pragma clang diagnostic push // starts the code block in which rules are modified
#pragma clang diagnostic ignored "-Wsign-conversion"
#pragma clang diagnostic ignored "-Wold-style-cast"
#pragma clang diagnostic ignored "-Wparentheses"
#pragma clang diagnostic ignored "-Wcast-qual"
#pragma clang diagnostic ignored "-Wdeprecated"
#pragma clang diagnostic ignored "-Wconversion"
#pragma clang diagnostic ignored "-Wreserved-id-macro"
#pragma clang diagnostic ignored "-Wweak-vtables"
#pragma clang diagnostic ignored "-Wundef"
#pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant"
#pragma clang diagnostic ignored "-Wundefined-func-template"
#pragma clang diagnostic ignored "-Wc++98-compat"
#pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
#pragma clang diagnostic ignored "-Wexit-time-destructors"
#pragma clang diagnostic ignored "-Wpadded"
#pragma clang diagnostic ignored "-Wnon-virtual-dtor"
#include "boost/exception/diagnostic_information.hpp"
#include "boost/filesystem.hpp"
#pragma clang diagnostic pop // go back to normal rules
```
%% Cell type:markdown id: tags:
Yes, even in a top-notch library like Boost there are plenty of warnings! (but don't use that as an excuse not to clean-up yours...)
Unfortunately, you will surely have seen _clang_ is mentioned explicitly; gcc needs the same kind of work... with the exact same syntax, compiler name aside. For instance if `-Wsign_conversion` is activated in your gcc build, you will need GCC pragma:
%% Cell type:code id: tags:
``` C++17
``` c++
#pragma GCC diagnostic ignored "-Wsign-conversion" // upper case GCC required to make it work!
```
%% Cell type:markdown id: tags:
To make things worse, unknown pragma triggers warning by itself, so either you need to deactivate _-Wunknown-pragmas_ or you need to use macros to separate compiler cases (see [this link](http://nadeausoftware.com/articles/2012/10/c_c_tip_how_detect_compiler_name_and_version_using_compiler_predefined_macros) to see how to indicate in a macro which compiler to use):
%% Cell type:code id: tags:
``` C++17
``` c++
#ifdef __clang__
# pragma clang diagnostic push // starts the code block in which rules are modified
# pragma clang diagnostic ignored "-Wsign-conversion"
...
#pragma clang diagnostic pop // go back to normal rules
#elif !defined(__INTEL_COMPILER) and defined(__GNUG__)
# pragma GCC diagnostic push // starts the code block in which rules are modified
# pragma GCC diagnostic ignored "-Wsign-conversion"
...
#pragma GCC diagnostic pop // go back to normal rules
#endif
```
%% Cell type:markdown id: tags:
In my code I [fiddled a bit with macros](https://gitlab.inria.fr/MoReFEM/CoreLibrary/MoReFEM/raw/master/Sources/Utilities/Pragma/Pragma.hpp) to put in common macros with the same name and thus spare few lines.
%% Cell type:markdown id: tags:
### Extra level of indirection
There's a common quote in the C++ community that almost every problem may be solved by adding an extra level of indirection. I recommend using it here if you go the pragma way: if several files in your project need the Boost filesystem to be included, it is better to define a header file of yours which will include the gory details with the pragmas. This way, you will repeat the Don't Repeat Yourself! principle and make your code more manageable (if one new warning appears after a compiler update you need to change it in only one location) and also make your code generally more readable, by substituting a big block by just one include line.
In my project, I include the Boost filesystem with:
```c++
#include "ThirdParty/IncludeWithoutWarning/Boost/Filesystem.hpp"
```
(yes, I'm not that good for naming stuff!)
%% Cell type:markdown id: tags:
[© Copyright](../COPYRIGHT.md)
......
This diff is collapsed.
......@@ -129,16 +129,15 @@
],
"metadata": {
"kernelspec": {
"display_name": "C++17",
"language": "C++17",
"name": "xcpp17"
"display_name": "Cppyy",
"language": "c++",
"name": "cppyy"
},
"language_info": {
"codemirror_mode": "text/x-c++src",
"codemirror_mode": "c++",
"file_extension": ".cpp",
"mimetype": "text/x-c++src",
"name": "c++",
"version": "17"
"name": "c++"
},
"latex_envs": {
"LaTeX_envs_menu_present": true,
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
#!/bin/bash
pip install git+https://gitlab.inria.fr/sed-saclay/cppyy_kernel.git
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.