1

I am trying to write a small program linking against a shared library (*.so).But when I try to compile the program, I get an error saying 'undefined reference' to "the function"

Content of the program file.

user@ubuntu:~/Perforce/user_ubuntu_3105/wp/eng/main/src/libfc/37D03B6/bin$ cat test.cpp 
#include <iostream>
#include <vector>
#include <memory>
#include "InfoModel.h"

int main() 
{
    libfc::InfoModel & model = libfc::InfoModel::instance();
    return 0;
}

Compiling this I get the error 'undefined reference to '

user@ubuntu:~/Perforce/user_ubuntu_3105/wp/eng/main/src/libfc/37D03B6/bin$ g++ -Wall -W -std=c++0x test.cpp -L. -lfc -o rst
test.cpp: In function ‘int main()’:
test.cpp:9:21: warning: unused variable ‘model’ [-Wunused-variable]
libfc::InfoModel & model = libfc::InfoModel::instance();
                 ^
/tmp/ccFtLDxc.o: In function `main':
test.cpp:(.text+0x9): undefined reference to `libfc::InfoModel::instance()'
collect2: error: ld returned 1 exit status

But when I look at the symbols in the .so file, I see the symbol there.

user@ubuntu:~/Perforce/user_ubuntu_3105/wp/eng/main/src/libfc/37D03B6/bin$ nm --demangle libfc.so | grep InfoModel 
0000000000007e40 t _GLOBAL__sub_I_InfoModel.cpp
00000000002464a0 b guard variable for libfc::InfoModel::instance()::instance_
0000000000010260 t libfc::InfoModel::add_unknown(unsigned int, unsigned short, unsigned short)
0000000000010520 t libfc::InfoModel::registerIEType(libfc::IEType const*)
000000000000f550 t libfc::InfoModel::add(libfc::InfoElement const&)
0000000000012980 t libfc::InfoModel::add(std::string const&)
0000000000010a60 t libfc::InfoModel::instance()
00000000000106f0 t libfc::InfoModel::initTypes()
00000000000108f0 t libfc::InfoModel::InfoModel()
00000000000108f0 t libfc::InfoModel::InfoModel()
0000000000027ae0 t libfc::InfoModel::~InfoModel()
0000000000027ae0 t libfc::InfoModel::~InfoModel()
0000000000010b00 t libfc::InfoModel::parseIESpec(std::string const&) const
000000000000ee80 t libfc::InfoModel::lookupIEType(unsigned int) const
000000000000ed40 t libfc::InfoModel::lookupIEType(std::string const&) const
000000000000ef20 t libfc::InfoModel::dump(std::ostream&) const
000000000000f0c0 t libfc::InfoModel::lookupIE(unsigned int, unsigned short, unsigned short) const
000000000000f1b0 t libfc::InfoModel::lookupIE(libfc::InfoElement const&) const
0000000000012840 t libfc::InfoModel::lookupIE(std::string const&) const
000000000000f410 t libfc::InfoModel::lookupIE2(unsigned int, std::string const&, unsigned short, unsigned short) const
00000000002463a0 b libfc::InfoModel::instance()::instance_

I also did this.

user@ubuntu:~/Perforce/user_ubuntu_3105/wp/eng/main/src/libfc/37D03B6/bin$ readelf -s libfc.so | grep FILE 
34: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS EncodePlan.cpp
43: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS InfoElement.cpp
49: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS FileExportDestination.cpp
53: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS IETemplate.cpp
58: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS IEType.cpp
104: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS InfoModel.cpp
113: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS libfc.cpp
118: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS PlacementExporter2.cpp
124: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS PlacementTemplate.cpp
129: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS TemplateState.cpp
135: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS test.cpp
141: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS UdpSocketExportDestinatio
149: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS crtstuff.c
158: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS BasicOctetArray.cpp
159: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS Exception.cpp
160: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS ExportError.cpp
161: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS FormatError.cpp
162: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS IESpecError.cpp
163: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS error_code.cpp
187: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS crtstuff.c
190: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS

Update: The make file to build this shared library is

PLUGIN          = libfc
OUTPUT_DIR      = bin
OUTPUT          = $(OUTPUT_DIR)/$(PLUGIN).so
PLUG_SRC        = src
EXCEPTION_SRC   = src/exceptions
CPP             = g++
THIRD_PARTY_DIR = ../../../../../third-party
BOOST_DIR       = $(THIRD_PARTY_DIR)/boost/1.66.0
G3LOG_DIR       = $(THIRD_PARTY_DIR)/g3log/2017-07-18_g3log
FLAGS           = -c -std=c++0x -fvisibility-inlines-hidden -pthread \
              -fPIC -fvisibility=hidden -fno-omit-frame-pointer -fpermissive 
MACROS          = -D_libfc_HAVE_NIXIO -U_libfc_HAVE_LOG4CPLUS_ -U_libfc_HAVE_WANDIO_
INCLUDES        = -I$(PLUG_SRC) \
              -I$(EXCEPTION_SRC) \
              -I$(BOOST_DIR) \
              -I$(G3LOG_DIR)/src \
              -I$(G3LOG_DIR)/include
LFLAGS          = -shared -lpthread -L$(G3LOG_DIR)/build -lg3logger
CPPFLAGS     = $(FLAGS) $(MACROS) $(INCLUDES)  
LDFLAGS      = $(LFLAGS)
ifeq ($(BUILD),DEBUG)
CPPFLAGS += -ggdb3 -O0 
else
CPPFLAGS += -g -Wall -O2 -D NDEBUG
LDFLAGS += -flto 
endif

# compile static boost lib as
# ./bjam --toolset=gcc address-model=64 cxxflags=-fPIC cflags=-fPIC 
variant=release threading=multi link=static --with-system stage
BOOST_LIBS      = $(BOOST_DIR)/stage/lib/libboost_system.a
OBJ_DIR         = obj
PLUG_OBJS       = $(patsubst %.cpp,$(OBJ_DIR)/%.o,$(subst 
$(PLUG_SRC)/,,$(wildcard $(PLUG_SRC)/*.cpp)))
FRAME_OBJS      = $(patsubst %.cpp,$(OBJ_DIR)/%.o,$(subst 
$(EXCEPTION_SRC)/,,$(wildcard $(EXCEPTION_SRC)/*.cpp)))
VPATH           = $(PLUG_SRC) $(EXCEPTION_SRC)

all: $(PLUGIN)
$(PLUG_OBJS): $(OBJ_DIR)/%.o: %.cpp
   $(CPP) $(CPPFLAGS) -o $@ $<
$(FRAME_OBJS): $(OBJ_DIR)/%.o: %.cpp
   $(CPP) $(CPPFLAGS) -o $@ $<
$(PLUG_OBJS) $(FRAME_OBJS): | $(OBJ_DIR)
$(OBJ_DIR):
   mkdir $(OBJ_DIR)
$(OUTPUT): | $(OUTPUT_DIR)
$(OUTPUT_DIR):
   mkdir $(OUTPUT_DIR)
$(PLUGIN): $(PLUG_OBJS) $(FRAME_OBJS) $(OUTPUT)
   $(CPP) $(LDFLAGS) -o $(OUTPUT)  $(PLUG_OBJS) $(FRAME_OBJS) $(BOOST_LIBS)

.PHONY: clean
clean:
   rm -f $(PLUG_OBJS) $(FRAME_OBJS) $(OUTPUT)
   rm -rf $(OBJ_DIR)
   rm -rf $(OUTPUT_DIR)

And the output of make is

user@ubuntu:~/Perforce/sselvam_ubuntu_3105/wp/eng/main/src/libfc/37D03B6$ make all 
mkdir obj
g++ -c -std=c++0x -fvisibility-inlines-hidden -pthread -fPIC -fvisibility=hidden -fno-omit-frame-pointer -fpermissive  -D_libfc_HAVE_NIXIO -U_libfc_HAVE_LOG4CPLUS_ -U_libfc_HAVE_WANDIO_ -Isrc -Isrc/exceptions -I../../../../../third-party/boost/1.66.0 -I../../../../../third-party/g3log/2017-07-18_g3log/src -I../../../../../third-party/g3log/2017-07-18_g3log/include -g -Wall -O2 -D NDEBUG -o obj/BasicOctetArray.o src/BasicOctetArray.cpp
g++ -c -std=c++0x -fvisibility-inlines-hidden -pthread -fPIC -fvisibility=hidden -fno-omit-frame-pointer -fpermissive  -D_libfc_HAVE_NIXIO -U_libfc_HAVE_LOG4CPLUS_ -U_libfc_HAVE_WANDIO_ -Isrc -Isrc/exceptions -I../../../../../third-party/boost/1.66.0 -I../../../../../third-party/g3log/2017-07-18_g3log/src -I../../../../../third-party/g3log/2017-07-18_g3log/include -g -Wall -O2 -D NDEBUG -o obj/EncodePlan.o src/EncodePlan.cpp
src/EncodePlan.cpp: In constructor ‘libfc::EncodePlan2::EncodePlan2(const libfc::PlacementTemplate*)’:
src/EncodePlan.cpp:90:9: warning: unused variable ‘ie_present’ [-Wunused-variable]
bool ie_present
     ^
g++ -c -std=c++0x -fvisibility-inlines-hidden -pthread -fPIC -fvisibility=hidden -fno-omit-frame-pointer -fpermissive  -D_libfc_HAVE_NIXIO -U_libfc_HAVE_LOG4CPLUS_ -U_libfc_HAVE_WANDIO_ -Isrc -Isrc/exceptions -I../../../../../third-party/boost/1.66.0 -I../../../../../third-party/g3log/2017-07-18_g3log/src -I../../../../../third-party/g3log/2017-07-18_g3log/include -g -Wall -O2 -D NDEBUG -o obj/FileExportDestination.o src/FileExportDestination.cpp
g++ -c -std=c++0x -fvisibility-inlines-hidden -pthread -fPIC -fvisibility=hidden -fno-omit-frame-pointer -fpermissive  -D_libfc_HAVE_NIXIO -U_libfc_HAVE_LOG4CPLUS_ -U_libfc_HAVE_WANDIO_ -Isrc -Isrc/exceptions -I../../../../../third-party/boost/1.66.0 -I../../../../../third-party/g3log/2017-07-18_g3log/src -I../../../../../third-party/g3log/2017-07-18_g3log/include -g -Wall -O2 -D NDEBUG -o obj/IETemplate.o src/IETemplate.cpp
 g++ -c -std=c++0x -fvisibility-inlines-hidden -pthread -fPIC -fvisibility=hidden -fno-omit-frame-pointer -fpermissive  -D_libfc_HAVE_NIXIO -U_libfc_HAVE_LOG4CPLUS_ -U_libfc_HAVE_WANDIO_ -Isrc -Isrc/exceptions -I../../../../../third-party/boost/1.66.0 -I../../../../../third-party/g3log/2017-07-18_g3log/src -I../../../../../third-party/g3log/2017-07-18_g3log/include -g -Wall -O2 -D NDEBUG -o obj/IEType.o src/IEType.cpp
 g++ -c -std=c++0x -fvisibility-inlines-hidden -pthread -fPIC -fvisibility=hidden -fno-omit-frame-pointer -fpermissive  -D_libfc_HAVE_NIXIO -U_libfc_HAVE_LOG4CPLUS_ -U_libfc_HAVE_WANDIO_ -Isrc -Isrc/exceptions -I../../../../../third-party/boost/1.66.0 -I../../../../../third-party/g3log/2017-07-18_g3log/src -I../../../../../third-party/g3log/2017-07-18_g3log/include -g -Wall -O2 -D NDEBUG -o obj/InfoElement.o src/InfoElement.cpp
g++ -c -std=c++0x -fvisibility-inlines-hidden -pthread -fPIC -fvisibility=hidden -fno-omit-frame-pointer -fpermissive  -D_libfc_HAVE_NIXIO -U_libfc_HAVE_LOG4CPLUS_ -U_libfc_HAVE_WANDIO_ -Isrc -Isrc/exceptions -I../../../../../third-party/boost/1.66.0 -I../../../../../third-party/g3log/2017-07-18_g3log/src -I../../../../../third-party/g3log/2017-07-18_g3log/include -g -Wall -O2 -D NDEBUG -o obj/InfoModel.o src/InfoModel.cpp
g++ -c -std=c++0x -fvisibility-inlines-hidden -pthread -fPIC -fvisibility=hidden -fno-omit-frame-pointer -fpermissive  -D_libfc_HAVE_NIXIO -U_libfc_HAVE_LOG4CPLUS_ -U_libfc_HAVE_WANDIO_ -Isrc -Isrc/exceptions -I../../../../../third-party/boost/1.66.0 -I../../../../../third-party/g3log/2017-07-18_g3log/src -I../../../../../third-party/g3log/2017-07-18_g3log/include -g -Wall -O2 -D NDEBUG -o obj/libfc.o src/libfc.cpp
g++ -c -std=c++0x -fvisibility-inlines-hidden -pthread -fPIC -fvisibility=hidden -fno-omit-frame-pointer -fpermissive  -D_libfc_HAVE_NIXIO -U_libfc_HAVE_LOG4CPLUS_ -U_libfc_HAVE_WANDIO_ -Isrc -Isrc/exceptions -I../../../../../third-party/boost/1.66.0 -I../../../../../third-party/g3log/2017-07-18_g3log/src -I../../../../../third-party/g3log/2017-07-18_g3log/include -g -Wall -O2 -D NDEBUG -o obj/PlacementExporter2.o src/PlacementExporter2.cpp
g++ -c -std=c++0x -fvisibility-inlines-hidden -pthread -fPIC -fvisibility=hidden -fno-omit-frame-pointer -fpermissive  -D_libfc_HAVE_NIXIO -U_libfc_HAVE_LOG4CPLUS_ -U_libfc_HAVE_WANDIO_ -Isrc -Isrc/exceptions -I../../../../../third-party/boost/1.66.0 -I../../../../../third-party/g3log/2017-07-18_g3log/src -I../../../../../third-party/g3log/2017-07-18_g3log/include -g -Wall -O2 -D NDEBUG -o obj/PlacementTemplate.o src/PlacementTemplate.cpp
g++ -c -std=c++0x -fvisibility-inlines-hidden -pthread -fPIC -fvisibility=hidden -fno-omit-frame-pointer -fpermissive  -D_libfc_HAVE_NIXIO -U_libfc_HAVE_LOG4CPLUS_ -U_libfc_HAVE_WANDIO_ -Isrc -Isrc/exceptions -I../../../../../third-party/boost/1.66.0 -I../../../../../third-party/g3log/2017-07-18_g3log/src -I../../../../../third-party/g3log/2017-07-18_g3log/include -g -Wall -O2 -D NDEBUG -o obj/TemplateState.o src/TemplateState.cpp
g++ -c -std=c++0x -fvisibility-inlines-hidden -pthread -fPIC -fvisibility=hidden -fno-omit-frame-pointer -fpermissive  -D_libfc_HAVE_NIXIO -U_libfc_HAVE_LOG4CPLUS_ -U_libfc_HAVE_WANDIO_ -Isrc -Isrc/exceptions -I../../../../../third-party/boost/1.66.0 -I../../../../../third-party/g3log/2017-07-18_g3log/src -I../../../../../third-party/g3log/2017-07-18_g3log/include -g -Wall -O2 -D NDEBUG -o obj/UdpSocketExportDestination.o src/UdpSocketExportDestination.cpp
g++ -c -std=c++0x -fvisibility-inlines-hidden -pthread -fPIC -fvisibility=hidden -fno-omit-frame-pointer -fpermissive  -D_libfc_HAVE_NIXIO -U_libfc_HAVE_LOG4CPLUS_ -U_libfc_HAVE_WANDIO_ -Isrc -Isrc/exceptions -I../../../../../third-party/boost/1.66.0 -I../../../../../third-party/g3log/2017-07-18_g3log/src -I../../../../../third-party/g3log/2017-07-18_g3log/include -g -Wall -O2 -D NDEBUG -o obj/Exception.o src/exceptions/Exception.cpp
g++ -c -std=c++0x -fvisibility-inlines-hidden -pthread -fPIC -fvisibility=hidden -fno-omit-frame-pointer -fpermissive  -D_libfc_HAVE_NIXIO -U_libfc_HAVE_LOG4CPLUS_ -U_libfc_HAVE_WANDIO_ -Isrc -Isrc/exceptions -I../../../../../third-party/boost/1.66.0 -I../../../../../third-party/g3log/2017-07-18_g3log/src -I../../../../../third-party/g3log/2017-07-18_g3log/include -g -Wall -O2 -D NDEBUG -o obj/ExportError.o src/exceptions/ExportError.cpp
g++ -c -std=c++0x -fvisibility-inlines-hidden -pthread -fPIC -fvisibility=hidden -fno-omit-frame-pointer -fpermissive  -D_libfc_HAVE_NIXIO -U_libfc_HAVE_LOG4CPLUS_ -U_libfc_HAVE_WANDIO_ -Isrc -Isrc/exceptions -I../../../../../third-party/boost/1.66.0 -I../../../../../third-party/g3log/2017-07-18_g3log/src -I../../../../../third-party/g3log/2017-07-18_g3log/include -g -Wall -O2 -D NDEBUG -o obj/FormatError.o src/exceptions/FormatError.cpp
g++ -c -std=c++0x -fvisibility-inlines-hidden -pthread -fPIC -fvisibility=hidden -fno-omit-frame-pointer -fpermissive  -D_libfc_HAVE_NIXIO -U_libfc_HAVE_LOG4CPLUS_ -U_libfc_HAVE_WANDIO_ -Isrc -Isrc/exceptions -I../../../../../third-party/boost/1.66.0 -I../../../../../third-party/g3log/2017-07-18_g3log/src -I../../../../../third-party/g3log/2017-07-18_g3log/include -g -Wall -O2 -D NDEBUG -o obj/IESpecError.o src/exceptions/IESpecError.cpp
mkdir bin
g++ -shared -lpthread -L../../../../../third-party/g3log/2017-07-18_g3log/build -lg3logger -flto  -o bin/libfc.so  obj/BasicOctetArray.o obj/EncodePlan.o obj/FileExportDestination.o obj/IETemplate.o obj/IEType.o obj/InfoElement.o obj/InfoModel.o obj/libfc.o obj/PlacementExporter2.o obj/PlacementTemplate.o obj/TemplateState.o obj/UdpSocketExportDestination.o obj/Exception.o obj/ExportError.o obj/FormatError.o obj/IESpecError.o ../../../../../third-party/boost/1.66.0/stage/lib/libboost_system.a

Any help would be really helpful.

ead
  • 32,758
  • 6
  • 90
  • 153
user1429322
  • 1,266
  • 2
  • 24
  • 38
  • @πάνταῥεῖ The poster seems to understand what undefined references are, and hasn't made any of the common simple mistakes as far as I can see. If some answer there explains this specific problem, which? Voting to reopen for now. – aschepler Sep 06 '18 at 23:28
  • @aschepler The answer is in the dupe. Order of the linked binaries matters. – πάντα ῥεῖ Sep 06 '18 at 23:30
  • @πάνταῥεῖ test.cpp appears before -lfc on the command line. Isn't that correct? – aschepler Sep 06 '18 at 23:31
  • It does look suspicious that nm reports the symbols as "t" and not "T", and readelf says "LOCAL". A lowercase nm code usually means internal linkage. (But I'm not sure how you would even end up with internal linkage for class member functions.) – aschepler Sep 06 '18 at 23:33
  • @aschepler You are right order is correct – πάντα ῥεῖ Sep 06 '18 at 23:34
  • So it could be helpful to see how libfc.so was built. (And by the way, on Unix/ELF systems, a lib*.a file is a "static library" and a lib*.so file is a "shared library".) – aschepler Sep 06 '18 at 23:44
  • @aschepler Updated with more information about how libfc.so was built. – user1429322 Sep 07 '18 at 00:00
  • 1
    https://stackoverflow.com/questions/22244428/hiding-symbol-names-in-library – Matthew Fisher Sep 07 '18 at 00:13
  • 1
    Possible duplicate of [What is an undefined reference/unresolved external symbol error and how do I fix it?](https://stackoverflow.com/questions/12573816/what-is-an-undefined-reference-unresolved-external-symbol-error-and-how-do-i-fix) – ead Sep 07 '18 at 06:26
  • 1
    https://stackoverflow.com/a/52216452/5769463 – ead Sep 07 '18 at 06:28

1 Answers1

0
libfc::InfoModel & model = libfc::InfoModel::instance();
                 ^
/tmp/ccFtLDxc.o: In function `main':
test.cpp:(.text+0x9): undefined reference to `libfc::InfoModel::instance()'
collect2: error: ld returned 1 exit status

Combined with -fvisibility=hidden (and friends):

$ nm -gCD ...

0000000000012980 t libfc::InfoModel::add(std::string const&)
0000000000010a60 t libfc::InfoModel::instance()
00000000000106f0 t libfc::InfoModel::initTypes()
...

I believe all this means is you have hidden your InfoModel class and it is no longer visible. I am guessing you manually added -fvisibility=hidden (and friends) but did not edit the source files and add DLL_PUBLIC (per the GCC Visibility wiki).

I think the easiest fix for you is to build the static archive without visibility. I.e., don't use -fvisibility=hidden (and friends). Then, when you build your shared object/plug-in that uses the static archive, use -fvisibility=hidden (and friends) and include -Wl,--exclude-libs,ALL linker flags. The extra linker flags will ensure you don't re-export the symbols from the static archives.

Your source files for the plugin would use DLL_PUBLIC (per the GCC Visibility wiki). The makefile recipe would use something like:

$(PLUGIN): $(PLUG_OBJS) $(FRAME_OBJS) $(OUTPUT)
   $(CXX) -shared -o $(OUTPUT) $(CXXFLAGS) $(PLUG_OBJS) $(FRAME_OBJS) $(BOOST_LIBS) $(LDFLAGS) -Wl,--exclude-libs,ALL

Then you can examine what is exported from your shared object/plug-in with something like:

nm -gCD libplugin.so | grep ' T '

Unfortunately there's no way to avoid the nm -gCD libplugin.so | grep ' T ' wart. I was just on the Binutils mailing list looking for a better way to display the exports.

A GCC issue report was recently opened against the docs for visibility at Issue 87190, Feedback on documentation for symbol visibility. Also see Linker exposing private symbols on the Binutils mailing list.


Some additional quick comments...

CPP = g++

CPP is the preprocessor. Use CXX.

FLAGS = ...

Use CXXFLAGS for C++ projects. Your C++ recipes might look like:

SRCS = $(sort $(wildcard *.cpp))
OBJS = $(SRCS:.cpp=.o)

%.o : %.cpp
    $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $<
jww
  • 97,681
  • 90
  • 411
  • 885