Silence GCC warnings in CMake C++ standalone project with ROOT classes and dictionaries

I have CMake projects with modern C++ with several warning flags enabled.

Whenever I include some ROOT libraries into the CMake project, I get thousands of warnings which ‘mask’ my real warnings. To get rid of those, I enclose all ROOT #include statements in my MainWindow.cpp class with:

#pragma GCC diagnostic ignored "-Wold-style-cast"
#pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wsign-conversion"
#pragma GCC diagnostic ignored "-Wconversion"
#pragma GCC diagnostic ignored "-Wcast-qual"

#include "TROOT.h"
#include "T...."

#pragma GCC diagnostic warning "-Wold-style-cast"
#pragma GCC diagnostic warning "-Wzero-as-null-pointer-constant"
#pragma GCC diagnostic warning "-Weffc++"
#pragma GCC diagnostic warning "-Wsign-conversion"
#pragma GCC diagnostic warning "-Wconversion"
#pragma GCC diagnostic warning "-Wcast-qual"

Note: I do not want to disable them globally, as many other parts of the code are not from ROOT and I want to keep these warnings.

However, there is a further problem when you have a custom derived ROOT class, e.g. MainWindow : public TGFrame, which needs a dictionary for signals/slots. In that case, my CMakeLists.txt has the statement:
ROOT_GENERATE_DICTIONARY(G__MainWindow ${CMAKE_CURRENT_SOURCE_DIR}/MainWindow.hpp)

The problem now is that I cannot enclose the resulting dictionary file G__MainWindow.cxx with the same pragmas, as it is generated behind the scenes.

I came up with a complicated hack to get rid of those 1000+ warnings appearing from the generated dictionary, by creating a custom command in the CMakeLists.txt:

add_custom_command(
  OUTPUT suppressWarnings
  # https://unix.stackexchange.com/questions/43119/preserve-modified-time-stamp-after-edit
  COMMAND cp -p G__MainWindow.cxx G__MainWindow_.cxx
  COMMAND sed -i '1i_Pragma\(\"GCC diagnostic ignored \\\\\"-Wold-style-cast\\\\\"\"\) _Pragma\(\"GCC diagnostic ignored \\\\\"-Wzero-as-null-pointer-constant\\\\\"\"\) _Pragma\(\"GCC diagnostic ignored \\\\\"-Weffc++\\\\\"\"\) _Pragma\(\"GCC diagnostic ignored \\\\\"-Wsign-conversion\\\\\"\"\) _Pragma\(\"GCC diagnostic ignored \\\\\"-Wconversion\\\\\"\"\) _Pragma\(\"GCC diagnostic ignored \\\\\"-Wcast-qual\\\\\"\"\) _Pragma\(\"GCC diagnostic ignored \\\\\"-Wmissing-declarations\\\\\"\"\)' G__MainWindow.cxx
  COMMAND echo '_Pragma\(\"GCC diagnostic warning \\\\\"-Wold-style-cast\\\\\"\"\) _Pragma\(\"GCC diagnostic warning \\\\\"-Wzero-as-null-pointer-constant\\\\\"\"\) _Pragma\(\"GCC diagnostic warning \\\\\"-Weffc++\\\\\"\"\) _Pragma\(\"GCC diagnostic warning \\\\\"-Wsign-conversion\\\\\"\"\) _Pragma\(\"GCC diagnostic warning \\\\\"-Wconversion\\\\\"\"\) _Pragma\(\"GCC diagnostic warning \\\\\"-Wcast-qual\\\\\"\"\) _Pragma\(\"GCC diagnostic warning \\\\\"-Wmissing-declarations\\\\\"\"\)' >> G__MainWindow.cxx
  COMMAND touch -r G__MainWindow_.cxx G__MainWindow.cxx
  DEPENDS G__MainWindow.cxx
  WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
)

add_library(MyLibrary SHARED MainWindow.hpp MainWindow.cpp G__MainWindow.cxx suppressWarnings)

It works fine, but it was a pain to find it all out. Now the question: is there a more sensible way of achieving this?

Maybe in the future, the ROOT_GENERATE_DICTIONARY CMake macro could include an additional parameter specifying a ‘prefix-line’ and a ‘suffix’ line that would be added automatically to it, based on what the user passes as parameter in the CMakeLists.txt?

Thanks for reading.

Hi @ferhue ,
maybe you could tweak the cmake compilation flags before/after compiling G__MainWindow.cxx into a shared object and add a G__MainWindow.so shared object as a target_link_library of MyLibrary instead of compiling MainWindow.cxx and G__MainWindow.cxx at the same time.

Cheers,
Enrico

EDIT: PRs are welcome to fix annoying warnings in ROOT, but I guess fixing e.g. all -Wzero-as-null-pointer-constant and -Wold-style-cast is too many changes to very old code.

1 Like

I ended up removing the ROOT dictionary generation, which simplifies greatly the CMakeLists, using ClassDefInline as suggested by @pcanal.

For reference a simple hack was to create a file (or multiple if needed) named “RootIncludes.h” that contains:

#pragma GCC diagnostic ignored "-Wold-style-cast"
#pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"
#pragma GCC diagnostic ignored "-Weffc++"
#pragma GCC diagnostic ignored "-Wsign-conversion"
#pragma GCC diagnostic ignored "-Wconversion"
#pragma GCC diagnostic ignored "-Wcast-qual"

#include "TROOT.h"
#include "T...."

#pragma GCC diagnostic warning "-Wold-style-cast"
#pragma GCC diagnostic warning "-Wzero-as-null-pointer-constant"
#pragma GCC diagnostic warning "-Weffc++"
#pragma GCC diagnostic warning "-Wsign-conversion"
#pragma GCC diagnostic warning "-Wconversion"
#pragma GCC diagnostic warning "-Wcast-qual"

and use as needed and/or pass just to dictionary generation part.

Thanks for the hint!

But that only simplifies the first part of it. The Macro ROOT_GENERATE_DICTIONARY creates a file G__MainWindow.cxx which has auto-generated #include “TROOT.h” like the one below:

#include "TInterpreter.h"
#include "TROOT.h"
#include "TBuffer.h"
#include "TMemberInspector.h"
#include "TInterpreter.h"
#include "TVirtualMutex.h"
#include "TError.h"

#ifndef G__ROOT
#define G__ROOT
#endif

#include "RtypesImp.h"
#include "TIsAProxy.h"
#include "TFileMergeInfo.h"
#include <algorithm>
#include "TCollectionProxyInfo.h"
/*******************************************************************/

#include "TDataMember.h"

which would not be ‘enclosed’ with the pragma stuff, even if I pass RootInclude.h as argument. That’s why I created the additional CMake target that adds this pragmas by hand on this dictionary intermediate cxx file.

right indeed … So the real solution is leverage the fact that there is way to tell cmake to apply CXX_FLAGS just for a single file. (See set_source_files_properties and COMPILE_FLAGS) So a combination of the file and applies the flags directly to the dictionary .o file production would have done the trick.

1 Like