Compile and run from command prompt

Hi

I apologize if my question is stupid, but here it is :wink:

After making the class from the root file, I have the .C and .h files – Is there any way to compile and run “Loop()” from command block rather than everytime having to

[quote]root -l macro.C
macro m
m.Loop();
[/quote]

Thanks

Alex

A brutal fix …

echo 'gROOT->LoadMacro("macro.C"); macro m; m.Loop(); gSystem->Exit(0);' | root -b -l

… or …

root -b -l <<EOF
.L macro.C
macro m;
m.Loop();
.q
EOF

thanks! works!
-a

Both of these seem to work for me, but then the root session closes immediately after. Even when I remove “gSystem->Exit(0)” and “.q” from these lines, the macro runs and then root quits. Why is this? Is there any way to leave the root session open after the macro runs? (my .C file generates some plots on a canvas and they close along with the root session). Sorry, I’m still learning bash/root/C++.

ROOT Primer -> 3 ROOT Macros
ROOT User’s Guide -> Getting Started -> Start and Quit a ROOT Session

Thanks for the quick response. As helpful as these documents are, I don’t think they contain the answer to my problem. As the original poster described, I’ve made a class from a root file, I have .C and .h files, and so in order to compile and run “Loop()” I need three lines:

root -l macro.C macro m m.Loop();

The methods described in the documentation don’t (explicitly anyway) tell you how to deal with macros which don’t have the same name as the main function. For example, the first lines of my macro.c file look like [code]#define macro_cxx
#include “macro.h”

void macro::Loop()
{

}[/code]

The documentation seems to imply that I can conclude the macro.c file with something like:

#ifndef __CINT__ int main(){ Loop(); return 0; } #endifin order to make it a standalone application, but I’ve had no luck with that either. And besides that seems like overkill, when all I want to do is reduce 3 or four command prompt lines to 1. It seems like it should be a simple fix from pepe’s first or second suggestions.

This is working example. See comments how to compile (file name root.cpp, standard executable will have name a.out).

/*
NB: inverse quotes ``!
g++ $ROOTSYS/bin/root-config --cflags --glibs root.cpp

To build dictionaries see, e.g. xmltree.cpp. I compiled it using

rootcint -f xmltree_dict.cxx -c xmltree.h xmltree_linkdef.h
g++ $ROOTSYS/bin/root-config --cflags --glibs -o xmltree xmltree.cpp xmltree_dict.cxx

See details about dictionaries in ROOT User Guide,
chapter “Writing a Graphical User Interface”, part “A Standalone Example”
*/

#include <TRint.h> // the only include you need
//#include <TROOT.h> // uncomment to use global variables like gPad, etc.

#include
#include

#include <TH1.h>
#include <TCanvas.h>

using std::cout; using std::endl;

main(int argc, char argv[])
{
TRint
theApp = new TRint(“Rint”, &argc, argv, 0, 0, 1); // do not show splash screen

// code starts here

TH1F* h = new TH1F(“h”, “h”, 100, -3, 3);

h->FillRandom(“gaus”, 10000);

cout<< "h->GetMean() = " << h->GetMean() << " h->GetRMS() = " << h->GetRMS() <<endl;

new TCanvas();
h->Draw();

// work in command line mode
theApp->Run();
delete theApp;
}

Try to create and use a simple “RunMe.cxx” file:

#include "macro.C"

//
// "ROOT Script" entry point (the same name as the "filename's base").
//
// [bash/csh] root RunMe.cxx
// [bash/csh] root RunMe.cxx++
// root [0] .x RunMe.cxx
// root [0] .x RunMe.cxx++
//
void RunMe(void)
{
  macro m;
  m.Loop();
}

#if !defined(__CINT__) && !defined(__ACLIC__)
//
// "Standalone Application" entry point ("main").
//
// `root-config --cxx --cflags` -o RunMe RunMe.cxx `root-config --libs`
// ./RunMe
//
int main(int /*argc*/, char ** /*argv*/)
{
  RunMe(); // just call the "ROOT Script"
  return 0;
}
#endif /* !defined(__CINT__) && !defined(__ACLIC__) */

Thank you Wile! I got it working with your script.

Now I’ll just try to understand it :slight_smile:

zatserkl - I fooled around with yours for a while, but I had no luck. Thanks though.

I just want to follow up here, for the record, and in case anyone is following.

The command that I was looking for is:gROOT->ProcessLine("line of root command");

A macro which would normally run with the initialization of ROOT plus three separate root commands:

$ root -l
root [0] .L Macro.C
root [1] Macro t
root [2] t.Loop()
[/code] can be reduced to a single line:
[code]$ root -l runme.C[/code]

Where runme.C contains exactly:
[code]void runme(){
    gROOT->ProcessLine(".L Macro.C");
    gROOT->ProcessLine("Macro t");
    gROOT->ProcessLine("t.Loop()");
}

Protip: To run a different file (e.g. Macro_2.C), instead of making a new runme file, use the “sed” bash shortcut to exchange all instances of “Macro” in runme.C into “Macro_2”:$ sed -i "" 's/Macro/Macro_2/g' runme.C(this is the Mac specific syntax for “sed”. See your own man page.)

1 Like

You can pass command-line arguments from your shell to your named macro as well. The macro sees it as a char *. Here is an old post of mine doing that: [url]TString, stdarg, variable argument list?

So you could have your runme.C look like:

#include "TString.h"
#include "TROOT.h"

void runme(char * arg){
gROOT->ProcessLine(TString::Format(".L %s.C",arg);
gROOT->ProcessLine(TString::Format("%s t",arg);
gROOT->ProcessLine("t.Loop()");
}

then as long as your macro/macro_2 defines a class with a Loop() method, you can call any of your macros with something like:

Even better, thanks J.F.

with your written .cpp file, say foo.cpp as:
#include
using namespace std;
void foo( ) {

}

you can compile and run the .cpp from command prompt by single line
root -q -l foo.cpp

-q will automatically exit the ROOT prompt after compile.

You can also write a Makefile. This allows you to run series of processes.
For example in Makefile, do:

.PHONY: run

run:
root -q -l foo.cpp && python foo.py

Hi @Pepe_Le_Pew @Wile_E_Coyote @jfcaron ,
I have a very similar situation as this post here. When I do run a macro of similar kind,
I’m attaching the macro I use for this.
RunMixLoop.C (278 Bytes)
I get the error

Error: Symbol PtCorr_mix t is not defined in current scope  (tmpfile):1:
*** Interpreter error recovered ***
Error: Symbol t is not defined in current scope  (tmpfile):1:
Error: Failed to evaluate t.Loop()
*** Interpreter error recovered *** ```

Is the “PtCorr_mix” class defined in the “PtCorr_mix.C” file?

Hi @Wile_E_Coyote ,
Thank you for the quick reply.
Hmm, there is the definition of #define PtCorr_mix_cxx
Here’s the file
PtCorr_mix.C (5.9 KB)
PtCorr_mix.h (4.3 KB)

I guess you have bugs in your “PtCorr_mix.C” file, so it is not properly loaded.
For example, the source code after “}// Mixed event loop ends” is a lulu.

Try to load it with ACLiC (fix all reported problems):
root [0] .L PtCorr_mix.C++

1 Like

@Wile_E_Coyote
Thank you!, I hope it is this silly mistake that’s causing the issue.

Cheers,
Rutik