0

I am trying to build a shared object to later use a function DoSomethingUseful() from the shared object in other projects. It uses external libraries as well as a bunch of headers that I am using across multiple projects.

Using CMake, I created a project MySharedLib with a header file called library.h:

#ifndef MYSHAREDLIB_LIBRARY_H
#define MYSHAREDLIB_LIBRARY_H



#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <cstdio>

// own header files
#include <header1.h>
#include <header2.h>

#define PI 3.14159265

//tesseract
#include <tesseract/baseapi.h>
#include <leptonica/allheaders.h>


//openCV 
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>

//face detection
#include "opencv2/objdetect.hpp"
#include "opencv2/imgproc.hpp"

void DoSomethingUseul(int[] inparray);


#endif

With library.cpp as

#include "library.h"
void DoSomethingUseful(int[] inparray){...}

My CMake file is as such:

cmake_minimum_required(VERSION 3.10)
project(MYSHAREDLIB)

find_package( OpenCV REQUIRED )

set(CMAKE_CXX_STANDARD 11)

set(MY_INCLUDE_DIR ../source/)
set(MY_OPENCV_CASCADES /opencvpath/openCV34/opencv/sources/data/haarcascades/)
include_directories(${MY_INCLUDE_DIR} ${MY_OPENCV_CASCADES} /usr/include)

link_directories(${MY_INCLUDE_DIR})

add_library(MYSHAREDLIB SHARED library.cpp library.h
        ${MY_INCLUDE_DIR}header1.cpp
        ${MY_INCLUDE_DIR}header1.h
        ${MY_INCLUDE_DIR}header2.cpp
        ${MY_INCLUDE_DIR}header2.h
        )

set_target_properties(MYSHAREDLIB PROPERTIES VERSION 3.10)
set_target_properties(MYSHAREDLIB PROPERTIES SOVERSION 1)

target_link_libraries(MYSHAREDLIB lept tesseract ${OpenCV_LIBS})

The *.so file is created sucessfully, i. e. using Clion, no errors are thrown and the file libMySharedLib.so is there.

However, when I want to use the function DoSomethingUseful() in another file DoSomething.cpp:

#include <iostream>
#include "library.h"

using namespace std;

int main()
{

    int[2] myarray; myarray[0]=1; myarray[1] =2;

    DoSomethingUseful(myarray);

    return 0;
}

And

 g++ -g -Wall -o DoSomething DoSomething.cpp -I ../source/ -L. libMYSHAREDLIB.so 

When I execute

./DoSomething

I get:

./DoSomething: error while loading shared libraries: libMYSHAREDLIB.so: cannot open shared object file: No such file or directory

Before, I compiled without -I ../source/ yielding:

In file included from DoSomething.cpp:8:0:
library.h:19:10: fatal error: header1.h: No such file or directory
 #include <header1.h>

I find many threads dealing with this issue in general, and I gathered already a lot of knowledge about shared objects from those issues, also suceeding in getting examples from various tutorials running. However, I do not suceed with my own project.

This is just one of many questions, but I hope I can get help here and maybe also general hints. Thank you a lot for any help.

  • Add two more flags: `-Wl,-rpath -Wl,\`pwd\``. – Sam Varshavchik Oct 03 '18 at 10:53
  • Thank you for your comment. unfortunately, `g++ -g -Wall -Wl,-rpath -Wl,'pwd' -o DoSomethingExe DoSomethingUseful.cpp -I ../source/ -L. libFrontalViewService_test.so.3.10` did not work out. Did I miss something? – Sebastian-CV-ML Oct 03 '18 at 11:31
  • Oh, I just used ` rather thab '. It does the job now. What is the difference to adding the path of the *.so to the config, as mentioned below? – Sebastian-CV-ML Oct 03 '18 at 11:36
  • It serves two different purposes. -L sets the search path ***at link time***. -rpath encodes in the resulting executable the search path to find the library ***at runtime***. The config lets the runtime loader search the directory that's not encoded in the binary. – Sam Varshavchik Oct 03 '18 at 11:42
  • Ok: -L: search path for created library at link time. Furthermore: As I understand, using -rpath I encode the search path, i. e. here pwd, into the binary itself to find at runtime. Therefore, I do not need to write it into the config - its already in the binary. So its either way -rpath or config, correct? – Sebastian-CV-ML Oct 03 '18 at 13:17
  • Pretty much. One way or another, it's necessary to specify where to search for libraries at runtime. – Sam Varshavchik Oct 03 '18 at 16:05

1 Answers1

1

Assuming Linux (amend question if wrong). When running an executable, shared libraries are loaded from paths listed in /etc/ld.so.conf only. If you want to load from somewhere else (.) , you have to set the LD_LIBRARY_PATH environment variable, e.g. LD_LIBRARY_PATH=. ./DoSomething

  • Thank you for your reply! With your suggestion, I followed these steps from this thread [link](https://stackoverflow.com/questions/13428910/how-to-set-the-environmental-variable-ld-library-path-in-linux). creating additional config file `sudo nano /etc/ld.so.conf.d/randomLibs.conf`, adding the directory of the *.so and running `sudo ldconfig`. – Sebastian-CV-ML Oct 03 '18 at 11:27
  • What I still not get: I thought I would create a shared library to use by multiple projects so that I do not have the dependency on my `../source/` , i. e. all the header files anymore. However, I still have to add `-I ../source/` when I want to create an executable using this library. Is there a way around? Is my approach just not the best one? – Sebastian-CV-ML Oct 03 '18 at 11:33
  • If we use the standard printf as an example, you need both the header file (stdio.h) and the shared library (libc.so). The header file tells your code that there is a function with this name and its arguments, the shared library provides the implementation. –  Oct 03 '18 at 12:07
  • Ok, I think I understand. But if I e. g. use another library in a *.cpp file, I only have to load the headers of the library. But here, I also have to add all the source files during compilation by `-I`.Whats the point of the *.so here? They should be included in the *.so. So what would be the advantage here for a *.so, when I need everything in `../source/` anyway? The purpose of my approach is, to get rid of all the dependencies and just call a function `./DoSomething` by just adding only the header where `DoSomething` is defined. Is my intention clear? – Sebastian-CV-ML Oct 03 '18 at 12:36
  • -I is only used for resolving #include directives, you may have pointed it to a directory containing all kinds of files, but only headers will be used (unless somebody actually #includes a .cpp, eww) –  Oct 03 '18 at 12:57
  • I understand about pointing with `-I` to seek for headers and ignore other files, but is there not a way around without compiling with `-I`? I mean, of course, I could create a second library from the headers in `../source/`. But since all those header in `../source/` are already added to the `MySharedLib` (see `add_library` in CMake file above) - why do I have to handle them again? What am I missing? Thank you a lot in advance – Sebastian-CV-ML Oct 03 '18 at 13:22
  • Not sure what you are trying to achieve, maybe it would be worth making another question. Anyway, the preprocessor #includes are not an ideal match for C++, people are working on a less silly module system for C++20, see https://medium.com/@wrongway4you/brief-article-on-c-modules-f58287a6c64 –  Oct 03 '18 at 13:42
  • Ok, I will open a new thread, if this is not clear, but it will be the same question: Want I want: One *.so file, that I can locate anywhere and just based on that file, call functions from that file without any other dependencies but this *.so file. Right now, if I want to call a function from the library, I also have to tell where all the other headers are via -I, so theres more dependencies than just the *.so – Sebastian-CV-ML Oct 03 '18 at 14:04