導入
ここでは、CERNが配布して知るROOTを使ったMakefileを作成した際に躓いたメモを書く。
環境
- Ubuntu 18.04.4 LTS
- ROOT 6.20/04
- gcc 7.5.0
- GNU Make 4.1
問題点
いままで別のバージョンのLinuxなどで使ってきた以下のMakefileが使えなくなってしまった。
いままで使っていたMakefilは以下のとおりである。
TARGET = macro
SRCS = $(TARGET).cc
OBJS = $(TARGET).o
ROOTCFLAGS = $(shell root-config --cflags)
ROOTLIBS = $(shell root-config --libs)
ROOTGLIBS = $(shell root-config --glibs)
CXXFLAGS = $(ROOTCFLAGS) -Wall -fPIC
CXXLIBS = $(ROOTLIBS)
CC = g++
$(TARGET): $(OBJS)
$(CC) $(CXXLIBS) $(OBJS) -o $@
# suffix rule
.cc.o:
$(CC) $(CXXFLAGS) -c $<
# clean
clean:
rm -f $(TARGET) $(OBJS)
基本的にはこれで使えたはずなのだが、本環境に移行した際に次のようなエラーが発生し、makeできなくなってしまった。
macro.o: 関数 `__static_initialization_and_destruction_0(int, int)' 内:
macro.cpp:(.text+0xcca): `TVersionCheck::TVersionCheck(int)' に対する定義されていない参照です
collect2: error: ld returned 1 exit status
Makefile:31: recipe for target 'macro' failed
make: *** [parmteqm2gpt] Error 1
ROOT forumを見てみると $ROOTSYS/lib が正しく通っていないことが原因なようだが、確認してみたところPATHは正しく通っていることがわかった。正確な話は後日気が向いたら追記していきたい。
該当するROOT forumのリンクは以下のものである。
https://root-forum.cern.ch/t/undefined-reference-to-tversioncheck-tversioncheck-int/21123/12
解決策
さて、上記問題点の原因を探るためにいろいろと探ってみたら、次のようなことがわかった。
1) libへのパスは通っている
2) ターミナル上からのコンパイル
g++ `root-config --libs --cflags` macro.cpp -o macro
は通らない。
3)オブジェクト生成を経由する
g++ $(root-config --cflags) -c macro.cpp
g++ $(root-config --libs) macro.o -o macro
は通らない。
4) ターミナル上からのコンパイルでlibの引用を分割した
g++ $(root-config --libs) $(root-config --cflags) macro.cpp -o macro
は通る(なんで!?)
そこで以下のようにMakefileを書き換えてみた。
TARGET = macro
SRCS = $(TARGET).cpp
OBJS = $(TARGET).o
ROOTCFLAGS = $(shell root-config --cflags)
ROOTLIBS = $(shell root-config --libs)
ROOTGLIBS = $(shell root-config --glibs)
CXXFLAGS = $(ROOTCFLAGS) -Wall -fPIC
CXXLIBS = $(ROOTLIBS)
CC = g++
$(TARGET):
$(CC) $(SRCS) $(CXXLIBS) $(CXXFLAGS) -o $@
# # suffix rule
# .cc.o:
# $(CC) $(CXXFLAGS) -c $<
# clean
clean:
rm -f $(TARGET) $(OBJS)
なにをやったかというと、ただソースファイルから直接実行ファイルを生成しただけである。
こうすると、エラーを吐き出さずに問題なくmakeできた。
まとめ
自分の環境だと、従来のコンパイルの方法でうまくいかないことがわかった。この問題は、libの引数を分割し、一括で実行ファイルを生成する方法だとうまく行くことがわかった。しかし、原因はよくわかっていない。
*用語に関して間違った使い方をしているかもしれません。ぜひご指摘をおねがいいたします。また、上記エラーの原因について初歩的なミスが考えられるので、もしご存じの方がいらっしゃったら教えていただけるとうれしいです。