0

I am currently developing a C library for a client and to do so I needed to use other libraries like: glib2.0, libxml2, lib, openssl and gmp. After I finished my development and created the .so I tried to compile a test program with it and found out that my library was not self-contained and that I needed to link the program with all those other libraries I mentioned above.

The client insist that he wants either a dll or a .so product and that it should be self contained, just one file so his application can consume it, the same way that he does with other libraries.

I am not sure what to do, it there a way to produced this self contained .so? If not possible what other options do I have? I am developing in solaris 11 and the target system is a Solaris server.

Thank you very much.

Makefile code:

# 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

Example output of test code compilation

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

If I link it with the other libraries doing:

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`

And then add the path using:

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

the test code works fine.

Caponte
  • 401
  • 1
  • 11
  • 20
  • It might be a good idea to edit your question and specify explicitly that you're building a plugin for Java, and what Java runtime is used, and (if you know), how the plugin is loaded in the Java code. – Greg A. Woods May 15 '15 at 20:33
  • I will find out all these things and modify the question. I think that the client and I are not on the same page. Thanks – Caponte May 15 '15 at 20:49

2 Answers2

0

I think you are more or less done.

The whole point of shared libraries is to not include anything from any other library dependencies. That's the job of the runtime linker, not the compile-time linker.

Since the application apparently depends on other libraries already, your library, and any additional libraries your library depends on but which the application does not already depend on, are just more libraries to add to the list.

Greg A. Woods
  • 2,663
  • 29
  • 26
  • First thing thank you for you answer. Now, according to what you said I did what would be expected when I was told to produce a .so, but the clients insist that it must be self-contained, that just by linking its app to it it should work without needing other dependencias, so what should I do? – The client code that would use the library is a java application contained by web sphere. They have used this strategy before but mostly using dll that someone else send to them. I am not sure if I am missing something here but according to them it has worked with .so too. – Caponte May 15 '15 at 19:57
  • Well, if by "self-contained" they mean it has no indirect dependencies on other shared objects, well that would be foolish, especially on recent Solaris systems. I think I fully understand their desire for self-contained binary executables, but they lost that goal when they chose Solaris, and even more so if what you are building is a shared object that is loaded by the application after it has started -- i.e. a plugin. – Greg A. Woods May 15 '15 at 20:20
  • Hmm... a plugin for JNI by any chance? – Greg A. Woods May 15 '15 at 20:22
0

In theory it is possible but I can't think of a reasonable reason to go on that path. Also it would be quite hard to do it. In terms of code here's what you should do:

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

By adding -Bstatic, you instruct the linker to use the static versions of the libraries that follow. But there's a catch: the static version of the libraries must exist on the system that you compile your .so on. Some of them might exist by default, but you'll have to do extra work:

  • libm, libgmp, libz - most likely there are packages in the os that have the static version of those, you have to install them (usually the package names are lib${LIBNAME}-static or lib${LIBNAME}-devel)
  • for libcrypto and libssl, you'll have to recompile OpenSSL as static libraries.
CristiFati
  • 38,250
  • 9
  • 50
  • 87
  • Thank for your answer. I am not sure what to do here because I kind of get the point of the client, but at the same time is not exactly how you would expect a share library to be used. also as I said in another comment the client code that would use the library is a java application contained by web sphere. They have used this strategy before but mostly using dll that someone else send to them. I am not sure if I am missing something here but according to them it has worked with .so too. – Caponte May 15 '15 at 19:59
  • BWT, in case the `-Bstatic` is confusing or causes problems because it ends up in the wrong place on the command line, I'm pretty sure (but have no current access to a modern Solaris to test) that the Solaris linker will still treat `lib*.a` files on the command line properly by loading any necessary objects from them, and that `-Bstatic` is only needed if the libraries are specified by `-lname`. – Greg A. Woods May 15 '15 at 20:26
  • Yes, i noticed that the `LDLIBS` macro is complicated (it should contain simple flags linker flags). *-Bstatic* won't work on a regular SunOS, since the static libs are not there by default. Dynamic ones are, and if you install the static you'll have both. By default, modern OSes prefer the dynamic version over the static one, that's why it is required. But anyway, i don't like this approach, they should install on the production server the required libraries (most are by default). Also I'm not sure if previous dlls were self contained or their dependencies simply happened to be present. – CristiFati May 15 '15 at 20:57