2

I'm a first year computer science student following a course on (amongst others) Makefiles. For our first assignment, we had to create a shared library and link against it.

I have the following setup:

  • A folder hw1 containing the folders app and lib.
  • Inside lib is a file called libmine.so, the library I want to link against.
  • Inside app, there are two files: test.cpp and a Makefile. The former uses the libmine library.

The Makefile is as follows (in the file itself, indentation etc. is correct):

all: test

test: test.cpp
      g++ -Wall -o test -L../lib -I../lib/include test.cpp -lmine

However, when running test, I get the infamous `libmine.so: cannot open shared object file' error.

I believe this has something to do with exporting LD_LIBRARY_PATH. I have tried doing so (export LD_LIBRARY_PATH=$[very long relative path to the lib folder]), but I want to do this in my Makefile. Additionally, I don't want the path to be relative, as my teachter should be able to open the file when I send it to him (so I think it should be something like ../lib/libmine.so).

I looked at various StackOverflow posts, such as this one, but none seemed to answer this specific question (either it was a different setup or the solution simply didn't work). By the way: putting the line export LD_LIBRARY_PATH=../lib right under test: test.cpp and before the g++ command did not do anything.

Any help is much appreciated :)

  • Just to be clear, that is not the full error message, and the error message appears when you try to execute `test`, not when you execute Make and *build* `test`. Is that correct? And have you gotten `test` to run by doing things differently, e.g. by having `libmine.so` in your current directory? – Beta Feb 13 '16 at 04:32
  • Yes, that is correct. The problem is that the library cannot be found at *runtime*. – limitIntegral314 Feb 13 '16 at 14:05

1 Answers1

1

when running test, I get the infamous `libmine.so: cannot open shared object file' error.

This is happening because the -L../lib argument tells the static linker where to find the library, but it doesn't tell anything to the dynamic linker (aka loader), and the problem is that the latter can't find this library.

To solve this, you can use LD_LIBRARY_PATH, but this is usually ill-advised.

What you want is something called RPATH or RUNPATH (assuming you are on a Linux or similar system):

 g++ -Wall -o test -L../lib -I../lib/include test.cpp -Wl,-rpath=../lib -lmine

Additionally, I don't want the path to be relative, as my teachter should be able to open the file when I send it to him

Is your teacher going to run your binary on the same system, or on a different one? If the former, you could do this:

g++ -Wall -o test -L../lib -I../lib/include test.cpp -Wl,-rpath=/full/path/to/hw1/lib -lmine

If the latter, /full/path/to/hw1/lib may or may not be available on your teacher's machine, and you need to think about what exactly you are going to send to him.

The usual way to solve this is to package both the application and the library into a tar file:

tar cvf to-send.tar app/test lib/libmine.so

The teacher can then extract the parts of your tar file into arbitrary directory, and try to run it. To make this work, you need RPATH that is relative to the application, regardless of where the application ends up. To achieve that, you want:

g++ -Wall -o test -L../lib -I../lib/include test.cpp -Wl,-rpath='$ORIGIN/../lib' -lmine
Employed Russian
  • 199,314
  • 34
  • 295
  • 362
  • You, sir, are my hero. Everything works now. The only thing is that I wrote `-Wl,-rpath='../lib'`, so without `$ORIGIN` (since that didn't work). Thanks a lot. – limitIntegral314 Feb 14 '16 at 18:14