rootlogon.C documentation

Following this discussion it seems that the correct syntax for rootlogon.C after version 6.08 is

void rootlogon() {
  gROOT->ProcessLine("#include \"TSystem.h\"");
}

and not (root before version 6.08)

gROOT->ProcessLine("#include \"TSystem.h\"");

It would be helpful to write that in the documentation and at least have tutorials/rootlogon.C in the correct shape . (I guess it only works here because it contains basically nothing)

In any ROOT version (also in ROOT 5), either an “unnamed” macro (I somehow remember that the “{” needed to be the very first line in an “unnamed” macro):

{
  // ...
}

or a “named” macro:

void rootlogon() {
  // ...
}

Yes you are right !

However, any documentation would be appreciated. rootlogon.C is becoming essential after adding new classes to ROOT stopped working in Cling . They will have to be “announced” through these include statements in the rootlogon.C

Continuing my rootlogon.C exploration, it used to be that the file was picked up
from either

  1. etc directory in the ROOT installation
  2. home directory
  3. pwd

That has changed:

root [0] TROOT::GetMacroPath()
(const char *) ".:/Users/eddyo/src/root_v6.26.00-cmake/macros"

to

  1. macros directory ROOT installation
  2. pwd

On a side note, where is now the initial macro path defined ? Apparently not
anymore in config/rootrc.in

grep MacroPath $(root-config --etcdir)/system.rootrc

To make things more complicated, create two simple files ("rootlogon.C" and “.rootlogon.C”):

{ // rootlogon.C ...
  std::cout << "rootlogon.C -> " << gInterpreter->GetCurrentMacroName() << "\n";
} // ... rootlogon.C
{ // .rootlogon.C ...
  std::cout << ".rootlogon.C -> " << gInterpreter->GetCurrentMacroName() << "\n";
} // ... .rootlogon.C

Copy both these files into your “${HOME}”, “${PWD}”, “$(root-config --etcdir)” and anywhere you think it may be relevant. Then start “root” and observe.

grep MacroPath $(root-config --etcdir)/system.rootrc

gives

#Unix.*.Root.MacroPath:      .:$(ROOTSYS)/macros
#WinNT.*.Root.MacroPath:     .;$(ROOTSYS)/macros

I thought these statements were commented out

grep Path $(root-config --etcdir)/system.rootrc

# Path used by dynamic loader to find shared libraries.
# Paths are different for Unix and Windows. The example shows the defaults
#Unix.*.Root.DynamicPath:    .:$(ROOTSYS)/lib
#WinNT.*.Root.DynamicPath:   .;$(ROOTSYS)/bin
# Path used to find macros.
# Paths are different for Unix and Windows. The example shows the defaults
#Unix.*.Root.MacroPath:      .:$(ROOTSYS)/macros
#WinNT.*.Root.MacroPath:     .;$(ROOTSYS)/macros
# Path used to find plugin macros.
# Paths are different for Unix and Windows. The example shows the defaults
#Unix.*.Root.PluginPath:     $(ROOTSYS)/etc/plugins
#WinNT.*.Root.PluginPath:    $(ROOTSYS)/etc/plugins
# Path where to look for TrueType fonts.
#*.*.Root.TTFontPath:        $(ROOTSYS)/fonts
Root.ShowPath:           false
#Unix.*.Gui.IconPath:         .:$(HOME)/icons:$(ROOTSYS)/icons:
#WinNT.*.Gui.IconPath:        .;$(HOME)/icons;$(ROOTSYS)/icons;
#HttpServ.JSRootPath:        $(ROOTSYS)/js
#WebGui.RootUi5Path:        $(ROOTSYS)/ui5
#ACLiC.IncludePaths:     -I/where/the/includes/are
# NetXNG.ClientMonitor        - Path to the client monitor library.
# Path to the X.509 user proxy
# Paths to the X.509 user certificate and key, in PEM format
# Path to the directory containing the CAs

First of all thank Wile_E_Coyote for helping me and prodding me in the right direction !

Wading through the lines of code, I (re)learned the following:

MacroPath :

It is currently not set in $(root-config --etcdir) , therefore the following piece of
code is triggered in core/base/src/TROOT.cxx :

////////////////////////////////////////////////////////////////////////////////
/// Get the macro directory in the installation. Static utility function.

const TString& TROOT::GetMacroDir() {
#ifdef ROOTMACRODIR
   if (IgnorePrefix()) {
#endif
      static TString rootmacrodir;
      if (rootmacrodir.IsNull()) {
         rootmacrodir = "macros";
         gSystem->PrependPathName(GetRootSys(), rootmacrodir);
      }
      return rootmacrodir;
#ifdef ROOTMACRODIR
   } else {
      const static TString rootmacrodir = ROOTMACRODIR;
      return rootmacrodir;
   }
#endif
}

resulting in rootmacrodir=(ROOTSYS)/macros

startup macro (i.e. rootlogon.C) :

  • search along the macrodir for a macro whose name is “.rootlogon.C” and/or
    what has been set in $(root-config --etcdir)/system.rootrc, let’s call it your-rootlogon.C .
    (This information is retrieved in TEnv.cxx):
# Rint (interactive ROOT executable) specific alias, logon and logoff macros.
Rint.Load:               rootalias.C
Rint.Logon:              rootlogon.C
Rint.Logoff:             rootlogoff.C
  • now the following piece of code is executed from the file
    core/rint/src/TRint.cxx:
////////////////////////////////////////////////////////////////////////////////
/// Execute logon macro's. There are three levels of logon macros that
/// will be executed: the system logon etc/system.rootlogon.C, the global
/// user logon ~/.rootlogon.C and the local ./.rootlogon.C. For backward
/// compatibility also the logon macro as specified by the Rint.Logon
/// environment setting, by default ./rootlogon.C, will be executed.
/// No logon macros will be executed when the system is started with
/// the -n option.

void TRint::ExecLogon()
{
   if (NoLogOpt()) return;

   TString name = ".rootlogon.C";
   TString sname = "system";
   sname += name;
   char *s = gSystem->ConcatFileName(TROOT::GetEtcDir(), sname);
   if (!gSystem->AccessPathName(s, kReadPermission)) {
      ProcessFile(s);
   }
   delete [] s;
   s = gSystem->ConcatFileName(gSystem->HomeDirectory(), name);
   if (!gSystem->AccessPathName(s, kReadPermission)) {
      ProcessFile(s);
   }
   delete [] s;
   // avoid executing ~/.rootlogon.C twice
   if (strcmp(gSystem->HomeDirectory(), gSystem->WorkingDirectory())) {
      if (!gSystem->AccessPathName(name, kReadPermission))
         ProcessFile(name);
   }

   // execute also the logon macro specified by "Rint.Logon"
   const char *logon = gEnv->GetValue("Rint.Logon", (char*)0);
   if (logon) {
      char *mac = gSystem->Which(TROOT::GetMacroPath(), logon, kReadPermission);
      if (mac)
         ProcessFile(logon);
      delete [] mac;
   }
}

In summary, execute ( if available) in the following order

  1. $(root-config --etcdir)/system.rootlogon.C
  2. ${HOME}/.rootlogon.C
  3. MacroPath/your-rootlogon.C

This information is either available in the documentation or should be added.

Now most users wonder why I care about these installation details, things work just
fine. But you are probably working in a collaboration (CMS/ATLAS etc)
which sets up your environment , taking care of all these details.
A complain by many (academic) users of ROOT is that knowledge of this wonderful
tool does not bring them very far in a job interview. Clearly it is not installed and
used as widely outside the physics community as we wish.
One reason is that installing these tools seamlessly in an existing production environment is not an easy task. Luckily, many knobs are available to accomplish this,
but sometimes the information is lacking.

Well, to be precise, the order is:

  1. $(root-config --etcdir)/system.rootlogon.C
  2. ${HOME}/.rootlogon.C
  3. ${PWD}/.rootlogon.C” but only if “${PWD}” != “${HOME}
  4. the file defined by “Rint.Logon” which exists in “TROOT::GetMacroPath()” (so, by default, it will be either “${PWD}/rootlogon.C” or “${ROOTSYS}/macros/rootlogon.C”)