Help figuring out linking error when compiling


Please read tips for efficient and successful posting and posting code

ROOT Version: 6.30
Platform: Ubuntu / Gitlab CI/CD


Dear ROOT support,

I am struggling with the compilation of a small project I am writing which uses ROOT. It works fine within a custom container that was provided to me by a colleague, but not when using a “standard” ROOT container (concretely, rootproject/root:6.30.04-ubuntu22.04). I assume it’s because some flags are not set up properly, but I am rather lost here.

The MakeFile looks as follows:

include ../standard.mk

# Target executables
TARGET_SELECTOR = SelectorFromJSON
SRC_FILES_SELECTOR = SelectorFromJSON.cc $(PREFIX)/Utils/Parser.cc
OBJ_FILES_SELECTOR = $(SRC_FILES_SELECTOR:%.cc=$(OBJ_DIR)/%.o)

all: $(TARGET_SELECTOR)

# Linking (compilation rule in standard.mk)
$(TARGET_SELECTOR): $(OBJ_FILES_SELECTOR)
        $(CXX) $(CXXFLAGS) $(INCLUDES) $(LIBS) -o $@ $^

# Clean rule
.PHONY: clean
clean:
        rm -rf  $(TARGET_SELECTOR) $(OBJ_FILES_SELECTOR)

where standard.mk looks like:

# Paths and Prefix
PREFIX = $(IRF_DIR)

# Object directory
OBJ_DIR = $(PREFIX)/build

# Include and library directories
INCLUDES = -I$(ROOTSYS)/include -I/usr/include/root/ -I$(PREFIX)

# Library paths
LIBS = -L$(PREFIX)/km3net-dataformat/lib -luuid `root-config --libs`

# Compiler and Flags
CXX = $(shell root-config --cxx)
CXXFLAGS = $(shell root-config --cflags) -Wall -fPIC

# Default object compilation rule
$(OBJ_DIR)/%.o: %.cc
        @mkdir -p $(dir $@)
        $(CXX) $(CXXFLAGS) $(INCLUDES) $(LIBS) -c $< -o $@

and before running make, I source the following:

#! /bin/bash

if [ -z $ROOTSYS ]; then
    echo "ERROR! IRF/setenv.sh environment variable ROOTSYS is not set"
    return 1
fi

# Determine the script directory
if [[ -n $BASH_SOURCE ]]; then
    # Bash: Use BASH_SOURCE[0]
    SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
else
    # Zsh: Use $0
    SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
fi

# Set IRF_DIR
export IRF_DIR="$SCRIPT_DIR"
export LD_LIBRARY_PATH=$IRF_DIR/lib:${LD_LIBRARY_PATH}
export LD_LIBRARY_PATH=$IRF_DIR/km3net-dataformat/lib:${LD_LIBRARY_PATH}

I also do source /opt/root/bin/thisroot.sh. But then I see the following error:

Selector:
/usr/bin/ld: /builds/oscillation/irf/build/SelectorFromJSON.o: in function `PrintTTreeNamesInTFile(TFile*)':
SelectorFromJSON.cc:(.text+0x472): undefined reference to `TString::TString()'
/usr/bin/ld: SelectorFromJSON.cc:(.text+0x4a2): undefined reference to `operator==(TString const&, char const*)'
/usr/bin/ld: SelectorFromJSON.cc:(.text+0x5ab): undefined reference to `TString::operator=(char const*)'
/usr/bin/ld: SelectorFromJSON.cc:(.text+0x5d7): undefined reference to `TString::~TString()'
/usr/bin/ld: SelectorFromJSON.cc:(.text+0x610): undefined reference to `TString::~TString()'
/usr/bin/ld: /builds/oscillation/irf/build/SelectorFromJSON.o: in function `main':
SelectorFromJSON.cc:(.text+0x6d8): undefined reference to `TCut::TCut()'
/usr/bin/ld: SelectorFromJSON.cc:(.text+0xc31): undefined reference to `TCut::operator=(char const*)'
/usr/bin/ld: SelectorFromJSON.cc:(.text+0xcf2): undefined reference to `TCut::operator=(char const*)'
/usr/bin/ld: SelectorFromJSON.cc:(.text+0x1140): undefined reference to `TFile::Open(char const*, char const*, char const*, int, int)'
/usr/bin/ld: SelectorFromJSON.cc:(.text+0x15db): undefined reference to `TFile::Open(char const*, char const*, char const*, int, int)'
/usr/bin/ld: SelectorFromJSON.cc:(.text+0x19ad): undefined reference to `TCut::~TCut()'
/usr/bin/ld: SelectorFromJSON.cc:(.text+0x1d73): undefined reference to `TCut::~TCut()'
/usr/bin/ld: /builds/oscillation/irf/build/SelectorFromJSON.o: in function `__static_initialization_and_destruction_0(int, int)':
SelectorFromJSON.cc:(.text+0x22d0): undefined reference to `TVersionCheck::TVersionCheck(int)'
/usr/bin/ld: /builds/oscillation/irf/build/SelectorFromJSON.o: in function `TIter::TIter(TCollection const*, bool)':
SelectorFromJSON.cc:(.text._ZN5TIterC2EPK11TCollectionb[_ZN5TIterC5EPK11TCollectionb]+0x1c): undefined reference to `vtable for TIter'
/usr/bin/ld: /builds/oscillation/irf/build/SelectorFromJSON.o: in function `TIter::~TIter()':
SelectorFromJSON.cc:(.text._ZN5TIterD2Ev[_ZN5TIterD5Ev]+0x13): undefined reference to `vtable for TIter'
collect2: error: ld returned 1 exit status
make[1]: *** [Makefile:12: SelectorFromJSON] Error 1
make: *** [Makefile:22: Selector] Error 2

Could I get some help figuring out what I am doing wrong? I tried searching the forums, but could not find an answer there.

Hello @FVazquez,

based on the errors, it looks like the ROOT libraries weren’t listed in the linker invocation. I see that you used root-config --libs, which should list them, but this doesn’t seem to have made it to linker invocation.
Could you check all lines that are invoked by make? The one just before the error is of most interest specifically. Probably, you want to check that this rule is invoked correctly:

$(OBJ_DIR)/%.o: %.cc

Thank you for your help!

So I split the make somewhat, to make sure only the minimum parts of the project get compiled. This is what I see now:

$ make

c++ -pthread -std=c++17 -m64 -I/opt/root/include -Wall -fPIC -I/opt/root/include -I/usr/include/root/ -I/builds/oscillation/irf -I/opt/root/include  -L/builds/oscillation/irf/km3net-dataformat/lib -luuid -L/opt/root/lib -lCore -lImt -lRIO -lNet -lHist -lGraf -lGraf3d -lGpad -lROOTVecOps -lTree -lTreePlayer -lRint -lPostscript -lMatrix -lPhysics -lMathCore -lThread -lMultiProc -lROOTDataFrame -Wl,-rpath,/opt/root/lib -pthread -lm -ldl -rdynamic -c SelectorFromJSON.cc -o /builds/oscillation/irf/build/SelectorFromJSON.o

c++ -pthread -std=c++17 -m64 -I/opt/root/include -Wall -fPIC -I/opt/root/include -I/usr/include/root/ -I/builds/oscillation/irf -I/opt/root/include  -L/builds/oscillation/irf/km3net-dataformat/lib -luuid -L/opt/root/lib -lCore -lImt -lRIO -lNet -lHist -lGraf -lGraf3d -lGpad -lROOTVecOps -lTree -lTreePlayer -lRint -lPostscript -lMatrix -lPhysics -lMathCore -lThread -lMultiProc -lROOTDataFrame -Wl,-rpath,/opt/root/lib -pthread -lm -ldl -rdynamic -c /builds/oscillation/irf/Utils/Parser.cc -o /builds/oscillation/irf/build//builds/oscillation/irf/Utils/Parser.o

c++ -pthread -std=c++17 -m64 -I/opt/root/include -Wall -fPIC -I/opt/root/include -I/usr/include/root/ -I/builds/oscillation/irf -I/opt/root/include  -L/builds/oscillation/irf/km3net-dataformat/lib -luuid -L/opt/root/lib -lCore -lImt -lRIO -lNet -lHist -lGraf -lGraf3d -lGpad -lROOTVecOps -lTree -lTreePlayer -lRint -lPostscript -lMatrix -lPhysics -lMathCore -lThread -lMultiProc -lROOTDataFrame -Wl,-rpath,/opt/root/lib -pthread -lm -ldl -rdynamic -o SelectorFromJSON /builds/oscillation/irf/build/SelectorFromJSON.o /builds/oscillation/irf/build//builds/oscillation/irf/Utils/Parser.o

/usr/bin/ld: /builds/oscillation/irf/build/SelectorFromJSON.o: in function `PrintTTreeNamesInTFile(TFile*)':
SelectorFromJSON.cc:(.text+0x472): undefined reference to `TString::TString()'
/usr/bin/ld: SelectorFromJSON.cc:(.text+0x4a2): undefined reference to `operator==(TString const&, char const*)'
/usr/bin/ld: SelectorFromJSON.cc:(.text+0x5ab): undefined reference to `TString::operator=(char const*)'
/usr/bin/ld: SelectorFromJSON.cc:(.text+0x5d7): undefined reference to `TString::~TString()'
/usr/bin/ld: SelectorFromJSON.cc:(.text+0x610): undefined reference to `TString::~TString()'

/usr/bin/ld: /builds/oscillation/irf/build/SelectorFromJSON.o: in function `main':
SelectorFromJSON.cc:(.text+0x6d8): undefined reference to `TCut::TCut()'
/usr/bin/ld: SelectorFromJSON.cc:(.text+0xc31): undefined reference to `TCut::operator=(char const*)'
/usr/bin/ld: SelectorFromJSON.cc:(.text+0xcf2): undefined reference to `TCut::operator=(char const*)'
/usr/bin/ld: SelectorFromJSON.cc:(.text+0x1140): undefined reference to `TFile::Open(char const*, char const*, char const*, int, int)'
/usr/bin/ld: SelectorFromJSON.cc:(.text+0x15db): undefined reference to `TFile::Open(char const*, char const*, char const*, int, int)'
/usr/bin/ld: SelectorFromJSON.cc:(.text+0x19ad): undefined reference to `TCut::~TCut()'
/usr/bin/ld: SelectorFromJSON.cc:(.text+0x1d73): undefined reference to `TCut::~TCut()'

/usr/bin/ld: /builds/oscillation/irf/build/SelectorFromJSON.o: in function `__static_initialization_and_destruction_0(int, int)':
SelectorFromJSON.cc:(.text+0x22d0): undefined reference to `TVersionCheck::TVersionCheck(int)'

/usr/bin/ld: /builds/oscillation/irf/build/SelectorFromJSON.o: in function `TIter::TIter(TCollection const*, bool)':
SelectorFromJSON.cc:(.text._ZN5TIterC2EPK11TCollectionb[_ZN5TIterC5EPK11TCollectionb]+0x1c): undefined reference to `vtable for TIter'

/usr/bin/ld: /builds/oscillation/irf/build/SelectorFromJSON.o: in function `TIter::~TIter()':
SelectorFromJSON.cc:(.text._ZN5TIterD2Ev[_ZN5TIterD5Ev]+0x13): undefined reference to `vtable for TIter'

collect2: error: ld returned 1 exit status
make: *** [Makefile:12: SelectorFromJSON] Error 1

As far as I can tell, the right flags are included both in the compiling and linking step, and yet somehow the linking is failing?

(Yes, the paths for the files in “build” are messed up, but I don’t think that’s the issue here).

$(CXX) $(CXXFLAGS) $(INCLUDES) -c $< -o $@

$(CXX) $(CXXFLAGS) -o $@ $^ $(LIBS)

That fixed it! Thank you very much for helping me out with my meager knowledge about compilers :slight_smile: