Possible cause for "Can't resolve symbol"? - linux

The cross-compiling of Lua, a test module, and a real-life module went OK, but when I load the real-life module on an appliance running uClinux, I get this error:
appliance::/var/tmp> ./lua -l dummy
Hello from dummy
Bye from dummy
Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio
appliance::/var/tmp> ./lua -l luasql.sqlite3
./lua: can't resolve symbol '_luaL_ref'
I don't have enough experience to know what the cause is, although Google seems to point to issues with shared libraries. Maybe the module expects some library, or some specific version of a library and it's not there?
Has someone seen this type of error before? How could I investigate?
Thank you.
Edit: Here are the config/Makefiles that I used to build Lua, SQLite3, and LuaSQL for SQLite3:
# cat /var/tmp/lua-5.1.4/src/Makefile
MYCFLAGS=
MYLDFLAGS=
MYLIBS=
export PATH:=$(PATH):/usr/src/baps/opt/uClinux/bfin-linux-uclibc/bin
TARGET_CROSS=bfin-linux-uclibc-
export CC=$(TARGET_CROSS)gcc
export STRIP=$(TARGET_CROSS)strip
export AR=$(TARGET_CROSS)ar rcu
export RANLIB=$(TARGET_CROSS)ranlib
export STAGING_DIR=/usr/src/baps/uClinux-dist/staging
export UCLINUX_LIB=/usr/src/baps/uClinux-dist/lib
export UCLINUX_ROOT_LIB=/usr/src/baps/uClinux-dist/root/lib
export CFLAGS=-O2 -Wall -Wmissing-prototypes -Wmissing-declarations -I$(STAGING_DIR)/usr/include -DLUA_USE_POSIX -DLUA_USE_DLOPEN
export LDFLAGS= -L$(STAGING_DIR)/usr/lib -L$(UCLINUX_LIB) -L$(UCLINUX_ROOT_LIB) -ldl -lm
...
$(LUA_T): $(LUA_O) $(LUA_A)
$(CC) -o $# $(CFLAGS) $(LDFLAGS) $(LUA_O) $(LUA_A)
$(LUAC_T): $(LUAC_O) $(LUA_A)
$(CC) -o $# $(CFLAGS) $(LDFLAGS) $(LUAC_O) $(LUA_A)
...
generic:
$(MAKE) all
# cat /var/tmp/sqlite-amalgamation-3070400/Makefile
export PATH:=$(PATH):/usr/src/baps/opt/uClinux/bfin-linux-uclibc/bin
TARGET_CROSS=bfin-linux-uclibc-
export CC=$(TARGET_CROSS)gcc
export STRIP=$(TARGET_CROSS)strip
export AR=$(TARGET_CROSS)ar rcu
export RANLIB=$(TARGET_CROSS)ranlib
export CFLAGS=-O2 -Wall
libsqlite3.o:
$(CC) $(CFLAGS) -DSQLITE_THREADSAFE=0 -o $# -c sqlite3.c
# cat /var/tmp/luasql-2.1.1/config
...
LUA_INC= /var/tmp/lua-5.1.4/src
LIB_OPTION= -shared #for Linux
...
DRIVER_LIBS= /var/tmp/sqlite-amalgamation-3070400/libsqlite3.o
DRIVER_INCS= -I/var/tmp/sqlite-amalgamation-3070400
WARN= -Wall
INCS= -I$(LUA_INC)
CFLAGS= -O2 $(WARN) -I$(COMPAT_DIR) $(DRIVER_INCS) $(INCS) $(DEFS)
CC=/usr/src/baps/opt/uClinux/bfin-linux-uclibc/bin/bfin-linux-uclibc-gcc
LDFLAGS = -Wl,--trace,--print-map,--cref
# cat /var/tmp/luasql-2.1.1/Makefile
...
src/$(LIBNAME): $(OBJS)
$(CC) $(CFLAGS) $(LDFLAGS) -o $# $(OBJS) $(DRIVER_LIBS) $(LIB_OPTION)
Edit: After being told that it was most likely a linking issue, and after more reading and trial/error, I finally found what it was: When building Lua, the following options are required: "-Wl,-E"

I don't have any experience with lua, but in general I can say that when a symbol is "unresolved", this is an indication that the linker cannot find the symbol in any of the archive files or libraries it is told to link together. You will need to identify what library defines the symbol and include it in the link command, usually with a -l flag. You may also need to provide a -L flag giving the directory that includes this library. In your Makefile, you could add these flags to the LDFLAGS variable.

In addition to the above answer, if you are running on an appliance, you have to make sure that you are not linking against the includes or libs on your build system. Your development system $PATH variable may be pointing to local include files and libs. In addition, you need to make sure that the libs are in a usable location in the appliance, usually in /bin or /lib.

Here is one other reason, when you get errors like can't resolve symbol 'open64' or can't resolve symbol 'setrlimit64' - you might be using an app with the large file support on an environment that doesn't support it. Watch out for the __USE_FILE_OFFSET64 macro.

Try deleting this line:
export STRIP=$(TARGET_CROSS)strip

Related

How do I correctly link a shared object (.so file) in a makefile when cross-compiling?

I have some C++ code on an openSuse platform that I need to compile to be executed on a different linux-based target. Part of the code is a dynamic library libfoo.so. I compile everything with make and then copy the compiled executable prog together with the libfoo.so to the target. When I then run the executable, I get some errors indicating the libfoo could not be initialized. I've tried everything I could find to tell the executable where it can find the libfoo.so but I still get the error.
Could anybody tell me what I am doing wrong here? I feel like it could be an error in the Makefile.
I am very new to C++ and using Makefiles in general, and on top of it all, the target runs kind of a proprietary linux version, so I cannot provide much information about it. I do have the appropriate compiler for it though.
My directory structure on the openSuse platform:
|src
|--Foolib
|----foolib.h
|----libfoo.so
|--Otherlib
|----otherlib.h
|----otherlib.hpp
|---+OtherlibSrcDirectory
|--bar.cpp
|--bar.h
|--Makefile
Directory structure on the target:
|program
|--libfoo.so
|--prog
My Makefile:
LIBS = -LFoolib -lfoo
INC = -I OtherLib -I Foolib
CXXFLAGS += -lpthread -std=c++11 -D_GLIBCXX_USE_NANOSLEEP $(INC)
LDFLAGS = '-Wl,-rpath,$$ORIGIN'
SRC_FILES = bar.cpp
OBJ = $(SRC_FILES:%.cpp=%.o)
prog: $(OBJ)
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(LIBS) -o $# $^
%.o: %.cpp
$(CXX) $(CXXFLAGS) $(LIBS) -c $<
Basically, bar.h includes Foolib/foolib.h as well as Otherlib/OtherlibSrcDirectory and bar.cpp includes bar.h. Then some functions from foolib.h are called in bar.cpp and they return error values. If necessary I can provide some more insights into the code but I'll leave it out for now to keep it a bit shorter.
Any help would be highly appreciated!
Found my mistake.
libfoo.so was already on the target machine and it was located in the correct folder (/lib). My program had been able to find it without problems.
My mistake: I executed my program on the target machine without root permissions.
Without root permissions, I am not allowed to initialize Foolib.
sudo ./prog fixed everything.

Linker cannot find library file with explicit path

In my makefile, I have specified a library dependency as follows:
LDFLAGS := -l/home/karnivaurus/OpenCV-3.0.0/build/lib/libopencv_core.so
all: $(DYNAMIC_NAME)
$(DYNAMIC_NAME): $(OBJS) | $(LIB_BUILD_DIR)
# echo LD -o $#
$(Q)$(CXX) -shared -o $# $(OBJS) $(LINKFLAGS) $(LDFLAGS) $(DYNAMIC_FLAGS)
Now, if I run make all, I get the following error:
/usr/bin/ld: cannot find -l/home/karnivaurus/Libraries/OpenCV-3.0.0-RC1/build/lib/libopencv_core.so
However, in the directory /home/karnivaurus/Libraries/OpenCV-3.0.0-RC1/build/lib, there is definitely a file called libopencv_core.so. I have checked the spelling many times!
Are there any reasons why the linker cannot find this file, even though I have explicitly specified its exact location and passed that to the linker?
Thanks!
Either use -L for the library path and -lopencv_core:
LDFLAGS := -L /home/karnivaurus/OpenCV-3.0.0/build/lib/ -lopencv_core
or just include the full path to the .so file without -l.
LDFLAGS := /home/karnivaurus/OpenCV-3.0.0/build/lib/libopencv_core.so

How to ouput the static library into other directory than current?

Following is my directory structure
calculator
|
|---src
(multiply.cpp sum.cpp)
|---lib
I am building a static library calc.a using following
ar -rcs calc.a multiply.o sum.o
calc.a is builded in current directory.
I trying calc.a to be put into lib folder not in current directory (i.e. src)
I searched in internet and man page but couldn't find anything.
Any idea?
Since you are using the command line, the easiest way to write the library into the lib directory is to do it explicitly:
ar -rcs lib/libcalc.a multiply.o sum.o
Using a Makefile you can do more sophisticated things, but even then, it boils down to the same thing, e.g. adding the path to the front of the library name.
Since you asked for additional info on your comment, I add here a simple Makefile, which may be helpful to get you started:
CC=g++
CFLAGS=-c -Wall
LDFLAGS=
SOURCES=src/main.cpp src/sum.cpp src/multiply.cpp
OBJECTS=$(SOURCES:.cpp=.o)
LIBRARY=lib/libcalc.a
EXECUTABLE=main
all: $(SOURCES) $(LIBRARY) $(EXECUTABLE)
$(LIBRARY): $(OBJECTS)
<tab>mkdir -p lib
<tab>ar -rcs $# $<
$(EXECUTABLE): $(OBJECTS)
<tab>$(CC) $(LDFLAGS) $(OBJECTS) -o $#
.cpp.o:
<tab>$(CC) $(CFLAGS) $< -o $#
clean:
<tab>rm -rf main lib/ src/*.o
Important: All <tab>s must be replaced with real tabs, as required by the Makefile syntax!
Makefiles are very very flexible, so they can be very simple and specific to your problem, or as general and/or complex to build many libraries and binaries, based on millions and millions of source code. I suggest you to search for Makefile documentation for more information.
As a final note, I also suggest you to rename your library as 'libcalc.a', since the 'lib' prefix is standard in Unix. Other similar standards apply for other environments.

Cannot compile with makefile - undefined reference to `boost::re_detail

I got an assignment to improve running time of some code. The only problem is, I can't even compile it to run it on my machine in the first place. Every time I try, it stops somewhere in the midst of compiling saying this:
"undefined reference to `boost::re_detail::put_mem_block(void*)'
collect2: ld returned 1 exit status make: * [cpu] Error 1"
This is how makefile looks:
SHELL = /bin/bash
OBJECTS = main.o atom.o molecule.o charges.o pdb.o asa.o amino.o chain.o addition.o string_operation.o pdb_peptide.o protein_chain.o residue_atom.o chain_residue.o residue_contact.o atom_grid.o circles.o atom_space_calculations.o
OBJDIR = obj
VPATH = src:src/ext:$(OBJDIR)
CFLAGS = -O3 -Wall -lm -lboost_regex -L/usr/local/boost/lib
HDIRS = src,src/ext,src/qt_redistributable, usr/lib, usr/local/lib, usr/local/lib/include/boost, /usr/local/lib/lib/
IOPTS = $(addprefix -I, $(HDIRS))
cpu : $(addprefix $(OBJDIR)/, $(OBJECTS) $(CPUOBJS))
g++ $(CFLAGS) -o mcpu $^
$(OBJDIR)/%.o : %.cpp
g++ $(CFLAGS) $(IOPTS) -c $< -o $#
clean :
rm obj/*.o $(PROG)
I'm using Linux Mint x64 and I have tried everything I googled out. Installed the whole boost library in usr/local/lib (for no obvious reason because it didn't help), tried to edit LD PATH (I'm very new to Linux and I have no idea if that went right) and lots of stuff, but this thing doesn't seem to go through. Any help appreciated.
One problem with your makefile happens when you link your program. As you can see in these questions with g++ the order of your arguments at link time is really important. You need to put your libraries after your object files. One easy way to solve would be separating your linker flags (LDFLAGS) from the compiler flags (CFLAGS), and then putting LDFLAGS after $^ (your object files) in the link command.
CFLAGS = -O3 -Wall
LDFLAGS = -L/usr/local/boost/lib -lm -lboost_regex
cpu : $(addprefix $(OBJDIR)/, $(OBJECTS) $(CPUOBJS))
g++ $(CFLAGS) -o mcpu $^ $(LDFLAGS)
$(OBJDIR)/%.o : %.cpp
g++ $(CFLAGS) $(IOPTS) -c $< -o $#
As can be seen in the Catalogue of Built-In Rules:
Linking a single object file
n is made automatically from n.o by running the linker (usually called
ld) via the C compiler. The precise recipe used is:
$(CC) $(LDFLAGS) n.o $(LOADLIBES) $(LDLIBS)
and Variables Used by Implicit Rules:
LDFLAGS
Extra flags to give to compilers when they are supposed to invoke the linker,
ld, such as -L. Libraries (-lfoo) should be added to the LDLIBS variable
instead.
So in this case -lboost_regex should be set or added to LDLIBS, not LDFLAGS.

Makefile for Shared Libraries?

I've just written a Makefile to build a shared library, similar to the following:
libmystuff.so: CFLAGS+=-fPIC -shared
libmystuff.so: libmystuff.o otherstuff.o
$(CC) $(CFLAGS) -o $# $^
I like to avoid doing explicit actions when this seems like a common operation, but it seems there's no implicit rule or other built-ins to standardize this. I'm using GNU Make on Linux at the moment, but will need this to work on OS X as well.
EDIT: I'm asking about make rules rather than compiler/linker flags.
Can you recommend clean, reusable Makefile rules to build shared libs? Perhaps a %.so: or .c.so: type rule?
For portability, I'd look into integrating libtool.
define compile_rule
libtool --mode=compile \
$(CC) $(CFLAGS) $(CPPFLAGS) -c $<
endef
define link_rule
libtool --mode=link \
$(CC) $(LDFLAGS) -o $# $^ $(LDLIBS)
endef
LIBS = libmystuff.la
libmystuff_OBJS = libmystuff.lo otherstuff.lo
%.lo: %.c
$(call compile_rule)
libmystuff.la: $(libmystuff_OBJS)
$(call link_rule)
install/%.la: %.la
libtool --mode=install \
install -c $(notdir $#) $(libdir)/$(notdir $#)
install: $(addprefix install/,$(LIBS))
libtool --mode=finish $(libdir)
libtool will automatically add -fPIC/-DPIC/-shared flags as appropriate, and generate whatever .o/.a/.so files would be used on the current platform.
Or you could use Automake's libtool integration.
Building shared libraries is platform dependent. For example, the flags you are using are
ok for GCC for ELF platforms, for cygwin, for example, you do not add -fPIC for some other platforms and compilers you need other flags.
You need one of:
Provide an option to set flags for user platform.
Use standard build system like Autotools

Resources