Error when compiling a ROOT macro

When I type
.x Detector_sensitivity_builder.cpp
command into my ROOT prompt, it works, but since I try to compile my macro
.x Detector_sensitivity_builder.cpp+

it gets the following:

Info in TUnixSystem::ACLiC: creating shared library /home/artem/Desktop/farPPD-build/./Detector_sensitivity_builder_cpp.so
sh: 1: c++: not found
sh: 1: c++: not found
Error in : Executing ‘cd “/home/artem/Desktop/farPPD-build” ; c++ -fPIC -c -g -isystem/root/parts/root/install/usr/include -isystem/root/parts/root/install/usr/include/x86_64-linux-gnu -std=c++17 -Wno-implicit-fallthrough -Wno-noexcept-type -pipe -W -Woverloaded-virtual -fsigned-char -pthread -I$ROOTSYS/include -I"/snap/root-framework/93/usr/local/etc/" -I"/snap/root-framework/93/usr/local/etc//cling" -I"/snap/root-framework/93/usr/local/include/" -I"/snap/root-framework/93/usr/local/include" -D__ACLIC__ “/home/artem/Desktop/farPPD-build/Detector_sensitivity_builder_cpp_ACLiC_dict.cxx” ; c++ -g “/home/artem/Desktop/farPPD-build/Detector_sensitivity_builder_cpp_ACLiC_dict.o” -shared “/snap/root-framework/93/lib/homeishome.so” “/snap/root-framework/93/usr/local/lib/libRint.so” “/snap/root-framework/93/usr/local/lib/libCore.so” “/snap/root-framework/93/usr/local/lib/libRIO.so” “/snap/root-framework/93/usr/local/lib/libThread.so” “/snap/root-framework/93/usr/local/lib/libCling.so” “/snap/root-framework/93/usr/local/lib/libMathCore.so” “/snap/root-framework/93/usr/local/lib/libImt.so” -o “/home/artem/Desktop/farPPD-build/./Detector_sensitivity_builder_cpp.so”’ failed!

I have no idea, what I should to do to fix it, and there is no information in the internet.

ROOT Version: 6.22/06
Platform: Ubuntu
Compiler: ?


Try: sudo apt-get install g++

Hi Artem,

This is a bug in the snap package of ROOT. Wile is right in that it effectively means that g++ isn’t accessible, but unfortunately installing it at a system level won’t help here. I can expose g++ internally to the snap and this part of the problem is easily fixable and shouldn’t require user involvement when released.

Due to some snap specific problems, this ends up being not as trivial as just ensuring g++ can be found, it’s trying to search folders that only exist in the snaps build environment and not its runtime environment, and the most direct fix I have for this kind situation isn’t available in this specific instance. Instead, I’ll spend some time tomorrow looking into what I can do to compensate, I imagine that there’s some metadata somewhere that could be adjusted to remove the the /root/ entries from the include path being passed to g++ and this might be all that’s needed.

Unfortunately it’s late now so I’ll have to look into this tomorrow, but this isn’t a problem with your machine and is entirely on me. If you need a workaround asap, you could try using the ROOT precompiled binaries for Ubuntu or the Conda package, which shouldn’t have this issue.

Thanks for the report and sorry I couldn’t be more helpful in the first instance.

3 Likes

already installed

Thank you, that was indeed a bug from snap. I reinstall ROOT using precompiled libraries (Installing ROOT - ROOT) and it works now

sudo snap remove root-framework
wget https://root.cern/download/root_v6.22.00.Linux-ubuntu19-x86_64-gcc9.2.tar.gz
tar -xzvf root_v6.22.00.Linux-ubuntu19-x86_64-gcc9.2.tar.gz
source root/bin/thisroot.sh # also available: thisroot.{csh,fish,bat}

Glad to see you’ve found an alternative.

I think I’m closing in on the issue in the snap. For the ROOT team who might be interested, the paths appear to be hardcoded into libCore.so and so it might be possible to use binary patching to remove them. They also appear to be in compiledata.h; which I presume is where libCore.so gets them from originally but I presume is ignored thereafter. I’m not quite sure how the build system fits together here, but it looks feasible to fix ACLiC in the snap one way or another.

If I understand correctly, you are saying that libCore.so contains hardcoded paths to the location of the c++ executable at build time (which happens to be different than its location at runtime, hence the problem).

On one hand, it sounds like a relocatability issue, on the other there might be a reason why the interpreter needs, at runtime, exactly the same compiler that it was built with. @Axel what’s your take, bug or feature? :slight_smile:

Fortunately, I can ship the exact same compiler in the snap so the concerns there aren’t a problem.

libCore contains harded paths to the include folders used at build time. These folders at build time aren’t present in the runtime, but the files in them I believe are.

I.E, -isystem/root/parts/root/install/usr/include doesn’t exist at runtime, because the files are copied over to /snap/root-framework/current/usr/local/include, cling correctly uses them in this location, but ACLiC appears to me to be hardcoded to use them as they were at build time.

ubuntu@impartial-mouflon:~/root-snap/squashfs-root$ root-framework
   ------------------------------------------------------------------
  | Welcome to ROOT 6.22/06                        https://root.cern |
  | (c) 1995-2020, The ROOT Team; conception: R. Brun, F. Rademakers |
  | Built for linuxx8664gcc on Mar 04 2021, 01:18:00                 |
  | From tags/v6-22-06@v6-22-06                                      |
  | Try '.help', '.demo', '.license', '.credits', '.quit'/'.q'       |
   ------------------------------------------------------------------

root [0] .include
-I
/snap/root-framework/x1/usr/local/etc/
-I
/snap/root-framework/x1/usr/local/etc//cling
-I
/snap/root-framework/x1/usr/local/include/
-cxx-isystem
/snap/root-framework/x1/usr/include/c++/9
-cxx-isystem
/snap/root-framework/x1/usr/include/x86_64-linux-gnu/c++/9
-cxx-isystem
/snap/root-framework/x1/usr/include/c++/9/backward
-isystem
/usr/local/include
-isystem
/snap/root-framework/x1/usr/local/etc//cling/lib/clang/5.0.0/include
-extern-c-isystem
/usr/include/x86_64-linux-gnu
-extern-c-isystem
/include
-extern-c-isystem
/usr/include
-I
/snap/root-framework/x1/usr/local/include
-resource-dir
/snap/root-framework/x1/usr/local/etc//cling/lib/clang/5.0.0
-fmodule-cache-path
/snap/root-framework/x1/usr/local/lib
-nostdinc++

So in cling, the build environment doesn’t appear at all as is expected and why cling itself works absolutely fine. In ACliC, /root appears and causes permission issues.

For the time being, I’d treat this as a snap specific error, because there might be things I can do to work around this and the payoff for other packages is nothing. The first option is simply use binary patching to remove the undesirable includes, the second option involves modifying the snap build environment so that the includes that become hardcoded can be symlinked and thus become accessible, I’d imagine both are easier than reworking ROOT itself here.

At this point, the symlinks approach seems right to me, as it should not require too much effort. However, in the long term, maybe @Axel has a different plan.

The “/snap/root-framework/x1/usr/local” string seems to be the prefix of your install (i.e., what you would get from “root-config --prefix”).
The “/snap/root-framework/x1/” string seems to be the root directory of your system (i.e., it would be just a “/” on a standard Linux system).

Indeed, /snap/root-framework/x1/ is the root of an Ubuntu environment and x1/usr/local is the effectively the prefix ROOT is itself installed into.

ubuntu@impartial-mouflon:~/root-snap/squashfs-root$ root-config --prefix
/snap/root-framework/x1/usr/local

There’s a lot of detail left out in my posts about how the mount namespace fits together, while I have total control of /snap/root-framework/revision/ ; I don’t have as much control of / itself, however / itself is also part of the mount namespace so I can make certain guarantees about it, you can see that /usr/local/include doesn’t cause problems because in the case of /usr/local, I’m actually able to symlink that folder, but I can’t for /root/.

So, if there ends up being a way to trivially build in another folder. e.g., /var/root, I’d be able to symlink that into /snap and ACLiC would likely work fine, but this is a problem with the snapcraft build environment and not ROOT’s itself. On a technical purity level, I’d argue that this information shouldn’t be stored in libCore.so itself (especially when it appears compiledata.h has the exact same information and would be queryable at runtime), but practically, this whole problem can likely fixed on the snap side and amounts to an edge case bug in the greater context.

Uhm could this be another instance of https://github.com/root-project/root/issues/7108 ?

I don’t believe this is the same bug, on my local tests I was just trying to compile

int main( int argc, char *argv[] ){
    return 0;
}

I’ve asked Snapcraft upstream, and it does seem possible to use a different build directory. It’s a bit more involved than I’d like, but I’m looking into if it allows for a fix now.

Edit: And I’ll test it on some of the actual tutorial scripts to be sure :wink:

On one hand, it sounds like a relocatability issue, on the other there might be a reason why the interpreter needs, at runtime, exactly the same compiler that it was built with.

IIRC we do this to allow clang to pick up modules “from there” - even though the headers come from the PCM, not from disk. It’s a virtual filesystem. So IIRC it’s a side effect of us using a mechanism (C++ modules) that wasn’t designed for software distribution.

So having built the snap in a new build directory, the next problem to crop up was a hardcoded location for /usr/lib/x86_64-linux-gnu/libc_nonshared.a. Fortunately this was trivially symlinkable too, and as a result I can now do this:

ubuntu@impartial-mouflon:~/root-snap$ cp /snap/root-framework/x2/usr/local/tutorials/tmva/TMVAClassification.C TMVAClassification.C
ubuntu@impartial-mouflon:~/root-snap$ root
   ------------------------------------------------------------------
  | Welcome to ROOT 6.22/06                        https://root.cern |
  | (c) 1995-2020, The ROOT Team; conception: R. Brun, F. Rademakers |
  | Built for linuxx8664gcc on Mar 04 2021, 14:31:00                 |
  | From tags/v6-22-06@v6-22-06                                      |
  | Try '.help', '.demo', '.license', '.credits', '.quit'/'.q'       |
   ------------------------------------------------------------------

root [0] .x TMVAClassification.C+
Info in <TUnixSystem::ACLiC>: creating shared library /home/ubuntu/root-snap/./TMVAClassification_C.so

==> Start TMVAClassification
[TFile::Cp] Total 0.20 MB       |====================| 100.00 % [1.0 MB/s]
Info in <TFile::OpenFromCache>: using local cache copy of http://root.cern.ch/files/tmva_class_example.root [./files/tmva_class_example.root]
--- TMVAClassification       : Using input file: ./files/tmva_class_example.root
DataSetInfo              : [dataset] : Added class "Signal"
                         : Add Tree TreeS of type Signal with 6000 events
DataSetInfo              : [dataset] : Added class "Background"
                         : Add Tree TreeB of type Background with 6000 events
Factory                  : Booking method: Cuts
...

It’ll require more time to rework the nightly builds to actually make use of this but it currently looks promising enough, and if Snap manages to facilitate symlinking /root in the future I would be very happy.

This is now fixed in the stable release of the snap which is rolling out now.

Having explored all the options, in the end simplicity wins. There’s a script that runs during the compilation to generate compiledata.h called compiledata.sh, a small patch to this script means that it’s possible to adjust the values that get stored in libCore.so to compensate for the snap build process, and it’s much cleaner than the previous two options.

Thanks again for the initial bug report and all the advice :).

1 Like