Позвольте мне сначала установить контекст, это Корень Церна а также CINT а также ACLiC и т.п.
Предположим, у меня есть основной macro
названный macro.cpp
и два заголовка h1.cpp
(содержит определение функции) и h1.h
содержащий объявление функции, определенной в h1.cpp
Точно так же у меня есть h2.cpp
а также h2.h
, Основная программа macro.cpp
вызывает эти функции внутри h1
а также h2
, Я успешно компилировал исходные файлы, используя:
root [0] .L h1.cpp+
root [1] .L h2.cpp+
root [2] .L macro.cpp+
который породил три .so
файлы macro_cpp.so
, h1_cpp.so
а также h2_cpp.so
, Я хочу знать, что с ними делать? Как я link
их, чтобы у меня было что-то вродеmacro.out
«или что-то подобное (сингл executable
какой-то файл), который я могу выполнить (хотя я не знаю, как!) и достичь того, чего я хотел достичь с помощью макроса.
Замечания: Если я просто загружу все файлы, используя .L file_name.cpp
и т.д. и просто выполнить основной макрос, используя .x macro.cpp
тогда все отлично работает и у меня есть результаты, но это не то, что я хочу! Я хочу скомпилировать, как мы делаем в обычном g++
и, кстати, на каждом форуме все продолжают давать советы по компиляции с использованием .L file_name.cpp+
или же ++
.. Мне бы очень хотелось узнать всю историю. Потому что никто не может объяснить дальше .L file_name.cpp+
.. что дальше ? Что делать с .so
и т.п.
Я новичок, буду очень признателен за простой и пошаговый ответ и объяснение.
Благодарю.
Edit-1: Я работаю с:
g ++ (Ubuntu 5.4.0-6ubuntu1 ~ 16.04.4) 5.4.0 20160609
Edit-2: Корень связанной информации:
ROOT 5.34 / 36 (v5-34-36 @ v5-34-36, 07 декабря 2016 г., 23:31:51 на linuxx8664gcc)
CINT / ROOT C / C ++ Версия интерпретатора 5.18.00, 2 июля 2010 г.
Если вы хотите скомпилировать и связать, вы можете использовать стандартный компилятор вместо Cint / Aclic.
Например, если вы работаете на платформе * nix, вы можете использовать приведенные ниже примеры файлов:
h1.h
int add_one(int a);
h1.cpp
#include "h1.h"
int add_one(int a)
{
return a+1;
}
h2.h
#include <TLorentzVector.h>
TLorentzVector multiply_by_two(const TLorentzVector v);
h2.cpp
#include "h2.h"
TLorentzVector multiply_by_two(const TLorentzVector v)
{
return 2.0*v;
}
macro.cpp
#include "h1.h"#include "h2.h"
#include <TLorentzVector.h>
#include <iostream>
using std::cout;
using std::endl;
int main()
{
int a = 0;
TLorentzVector v;
v.SetPtEtaPhiM(1.0, 0.0, 0.0, 0.0);
cout<<"calling add_one on "<<a<<": "<<add_one(a)<<endl;
cout<<"calling multiply_by_two on "<<v.Pt()<<": "<<multiply_by_two(v).Pt()<<endl;
return 0;
}
Тогда вы можете скомпилировать с
g++ -c -g -Wall `root-config --cflags` h1.cpp
g++ -c -g -Wall `root-config --cflags` h2.cpp
g++ -c -g -Wall `root-config --cflags` macro.cpp
и связать с
g++ `root-config --glibs` h1.o h2.o macro.o
Исполняемый файл будет a.out
:
$ ./a.out
calling add_one on 0: 1
calling multiply_by_two on 1: 2
Вы можете положить эти g++
Команды в сценарии или, когда вы начинаете иметь несколько файлов и каталогов, вы можете написать свой make-файл (или cmake). Для этого последнего шага, см., Например, учебник здесь
http://www-pnp.physics.ox.ac.uk/~brisbane/Teaching/Makefiles/Tutorial_1_Makefiles_and_ROOT.pdf
Примечание 1: одно из преимуществ использования g++
является то, что вы получите четкие сообщения об ошибках, когда что-то не компилируется. Сообщения об ошибках от Cint могут
быть трудным для понимания — хотя это очень улучшено в root 6 с Cling.
Заметка 2Еще одно преимущество использования стандартного компилятора заключается в том, что вы сможете легко связать ваш основной исполняемый файл с библиотеками, отличными от root.
Этот ответ основан в основном на ответе user2148414, но если последует ответ, вы заметите, что были некоторые проблемы с методом связывания исходных файлов (* .cpp). Мой ответ также касается другого важного объекта, называемого TApplication это сыграет решающую роль в таких приложениях с корневыми библиотеками. Следующий шаг связывания:
g++ `root-config --glibs` h1.o h2.o macro.o
скорее всего, будет отображаться множество ошибок с жалобами на корневые объекты, такие как TWhatever
(в user2148414ответ TLorentzVector покажет проблемы). В комментариях к этому ответу можно найти обсуждение включения различных библиотек физики, которые могут решить эту проблему, но без обсуждения этого (и мне это неудобно :)) позвольте мне записать команду, которая решает все.
Эта процедура является однострочной, которая не требует компиляции отдельных файлов, создания файлов * .cpp и * .h, как описано в этот ответ затем скомпилируйте и скомпонуйте и создайте один исполняемый файл с именем «someExecutable», используя:
g++ macro.cpp h1.cpp h2.cpp `root-config --libs --cflags` -o someExecutable
или лучше (и это надо делать)
g++ -Wall -Wextra -Werror -pedantic -std=c++14 macro.cpp h1.cpp h2.cpp `root-config --libs --cflags` -o someExecutable
Это решит мой оригинальный ответ, но для полноты я хотел бы добавить еще несколько вещей.
TApplication
Моей первоначальной мотивацией было создать приложение, которое общается сROOT«но я не хотел работать с оболочкой ROOT, CINT, ACLiC и т. Д. И хотел полностью работать с g ++. user2148414и мой ответ решит часть создания приложения, но приложение не будет служить какой-либо цели, оно будет работать, создавать гистограммы, рисовать их и делать все, но все холсты закроются в конце, когда код достигнет «return 0;
«Чтобы держать полотна открытыми, нам понадобится»TApplication
«. Так что рассмотрим main
из user2148414ответ, я собираюсь включить еще две строки и два аргумента main
:
macro.cpp
#include "h1.h"#include "h2.h"
#include <TLorentzVector.h>
#include <iostream>
using std::cout;
using std::endl;
int main(int argc, char* argv[]) //introduced arguments to main
{
// here I introduce TApplication
TApplication* SomeApp = new TApplication("SomeApp",&argc, argv);
int a = 0;
TLorentzVector v;
v.SetPtEtaPhiM(1.0, 0.0, 0.0, 0.0);
cout<<"calling add_one on "<<a<<": "<<add_one(a)<<endl;
cout<<"calling multiply_by_two on "<<v.Pt()<<": "<<multiply_by_two(v).Pt()<<endl;
//and just before returning 0
SomeApp->Run();
return 0;
}