13

I have a Visual Studio 12 project; source code written in C++; it's an OpenCV project. I want to give my compiled program to someone else, but, on other PC, I getting an error message about missing some dlls. My program using many OpenCV (maybe, not only) dll's. How can I resolve that problem? Maybe in VS 12 available an option to include all dll's in .exe? It's a pretty similar question without proper answer: include dlls in visual studio c++ 2008

Community
  • 1
  • 1
Pavlo Zvarych
  • 615
  • 2
  • 9
  • 13
  • 1
    possible duplicate of [MS Visual Studio 2012: build statically linked exe](http://stackoverflow.com/questions/18174101/ms-visual-studio-2012-build-statically-linked-exe) – Joe May 24 '14 at 12:15
  • 1
    @LuchianGrigore: You can't link DLLs statically. A DLL is structured around dynamic linking. Yes, static linkage would be the way to go but you need a static library for that. – datenwolf May 24 '14 at 12:17
  • 1
    @datenwolf yes, I meant link statically :) – Luchian Grigore May 24 '14 at 12:26
  • @Joe answer provided there (on that page) didn't help me. I already did this steps (provided by Zaw Lin). – Pavlo Zvarych May 24 '14 at 12:29

4 Answers4

18

DLLs themself can not be "statically linked" into an executable; that completely defies their purpose (well, actually you can use some really weird voodoo tricks to actually do it, but this is neither recommendable nor should you try it if you have to ask this question).

The simple solution would be to identify all the DLLs your program requires (just starting the program in the Debugger will generate a log file listing them all) and copy those DLLs into the same directory as the EXE resides in; as it happens the directory with the EXE file in is also the first directory where the system looks for DLLs before advancing to the standard system directories in default configuration. Package it up and distribute it that way.

Quaternion
  • 10,380
  • 6
  • 51
  • 102
datenwolf
  • 159,371
  • 13
  • 185
  • 298
  • I know this is a really old post, but I'm very interested in the "weird voodoo tricks" to make this work. Can you elaborate? – MooseBoys Nov 16 '17 at 18:48
  • @MooseBoys: To give a coarse summary. The steps involved would be to use a tool similar to objcopy (maybe you can even use objcopy for that) or objdump to kind of "delink" the DLL/shared object into plain object files. However DLLs/shared objects have entry points `DllMain`/`_init/_fini` which are called upon special times. Also a couple of special sections for symbol location translation. Windows DLLs permit for interprocess shared memory sections. etc. etc. Ultimately you'd have split up everything into objects and relink as a static library. – datenwolf Nov 16 '17 at 22:43
  • @MooseBoys: Another method is to simply embed the whole DLL/shared object as it is as a binary blob inside the executable. Upon program start that part of the executable could be remapped as a virtual file / file view and passed to the dynamic linker as such. – datenwolf Nov 16 '17 at 22:46
  • @MooseBoys: And yet another method would be implementing a custom dynamic linker in the executable and let that work with the binary blob of an embedded DLL/shared object directly. – Except for the delink/relink way, the two other methods are outright scary (mostly for security reasons). – datenwolf Nov 16 '17 at 22:48
  • Wrong. Look at this https://stackoverflow.com/questions/26103966/how-can-i-statically-link-standard-library-to-my-c-program – César Javier Mendoza May 21 '18 at 14:28
  • @CésarJavierMendoza the Q&A you've linked is covering **statically** linking. This questionhowever is about how to include (preexisting) DLLs into an executable. You can link statically only if you have a static library at hand. But if all you have is the DLLs then plain boring and simple static linking *is not* possible. – datenwolf May 22 '18 at 18:32
  • @Microsoft: it is possible in Java using MAVEN standard technologies. It is also possible on SIEMENS BS2000 Mainframe using BINDER before 2000 ! For those that are interesting, see BLSSERV on http://manuals.ts.fujitsu.com/index.php?id=1-2-12672-13963 / This is one of the best products on Mainframe I have never seen. – schlebe Feb 28 '19 at 10:45
  • @schlebe: Java always comes with a runtime environment interpreter and Java builds are not native executables. They're ZIP container, that contain the `.java` and supplemental resources. Of course in that situation the JRE can do all the executable wrangling to support this: Load DLL from container into process address space, and perform all relocations and dynamic linking. Performing JIT compilation and loading code into a process space is *the* job description of a runtime environment interpreter, like the JRE. – datenwolf Feb 28 '19 at 11:12
  • 2
    @schlebe: The original question though was, how to "embed" a DLL (or statically link it) if there's no runtime environment interpreter around in the first place. This is a completely different problem scope. And comparing with other OSs is moving the goalposts, because OP asks about a specific OS and "marketing" for other systems doesn't help here. – datenwolf Feb 28 '19 at 11:14
5

the more complicated solution would be, to build static opencv libraries from src, then link your program against those, resulting in 1 large binary exe-chunk, that does not use any dlls (apart from ffmpeg, not sure about that one).

to build static libs, you'd need to run cmake with : BUILD_SHARED_LIBS=OFF

but take a deep breath, before doing that. linking your program will be sigificantly more difficult, because now you have to link all the zlib,libpng, whatever dependecies manually ( which before got conveniently linked into your dlls )

again, the most simple solution is to deploy all the opencv dlls with your program.

berak
  • 39,159
  • 9
  • 91
  • 89
4

You can use the Windows Dependency Walker to determine which DLLs your program needs to run.

Actually, this only tells you which DLLs your program needs to launch successfully. If you load DLLs dynamically (via LoadLibrary) then you are on your own.

Ferruccio
  • 98,941
  • 38
  • 226
  • 299
2

If you opt for the accepted solution (package the DLLs with the EXE file), and you don't want to go into the trouble of finding which DLLs to use, then you can copy all the OpenCV DLLs. They're not so big (65 MB on OpenCV 2.43). They are located at ...\opencvXXX\build\x64\vc10\bin\

where XXX is the OpenCV version. You can use x64 or x86 depending on your platform (32 or 64-bit). And the version of vc can be different on your system (vc9, vc10, etc...)

Hazem
  • 520
  • 5
  • 10