kgui
kgui

Reputation: 4165

Function Defined in Static Library is not being found

I am having a problem finding a function called get_offsets() defined in bam_sqlite.c.

I create a static library with the following Makefile:

CC    = gcc
CFLAGS = -Wall -g -std=c99 -fPIC
INC := -Iinclude -I./ -I/gpfs/commons/home/knagdimov/temp/git/Rbamdb/htslib/ -I/gpfs/commons/home/knagdimov/temp/git/Rbamdb/lmdb/libraries/liblmdb/ -I/gpfs/commons/home/knagdimov/temp/git/Rbamdb/sqlite3/

all:

    @mkdir -p bin 
    $(CC) $(CFLAGS) $(INC) -c bamdb.c -o bin/bamdb.o
    $(CC) $(CFLAGS) $(INC) -c src/bam_api.c -o bin/bam_api.o
    $(CC) $(CFLAGS) $(INC) -c src/bam_lmdb.c -o bin/bam_lmdb.o
    $(CC) $(CFLAGS) $(INC) -c src/bam_sqlite.c -o bin/bam_sqlite.o
    ar -rcs bin/libbamdb.a bin/bamdb.o bin/bam_api.o bin/bam_lmdb.o bin/bam_sqlite.o

Then, I run nm libbamdb.a and get the following output:

bam_sqlite.o 
000000000000067b T get_offsets

Thus, the function is defined in the static library. Finally, I run another Makefile (in a higher directory) which contains the following:

PKG_BASE = $(shell pwd)/../
LIB_BASE = -Wl,-rpath,$(PKG_BASE)
PKG_CPPFLAGS = -I$(PKG_BASE)bamdb -I$(PKG_BASE)Rbamdb -I$(PKG_BASE)bamdb/include/ -I$(PKG_BASE)htslib/ -I$(PKG_BASE)lmdb/libraries/liblmdb/ -I$(PKG_BASE)sqlite3/
PKG_CXXFLAGS = -I$(PKG_BASE)badb -I$(PKG_BASE)Rbamdb -I$(PKG_BASE)bamdb/include/ -I$(PKG_BASE)htslib/ -I$(PKG_BASE)lmdb/libraries/liblmdb/ -I$(PKG_BASE)sqlite3/
PKG_LIBS = -L$(PKG_BASE)/ -L$(PKG_BASE)/bamdb/bin/ -L$(PKG_BASE)htslib/ -L$(PKG_BASE)lmdb/libraries/liblmdb/ -L$(PKG_BASE)sqlite3/ -lbamdb -lhts -llmdb -lsqlite3

The other libraries are libsqlite3.so, libhts.a, liblmdb.a, and they seem to all be found. The only one not being found is libbamdb.a which makes me believe I am defining the static library in a wrong way.

Please note that bamdb source code (bam_api.c, bam_lmdb.c, bam_sqlite.c, bam_sqlite.c) depend on functions defined in other static libraries. Should I include them them I'm compiling these source codes into object files?

Ultimately the following solved the problem: the Makevars file is creating a .so file using the g++ compiler. The previous libraries were C libraries compiled using gcc. The header files of the C source code didn't include the following:

#ifdef __cplusplus 
 extern "C" { 
 #endif 
 #ifdef __cplusplus
}

Including that solved the problem.

Upvotes: 2

Views: 1473

Answers (1)

brian beuning
brian beuning

Reputation: 2862

If you are using gcc and the gnu linker, then this description of the -l command line argument may help

The linker will search an archive only once, at the location where it is specified on the command line. If the archive defines a symbol which was undefined in some object which appeared before the archive on the command line, the linker will include the appropriate file(s) from the archive. However, an undefined symbol in an object appearing later on the command line will not cause the linker to search the archive again.

See the -( option for a way to force the linker to search archives multiple times.

So if the reference to get_offsets() is coming from one of the -l library after -lbamdb then you need to rearrange the -l or use -( -) .

Upvotes: 2

Related Questions