malajedala
malajedala

Reputation: 907

Linking c++ dynamic library keeps failing

I know there have been a lot of posts about it, however I have tried and I am still getting an error for linking my library.

In my current directory, I have created a dynamic library at

/bin/library_test.so

The source code and include files are as usual in

./lib/ and ./src/

Then I am trying to compile a simple main.cpp and link the library by doing

 g++ main.cpp -I/lib/ -L/bin/ -llibrary_test

But I keep getting errors like "ExampleClass" was not declared in this scope, meaning I have not linked the library, right? As this class is contained in my library cpp/header files.

Am I missing something in the linking, or should I add some include command in my main.cpp file??

Upvotes: 1

Views: 1517

Answers (1)

Matteo Ragni
Matteo Ragni

Reputation: 2956

There are several stuff to check in your command and setup. Also please check out the C++ compilation phases. You need to understand that to fully understand your issues.

Looking at the comment you made you had 3 main problem in:

  1. Compilation (after preprocessing and before assembling and linking)
  2. Linking (still while compiler is running)
  3. Runtime linking (during execution of the compiled binary)

Compilation

The error you are receiving is in compilation phase, before linking the binary. This error can be generated either because:

  • you forgot the #include for the header that defines ExampleClass

  • you are not telling the compiler the correct path for searching for headers. In your command you are telling the compiler to search the headers in /lib (a directory that start from the root of the filesystem) while I'm quite sure you want to search for them in a directory relative to your current working directory, meaning -Ilib -Isrc.

    By the way, I strongly suggest you to put all your source file in a src directory and all the headers in an include directory, that this what is usually done in complex C/C++ projects.

Linking

Once you correct the compilation phase, you will probably get a linking issue, because your library is not following the naming convention used in linux for shared objects. The filename for the library LIBRARYNAME should be libLIBRARYNAME.so.

In some cases you may have more than one version of a library, thus it is possible to add the version with a semantic versioning convention after the so extension (for example libLIBRARYVERSION.so.2.1 for the version 2.1 of your library).

To link the aforementioned library you must use the -lLIBRARYNAME option.

In order to inform your compiler where to find the library at linking time, you should provide the path with the -L, but this option informs only the compiler and does not save the position of such library in the executable.

Runtime Linking

In this case there are two main scenarios (I will be a little sloppy, but just to point you in the right direction. A complete explanation may require a lot more space... and time):

  • You can hardcode the position of the shared library in your binary by using the rpath, but if you distribute your application the end user must have the lib in the same path you specified via rpath, and this is why I tend to avoid this solution.
  • Modern linux system are capable of search for the a required shared object (this is the reason why there is a naming convention). The search is performed in trusted directories, and the searching path are configured via ldconfig configuration file (or the $LD_LIBRARY_PATH env variable). When a new library is installed in a searching path, the cache of the runtime linker should be refreshed (again, this is done via ldconfig or via reboot). I strongly suggest you to read the link about ldconfig since it explains you how to configure a new searching path (like /usr/local/lib in your case).

You can check if a binary is able to find all the required shared object through the command ldd BINARY_NAME (in your case ldd a.out).

Upvotes: 1

Related Questions