自包含的C共享库

时间:2015-05-15 18:36:38

标签: c gcc compilation shared-libraries self-contained

我目前正在为客户端开发一个C库,为此我需要使用其他库,如:glib2.0,libxml2,lib,openssl和gmp。在我完成开发并创建.so后,我尝试用它编译测试程序,发现我的库不是自包含的,我需要将程序与我上面提到的所有其他库链接。

客户端坚持要求dll或.so产品,并且它应该是自包含的,只有一个文件,因此他的应用程序可以使用它,就像他对其他库一样。

我不知道该怎么做,有没有办法产生这种自包含。所以?如果不可能,我还有其他选择吗?我在solaris 11中开发,目标系统是Solaris服务器。

非常感谢。

Makefile代码:

# C compiler 
CC = gcc 

# C flags
CFLAGS = -fPIC -O3 -g 

# linking flags
LDFLAGS = -shared 
LDLIBS = $(shell xml2-config --cflags --libs) $(shell pkg-config --cflags --libs glib-2.0) -lssl -lcrypto -lm -lgmp -lz 

# target lib
TARGET_LIB = libservices.so
SRCS = lib1.c lib2.c lib3.c lib4.c # source files

OBJS = $(SRCS:.c=.o)
# Compilation 
.PHONY: all
all: ${TARGET_LIB}

$(TARGET_LIB): $(OBJS) 
    ${CC} ${LDFLAGS} $(OBJS) -o ${TARGET_LIB}

# pull in dependency info for *existing* .o files
-include $(OBJS:.o=.d)

# Compiles and Generates Dependency Info
%.o: %.c
    gcc $(CFLAGS) -c $*.c -o $*.o ${LDLIBS}
    gcc -MM $(CFLAGS) $*.c > $*.d

测试代码编译的示例输出

gcc -I/path/to/libservices -L/path/to/libservices services_test.c -o test -lservices

libservices.so: undefined reference to `EVP_CipherInit'
libservices.so: undefined reference to `g_free'
libservices.so: undefined reference to `xmlFreeDoc'
libservices.so: undefined reference to `g_str_equal'
libservices.so: undefined reference to `g_hash_table_lookup'
libservices.so: undefined reference to `__gmpz_get_str'
libservices.so: undefined reference to `EVP_CIPHER_CTX_block_size'
libservices.so: undefined reference to `xmlCheckVersion'
libservices.so: undefined reference to `EVP_EncryptFinal'
libservices.so: undefined reference to `g_hash_table_new'
libservices.so: undefined reference to `EVP_CIPHER_CTX_init'
libservices.so: undefined reference to `xmlNodeGetContent'
libservices.so: undefined reference to `xmlCleanupParser'
libservices.so: undefined reference to `__gmpz_pow_ui'
libservices.so: undefined reference to `EVP_EncryptUpdate'
libservices.so: undefined reference to `__gmpz_clear'
libservices.so: undefined reference to `xmlParseDoc'
libservices.so: undefined reference to `g_hash_table_insert'
libservices.so: undefined reference to `EVP_DecryptInit_ex'
libservices.so: undefined reference to `EVP_EncryptInit_ex'
libservices.so: undefined reference to `g_hash_table_destroy'
libservices.so: undefined reference to `g_list_free'
libservices.so: undefined reference to `EVP_DecryptFinal'
libservices.so: undefined reference to `g_str_hash'
libservices.so: undefined reference to `__gmpz_init_set_str'
libservices.so: undefined reference to `EVP_DecryptUpdate'
libservices.so: undefined reference to `EVP_CipherFinal'
libservices.so: undefined reference to `__gmpz_sizeinbase'
libservices.so: undefined reference to `xmlDocGetRootElement'
libservices.so: undefined reference to `g_hash_table_foreach'
libservices.so: undefined reference to `EVP_CIPHER_CTX_cleanup'
libservices.so: undefined reference to `EVP_CipherUpdate'
collect2: error: ld returned 1 exit status

如果我将其与其他库链接:

gcc -I/path/to/libservices -L/path/to/libservices servicios_test.c -o test -lservices -lssl -lcrypto -lm -lgmp -lz `pkg-config --cflags --libs glib-2.0` `xml2-config --cflags --libs`

然后使用以下方法添加路径:

export LD_LIBRARY_PATH=/path/to/libservices:$LD_LIBRARY_PATH

测试代码工作正常。

2 个答案:

答案 0 :(得分:0)

我认为你或多或少已经完成了。

共享库的重点是包含任何其他库依赖项中的任何内容。这是运行时链接程序的工作,而不是编译时链接程序。

由于应用程序显然依赖于其他库,您的库以及您的库所依赖的任何其他库,但应用程序尚未依赖它们,只需要添加到列表中的库。

答案 1 :(得分:0)

从理论上讲,这是有可能的,但我想不出合理的理由走这条路。这也很难做到。在代码方面,这是你应该做的:

LDLIBS = $(shell xml2-config --cflags --libs) $(shell pkg-config --cflags --libs glib-2.0) -Bstatic -lssl -lcrypto -lm -lgmp -lz

通过添加 -Bstatic ,您可以指示链接器使用后续库的 static 版本。但是有一个问题:库的静态版本必须存在于您编译 .so 的系统上。其中一些可能默认存在,但你必须做额外的工作:

  • libm libgmp libz - 很可能在操作系统中有包含静态版本的软件包,你必须安装它们(通常包名是 lib $ {LIBNAME} -static lib $ {LIBNAME} -devel
  • 对于 libcrypto libssl ,您必须将OpenSSL重新编译为静态库。