Root branch v6-30-00-patches for C++20 Not Quite Working

Hi,
So I wanted to build root from source setting the C++ standard to C++20 and I was advised that the root git branch v6-30-00-patches was the branch that would support C++20 (and was the most stable branch that supported C++20). I notice that when bringing up root, by default it now brings up the web-based canvas, but it seems that for this branch, there’s a lot of things broken in the tutorial scripts. For starters, if you ran gl/glbox.C, you only see a single box or circle (btw I couldn’t even save this image as a jpg or a png from the file option; I had to use some other screenshot tool to take a snapshot of this picture):

Whereas for earlier versions like branch v6-28-06 (which didn’t support C++20, so I could only build it for C++17), running that same script would give you the correct results:

I understand that one can turn off the web-base canvas in v6-31-00-patches by running root --web=off, but that didn’t changes the results (got the same picture of just a single box/circle).

It does spew the errors (whether web-base canvas is on or not)

Error in <TFormula::Eval>: Formula is invalid and not ready to execute 
z] is unknown.

There are many other changed behaviors of other tutorial scripts with either the web-base canvas on or off (mostly with the canvas on, in some cases, you just don’t see any pictures appearing on the web browser that opens) that I don’t have time listing all of them.

Is there a more stable branch where these tutorial scripts do work that supports C++20?


Please read tips for efficient and successful posting and posting code

Please fill also the fields below. Note that root -b -q will tell you this info, and starting from 6.28/06 upwards, you can call .forum bug from the ROOT prompt to pre-populate a topic.

_ROOT Version:Root git branch v6-30-00-patches
_Platform: Ubuntu 20.04 Linux
_Compiler: gcc/g++ 10.5.0


Hello @jade2 ,

assuming you mean v6-30-00-patches, @Axel or @Danilo can correct me if I’m wrong but it does not get more stable than that outside of actual releases (EDIT: see also ROOT versioning scheme - ROOT ).

About:

Error in <TFormula::Eval>: Formula is invalid and not ready to execute 
z] is unknown.

checking for the obvious first, if you grep -F 'z]' glbox.C does that find something? It should not.

Cheers,
Enrico

P.S.
I just compiled v6-30-00-patches with cmake -S . -B cmake-build -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -G Ninja -DCMAKE_INSTALL_PREFIX=cmake-build/install and the tutorial displays fine for me with and without the new web graphics. That’s not to say there isn’t a problem, just that it might depend on a difference between my environment and yours.

However that TFormula::Eval error is suspicious and the first thing I would do is to track down where it comes from exactly. z] is unknown makes it sound like there is a typo in the formula expression.

checking for the obvious first, if you grep -F 'z]' glbox.C does that find something? It should not.

No, nothing comes up for that grep. That’s not all the errors that are spewing. Let me add a few lines to the errors I’m seeing:

Error in <TFormula::Eval>: Formula is invalid and not ready to execute 
z] is unknown.
gaus[x is unknown.
Error in <TFormula::Eval>: Formula is invalid and not ready to execute 
z] is unknown.
gaus[x is unknown.

There are two places in the root source code that prints this out and it is here and here, both in hist/hist/src/TFormula.cxx. If you look at those two links, you’ll see that the messages z] is unknown comes from the printf within that for-loop. But knowing where in the code that error is spewing from and why it’s spewing that error — the latter I couldn’t tell you. You’ll need to consult with the owner of that code.

I just compiled v6-30-00-patches with cmake -S . -B cmake-build -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -G Ninja -DCMAKE_INSTALL_PREFIX=cmake-build/install and the tutorial displays fine for me with and without the new web graphics. That’s not to say there isn’t a problem, just that it might depend on a difference between my environment and yours.

Did you build it with the same compiler I specified in the post (gcc/g++ 10.5.0)? This was the cmake config summary of my build:

System          Linux-5.15.0-87-generic
Processor       8 core 11th Gen Intel(R) Core(TM) i7-11850H @ 2.50GHz (x86_64)
Build type      Release
Install path    /home/jade/bin/root-v6-31-00-patches
Compiler        GNU 10.5.0
Compiler flags:
C                -Wno-implicit-fallthrough -pipe -Wall -W -pthread -O3 -DNDEBUG
C++              -std=c++2a -Wno-implicit-fallthrough -Wno-noexcept-type -pipe  -Wshadow -Wall -W -Woverloaded-virtual -fsigned-char -pthread -O3 -DNDEBUG
Linker flags:
Executable       -rdynamic
Module          
Shared           -Wl,--no-undefined -Wl,--hash-style="both"

-- Enabled support for:  asimage builtin_afterimage builtin_clang builtin_cling builtin_ftgl builtin_gl2ps builtin_glew builtin_llvm builtin_lzma builtin_nlohmannjson builtin_openui5 builtin_pcre builtin_tbb builtin_vdt builtin_xrootd builtin_xxhash builtin_zstd clad dataframe exceptions gdml http imt mlp minuit2 opengl proof pyroot roofit webgui root7 rpath runtime_cxxmodules shared ssl tmva spectrum vdt x11 xrootd
-- Configuring done
-- Generating done
-- Build files have been written to: /home/jade/root/linux-build

How does your config settings in your successful build differs?

FYI, this was using the same build that gave that warning that I haven’t been able to get to root cause.

Hi,
I am using gcc 13.2.1.

The C++ version mismatch warning is still weird and I still don’t know what might cause it. But I’d be surprised if it had to do with TFormula::Eval going haywire.

@moneta could you please help here? I can’t tell what might cause those errors in TFormula::Eval.

@jade2 at this point I would suggest to build ROOT inside a Docker container that provides one of the toolchains ROOT is tested against. For C++20 that would be Ubuntu 22.04. Graphics should work too by following these instructions.

Sorry I can’t be of more help, I strongly suspect there is something off with your environment but from where I sit I can’t tell what it might be.

@eguiraud what is the minimum gcc/g++ version I need to use to get sufficient C++20 support? I thought you said that gcc 10 and above would suffice (so I upgraded gcc/g++ to 10.5)

I can’t just run root in docker for my situation. In the very near future, we’re hoping to use some of our C++ software libraries to be used in our analysis we hope to run using root. To do that, I eventually need to build root using the same C++ toolchain our software library is built with (still an x86_64-linux platform and 10 > gcc compiler version > 11). One of the main considerations of using root is the ability to bring in our own C++ libraries into our analysis (aside from the fact that it can handle large data). So this preliminary exercise I’m doing is to at least verify that root supports C++20 with gcc/g++ 10.5.

At least what I can gather in the build documentation for root, this was suppose to work (setting the C++ standard to C++20). Unfortunately, the build document doesn’t note what are the minimum requirement for 3rd party libraries (and their versions) that root is dependent on (openGL, X11, etc). I’m solely relying on the cmake configuration to tell me what’s acceptable or not, and yet the cmake configuration didn’t even tell me in my earlier attempts that having a gcc version of 9.4 wasn’t sufficient support for C++20 (which eventually led me to upgrade my default compiler to above 10). I wonder if some lapses of the cmake configuration, also doesn’t check if any of the versions of the 3rd party libraries I have installed on my machine are sufficient (e.g. I don’t think this is the compiler version problem).

So is it the case that building root from source are only supported for specific host platform versions? That is if using ubuntu and specifying a bulid for C++20, that one has to have Ubuntu 22.04 to do that? I didn’t see that as a requirement in the build doc for root …

I’m afraid I don’t know how to answer that question. Due to how C++ and C++ standard support in the different compilers work, the only way to know whether a certain compiler version works is to try to build ROOT with it, run the test suite and see if it’s green. There might be features that ROOT or a library on which ROOT depends that are required but not supported, and it’s very hard to know until one tests it out.

So I can only report what has been tested, and that’s Ubuntu 22.04 with its default system compiler (gcc 11.4, tested by ROOT’s nightly builds) or Arch Linux with gcc 13.2.1 (tested by me to try to reproduce the problem you reported).

Can reproduce all problems: they seem due to gcc 10.5 + -std=2a

I ran the commands [1] in an Ubuntu 20.04 Docker container, and it reproduces the warnings about the C++ standard you saw and reported in your first thread, so they are most likely due to the mix of gcc 10.5 and c++20.

Patching /root_build/include/RConfigure.h to print out __cplusplus, the message becomes:

warning: The C++ standard in this build (202002L) does not match ROOT configuration (201709L)

Now the question of course is why ROOT thinks it was configured with C++17.
It turns out that fundamentally it’s because clang (the compiler ROOT’s C++ interpreter is based on) and gcc 10.5 disagree on the meaning of -std=c++2a.

Surprisingly, g++ -std=c++2a -c root_src/config/__cplusplus.cxx (which is what ROOT’s CMake runs to figure out what standard it is using) prints 201709L.
On the other hand, using this ROOT build, root -q -e 'printf("%d", __cplusplus)' prints 202002L.

All problems should go away by using gcc 10 with C++17 instead of C++20 or with Ubuntu 22.04 and its system compiler (gcc 11.4).

I’ll leave it to someone in the ROOT team (@bellenot or @Axel maybe?) to comment on whether ROOT’s cmake configuration can be improved to catch more problems than it does now and detect when the compiler does not provide the expected __cplusplus.

On the other hand, the warning we saw was, in a sense, the build system trying to say that there was something funky going on with the compilation toolchain.

I hope this helps.
Cheers,
Enrico


[1]

# gcc 10
apt update -y
apt upgrade -y
apt install -y build-essential
apt install -y gcc-10 g++-10 cpp-10
update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 100 --slave /usr/bin/g++ g++ /usr/bin/g++-10 --slave /usr/bin/gcov gcov /usr/bin/gcov-10

# ROOT dependencies from https://root.cern/install/dependencies/#ubuntu-and-other-debian-based-distributions
apt install gfortran libpcre3-dev xlibmesa-glu-dev libglew-dev libftgl-dev libmysqlclient-dev libfftw3-dev libcfitsio-dev graphviz-dev libavahi-compat-libdnssd-dev libldap2-dev python-dev python-numpy libxml2-dev libkrb5-dev libgsl0-dev qtwebengine5-dev
# missing dependencies to build from source:
apt install git cmake python3-dev python3-numpy libxpm-dev libxft-dev 

# ROOT build
git clone --branch v6-30-00-patches --depth 1 https://github.com/root-project/root.git root_src
mkdir root_build && mkdir root_install
cmake -S root_src -B root_build -DCMAKE_INSTALL_PREFIX=root_install -DCMAKE_CXX_STANDARD=20
cmake --build root_build -- -j16 install

P.S.

you said that gcc 10 and above would suffice

I must point out I did not say that :sweat_smile: the quote is “I think you will need at least gcc 10 […] But 12 or 13 would be better” (emphasis added now). And as per the context around that quote, it was a guess based on the C++20 compiler support table that I linked from there.

Wow thank you @eguiraud! I’ve learned a lot from your investigation; thank you for clarifying these things.

It turns out that fundamentally it’s because clang (the compiler ROOT’s C++ interpreter is based on) and gcc 10.5 disagree on the meaning of -std=c++2a .

This is interesting. My understanding of cling (the C++ interpreter used in root) is that it’s built on top of llvm & clang compiler (or rather the libraries that the clang compiler uses). But didn’t really think that far down on how the choice of compiler used to build root the tool, impacts the behind the scene of how root consolidates this when its C++ interpreter is based on a different compiler (clang). You don’t need to answer this question … just kind of thinking out loud. :smile: I’m guessing you guys have figured this out. I suppose this problem would go away if I had used the clang compiler instead of the gnu compiler to build root from source?

The other thing that surprises me is that gcc and clang do not agree on the meaning of -std=c++2a. Sure they differ on some things, but I didn’t think they would differ on this! I was a bit surprise that gcc 10.5 with -std=c++2a produced a __cplusplus value of “201709” (I wonder if this is gnu bug) and I can confirm that the gcc 10.5 with -std=c++2a does in fact have C++20 features.

Concerning what the patched /root_build/include/RConfigure.h now prints:

warning: The C++ standard in this build (202002L) does not match ROOT configuration (201709L)

I think that overall message is just confusing. Because when one says “The C++ standard in this build”, one would think that it’s referring to the current compiler (in my case its gcc) and the C++ standard set in the configuration, used to build the root tool — which I don’t think is its intended message.

After you explained why these values differ (clang vs gcc) maybe a suggestion on improving that warning message:

warning: ROOT C++ interpreter standard in this build (202002L) does not match this ROOT's build configuration (201709L)

It doesn’t have to worded exactly like this, but make the distinction that one is not the same as the other. The way the current message reads, I couldn’t quite make the distinction because the C++ standard is set in the build configuration, which adds to the confusion.

BTW this check on matching the C++ interpreter and the compiler (mixed in with the C++ standard used), could this not be verified during cmake configuration? I would think this is doable, no? I don’t think this check should be flagged during build time. For one thing, it is flagged as a warning rather than an error, and easily missed if someone is not carefully looking at the build log, only to find out that things don’t actually work as it should when one tries to run root. Also this check is really a requirements check on utilities used to build, which is the job of configuration.

In any case, thanks again for all this information. I realize now I’m going to have to make some difficult decisions on whether we can still use root (or maybe we still can but in a very limited way, since upgrading the compiler used to build our software, would take a lot of effort). Will need to investigate what the options are on our end.

However this might be the right choice independently of ROOT. The version of gcc that you have been trying does not really support the full/complete C++20 standard and as such you will encounter problem when trying to use C++20 feature in your own code (and hence the argument --std=c++2a)

So I see only 2 realistic solution:

a. Keep that version of the compiler and use the C++17 standard

b. Use gcc v11 or later to have proper C++20 supports (i.e. --std=c++20)

Cheers,
Philippe.

I echo this sentiment: requiring C++20 but with a compiler toolchain that has only partial support for it can cause trouble down the road.

There is a very important difference between having C++20 features and having full support for the whole C++20 standard. GCC 10.5 does not, as indicated on the GCC C++ standard official support page. As already commented above, this means that it’s unsafe to use C++20 in any C++ code you may have in your stack.

This is also the reason why it was possible to move the ROOT codebase to using C++17 as the minimum standard version only this year (it will become the default minimum standard in the soon-to-be-released ROOT 6.30), as finally all the most common Linux distros / MacOS versions available have a C++ compiler with full support for C++17.

Best,
Vincenzo

Hi,
Yes, I agree with all of you. This all makes sense when @eguiraud explained to me how the compiler needs to be consistent with cling as far as which C++ standard being used.

I would only ask that for better user experience, it might be best to place such checks in the cmake configuration. For my build I had passed -DCMAKE_CXX_STANDARD=20 and could see at the end of configuration log that it notes that the build options will be passing -std=c++2a and made no complaint about it (e.g. the cmake configuration passed). At the time, I didn’t think anything wrong that it was going to use -std=c++2a as a build option. Rather than relying on these warning messages I saw during build (which btw doesn’t fail the build), why not just have the cmake configuration fail right from the start, by noting that the compiler lacks full support of C++20? Just so I"m not the last person wondering why root was not behaving correctly, despite the cmake configuration and the build passing. :smile:

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.