First of all, let me say that I have read quite a few questions and answers about this problem on Stackoverflow, most of them with the conclusion that it is a linking ordering problem. Nevertheless, I couldn't solve the issue so far.
My goal is to build a shared library (libdetector.so) that uses external libraries (OpenCV and others but for now let's assume it's just OpenCV) and I'd like to embed them into libdetector.so so that users just have to install libdetector.so and are good to go.
Let's say the source code for libdetector.so is detector.cc and looks like this (it doesn't do anything useful yet but it's good enough to illustrate the problem)
#include "detector.hh"
#include <string>
#include <vector>
#include "opencv2/opencv.hpp"
#include "opencv2/videoio.hpp"
namespace detector {
Detector::Detector(const std::string& filepath) : filepath(filepath) {}
std::vector<float> Detector::detect(float similarityThreshold) {
cv::Mat new_img = cv::Mat::zeros(1, 49, CV_64FC1);
std::vector<float> vec{1.0, 1.0, 1.0};
return vec;
}
} // namespace detector
detector.hh looks like this
#ifndef DETECTOR_H
#define DETECTOR_H
#include <string>
#include <vector>
#include "opencv2/opencv.hpp"
#include "opencv2/videoio.hpp"
namespace detector {
class Detector {
private:
std::string filepath;
public:
Detector(const std::string &filepath);
std::vector<float> detect(float similarityThreshold = 0.7);
};
} // namespace detector
#endif
I have compiled OpenCV with the cmake flag -DBUILD_SHARED_LIBS:BOOL=OFF and I got several OpenCV *.a libraries in the build/ directory. Afterwards I build libdetector.so like so:
g++ -Wall -fPIC -shared -o libdetector.so detector.cc opencv/build/lib/*.a
This doesn't return any errors and outputs libdetector.so - so far so good.
Next step is some sample code that should make use of libdetector.so, let's call it detector_use.cc:
#include <iostream>
#include <string>
#include <vector>
#include "detector.hh"
int main() {
detector::Detector d("test/path");
std::vector<float> vec = d.detect(0.1);
for (auto el : vec) {
std::cout << el << std::endl;
}
return 0;
}
My wish would be that users should be able to simply compile this with
g++ -o detector_use detector_use.cc ./libdetector.so
But this outputs
/tmp/ccseI2o0.o: In function `cv::String::~String()':
detector_use.cc:(.text._ZN2cv6StringD2Ev[_ZN2cv6StringD5Ev]+0x14): undefined reference to `cv::String::deallocate()'
/tmp/ccseI2o0.o: In function `cv::String::operator=(cv::String const&)':
detector_use.cc:(.text._ZN2cv6StringaSERKS0_[_ZN2cv6StringaSERKS0_]+0x28): undefined reference to `cv::String::deallocate()'
./libdetector.so: undefined reference to `ippicvsMaxEvery_32f'
./libdetector.so: undefined reference to `__itt_api_version_ptr__3_0'
./libdetector.so: undefined reference to `__itt_id_create_ptr__3_0'
./libdetector.so: undefined reference to `ippicviNormRel_L1_16u_C1R'
[...]
If I understand this correctly the linker complains that a reference in libdetector.so to ippicvsMaxEvery_32f among others can't be found. To dig into this deeper I ran
me@VI:~/C-Linux$ nm -gD libdetector.so | grep ippicvsMaxEvery_32f
U ippicvsMaxEvery_32f
Doesn't this prove that the symbol is in there?
If I simply link against the shared OpenCV libraries I have also installed on my machine like so
g++ -g detector_use.cc detector.cc -I. -lopencv_core -lopencv_videoio -lopencv_high
gui -o detector_use
everything works as expected. But why does it fail if I go the way over my libdetector.so library?