Build Application with Static Libraries
Hi all,
I'm trying to statically link my C++ (CMake) application to run on another computer which does not have OpenCV installed.
So far,
I built OpenCV from source by setting BUILD_SHARED_LIBS to OFF, so I can see library files under lib directory. (with .a extension)
I edited the environment variable for the new build of OpenCV, my IDE does see include directories and files, so this step also seems ok.
Added "-static" parameter to target_link_libraries command in CMake:
target_link_libraries(HoGPeopleDetector ${OpenCV_LIBS} "-static")
Then rebuilt the application, EXE size increased to 1.6 MB from 200 KB. So I guess linking process was successful.
The application works well when I run it within my IDE. However, when I try to run it from the EXE file, it still expects DLL files. (libopencv_core310.dll and maybe more)
IDE: CLion 2017.1.2 OpenCV: 3.1
Program Code:
#include <iostream>
#include <opencv2/objdetect.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/video.hpp>
using namespace cv;
using namespace std;
static void detectAndDraw(const HOGDescriptor &hog, Mat &img)
{
vector<Rect> found, found_filtered;
hog.detectMultiScale(img, found, 0, Size(8,8), Size(32,32), 1.05, 2);
for(size_t i = 0; i < found.size(); i++ )
{
Rect r = found[i];
size_t j;
for ( j = 0; j < found.size(); j++ )
if ( j != i && (r & found[j]) == r )
break;
if ( j == found.size() )
found_filtered.push_back(r);
}
for (size_t i = 0; i < found_filtered.size(); i++)
{
Rect r = found_filtered[i];
r.x += cvRound(r.width*0.1);
r.width = cvRound(r.width*0.8);
r.y += cvRound(r.height*0.07);
r.height = cvRound(r.height*0.8);
rectangle(img, r.tl(), r.br(), cv::Scalar(0,255,0), 3);
}
}
int main(int argc, char** argv)
{
cout << "Cikis icin Q ya da ESC ye basin\n";
HOGDescriptor hog;
hog.setSVMDetector(HOGDescriptor::getDefaultPeopleDetector());
namedWindow("people detector", 1);
string pattern_glob = "";
string video_filename = "C:\\OpenCV\\video.mp4";
VideoCapture vc;
Mat frame;
vc.open(video_filename.c_str());
if (!vc.isOpened())
throw runtime_error(string("Dosya acilamadi: " + video_filename));
for (;;)
{
vc >> frame;
if (frame.empty())
break;
detectAndDraw(hog, frame);
imshow("people detector", frame);
int c = waitKey( vc.isOpened() ? 10 : 0 ) & 255;
if ( c == 'q' || c == 'Q' || c == 27)
break;
}
return 0;
}
CMake:
cmake_minimum_required(VERSION 3.7)
project(HoGPeopleDetector)
set(CMAKE_CXX_STANDARD 11)
find_package(OpenCV REQUIRED)
set(SOURCE_FILES main.cpp)
add_executable(HoGPeopleDetector ${SOURCE_FILES})
target_link_libraries(HoGPeopleDetector ${OpenCV_LIBS} "-static")
ABout target_link_libraries(HoGPeopleDetector ${OpenCV_LIBS} "-static") in static I don't use specific cmake command for visual studio
and "EXE size increased to 1.6 MB from 200 KB" I think it is 200MB
I don't need all libraries, my application is just a simple application. AFAIK, Visual Studio does not use CMake, so it's a little bit different. I edited the post with app code and CMake, you can look again
"Visual Studio does not use CMake," wrong
${OpenCV_LIBS} might still point to your old dynamic libs ? (when in doubt, remove them, maybe)
There is a Linker option for Static linking in Visual Studio, so you don't need to make any change on CMake. My IDE is using MinGW and CMake, I need to solve this with MinGW or CMake parameters
@berak I have changed the environment variable, %OpenCV_DIR% is pointing to correct directory. How can I check OpenCV_LIBS ?
message( ${OpenCV_LIBS} )
in the cmakelists.txt@berak I reset the CMake cache and reloaded the project after adding the new message command, after a long waiting, IDE has indexed the files and libraries again. EXE size increased to 9.5MB now. Tried it on my virtual machine which does not have OpenCV installed, EXE is working but I'm having another problem. Even though I put the video.mp4 file to correct directory (C:\OpenCV\video.mp4), EXE can't find the file
" EXE size increased to 9.5MB now. " -- that's what i get with mingw, too.
" EXE can't find the file" -- even if you succeeded linking statically, there'S always an exception ;)
this time, it's opencv_ffmpeg320XXX.dll, you will need that either on t, he path or next to your app.
(this dll is still linked dynamically, to obercome a license problem, long story, youcan't avoid it)
Ok solved, related to the codec. Put the opencv_ffmpeg310.dll with the same directory with your EXE on the new machine. I'm writing the solution as the answer.