16

I am able to make a shared library without problems. I create libcbitcoin.so (without any errors) and attempt to link against it with an executable as well as OpenSSL libraries. I use this command:

gcc -L/media/sf_BitEagle_Projects/cbitcoin/build/bin -lcbitcoin \
-Wl-rpath,/media/sf_BitEagle_Projects/cbitcoin/build/bin -lssl -lcrypto \
-L/usr/local/ssl/lib/ -o /media/sf_BitEagle_Projects/cbitcoin/build/bin/testCBAddress \
/media/sf_BitEagle_Projects/cbitcoin/build/obj/testCBAddress.o \
/media/sf_BitEagle_Projects/cbitcoin/build/obj/CBOpenSSLCrypto.o

The bin directory is the location of the library. The obj directory has the object files I wish to link into an executable. In the command I use the -L, -l and -rpath* options which I thought was all that is needed for linking in Linux. It seems I am wrong since I get errors like:

/media/sf_BitEagle_Projects/cbitcoin/test/testCBAddress.c:40:
undefined reference to `CBNewByteArrayFromString'

CBNewByteArrayFromString is found in the library. For some reason it is not being linked. OpenSSL too:

/media/sf_BitEagle_Projects/cbitcoin/dependencies/crypto/CBOpenSSLCrypto.c:37:
undefined reference to `SHA1'

How do I get the linking to work?

GCC version: gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3

It is on Linux Mint 13 (Maya).

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Matthew Mitchell
  • 5,293
  • 14
  • 70
  • 122

2 Answers2

33

Put the libraries after the object files on the link command line:

gcc /media/sf_BitEagle_Projects/cbitcoin/build/obj/testCBAddress.o \
    /media/sf_BitEagle_Projects/cbitcoin/build/obj/CBOpenSSLCrypto.o \
    -L/media/sf_BitEagle_Projects/cbitcoin/build/bin \
    -lcbitcoin -Wl-rpath,/media/sf_BitEagle_Projects/cbitcoin/build/bin \
    -L/usr/local/ssl/lib/ -lssl -lcrypto \
    -o /media/sf_BitEagle_Projects/cbitcoin/build/bin/testCBAddress

If you don't do that, the linker may decide that it needs nothing from a particular library at the stage of the link where it scans the library, and then it won't rescan the library later after it finds some undefined symbols in the object files. If you put the object files first, you don't run into this problem.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • 4
    Fixed my problem too. What a terrible(counter-intuitive, unexpected) bug/design-decision that is (to make the order of the options relative to the positional parameters significant) Conventionally options come first and other parameters follow. – Ribo Nov 24 '13 at 22:11
  • 1
    The `-L` options can go more or less anywhere on the command line, but you need to think of the `-l name` options as specifying a file that is processed at that point in the command line (so any relevant `-L` flag should preceed it). It has always been thus, since the beginning of (Unix) time — some time in the 1970s, anyway. – Jonathan Leffler Nov 25 '13 at 01:42
  • 2
    It seems that the order of the `-l` options relative to each other matters as well, and the more general / lower level dependencies should come *last*, not *first*. I was getting `undefined reference to 'pow'` until I moved `-lm` to the very *end* of my option string. – IMSoP Nov 19 '14 at 16:41
1

I think it is caused by can not find symbol. GCC will first go through from the left and will try to put the library file at the end.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
How Chen
  • 1,340
  • 2
  • 17
  • 37