System designTroubleshooting

CMake prefix path set but DLL not found at run time

The CMake prefix path is a build-time setting only. Why the DLL is not found at run time, how to read its name, and the post-build copy step that ends it.

LumaSpec Vision11 min read Share on LinkedIn

On this page 9 sections
  1. 01Why does CMake find OpenCV but Windows can't find the DLL?
  2. 02Why does the missing DLL's name end in a d?
  3. 03Where does Windows actually search for a DLL when your exe starts?
  4. 04What is the quickest fix for the next test run?
  5. 05How do you make every build copy the right DLL by itself?
  6. 06How do you list every DLL your executable will ask for?
  7. 07Why does it run on one machine and fail on another?
  8. 08What has to change before the exe runs on a line-side controller?
  9. 09Questions

You set CMAKE_PREFIX_PATH, CMake configured clean, and the linker finished. The executable still dies before its first frame with a dialog naming opencv_world4100d.dll. Nothing about the build went wrong: the failure sits between the two lookups every Windows vision application makes — CMake resolving the library at build time, the Windows loader resolving the DLL at run time. This page is for anyone building a machine-vision SDK's C++ examples in Visual Studio: grab-image samples, 3D profiler samples, GUI examples. You will learn to decode the missing DLL's name, list every DLL your exe will ask for, and set up a copy step that keeps the right file beside it for Debug and Release alike.

Why does CMake find OpenCV but Windows can't find the DLL?

CMAKE_PREFIX_PATH does all of its work while CMake configures the build. That is why the headers and the matching opencv_world4100d import library are found and the link step succeeds. The finished executable never receives that path, and the Windows loader does not search it when your process starts.

Three tools look things up in sequence, and only the first two read that variable:

  • Configure time. find_package(OpenCV) follows CMAKE_PREFIX_PATH to OpenCV's CMake config package. Passing -DCMAKE_PREFIX_PATH=C:/opencv/build in the CMake command arguments field of the Visual Studio CMake settings is exactly the right move — that part of your set-up is not the problem.
  • Link time. The linker reads the small import library from the config package's lib folder and records which DLL your exe will need.
  • Run time. The loader wants the real opencv_world4100d.dll and searches the folders listed two sections down. It finds nothing, Windows shows the dialog, and your first frame never happens.

If CMake stops instead, with OpenCV not found at configure time, that is the build-time half of this pair and it has its own fix: CMake can't find OpenCV in SDK samples: fix the config path.

You meet the run-time half fastest when building the sample that ships with a camera SDK — a first grab-image example for an area scan camera such as this 20 MP, 1-inch USB3 mono model:

Area scan camerasHikrobot MV-CS200-10UM 20 MP Area Scan Camera, USB3.0, IMX183, 2nd Gen., MonoMV-CS200-10UM
Sensor format
1"
Lens mount
C-mount
Interface
USB3
Resolution
16-25 MP
$759.00View partBuild a system with it

SDK examples for 3D sensors — for a projected structured-light camera such as the MV-DPS200P-02 — configure, link and fail the same way, so nothing below is camera-specific.

3D sensorsHikrobot MV-DPS200P-02 Projected structured-light 3D cameraMV-DPS200P-02
Type
Stereo / structured light
$8,829.00 · quotedView and quote

Why does the missing DLL's name end in a d?

The trailing d is OpenCV's debug suffix. A Debug configuration links the debug import library, so the loader demands opencv_world4100d.dll, while a Release build of the same source demands opencv_world4100.dll. The four digits are the OpenCV version: 4.10.0 becomes 4100, 4.11.0 becomes 4110.

So the dialog name is a precise report, not a generic error. Read it as configuration plus version:

The dialog names Your build expects What it tells you
opencv_world4100d.dll Debug, OpenCV 4.10.0 Copy that exact file from the 4.10.0 build folder beside the exe
opencv_world4110d.dll Debug, OpenCV 4.11.0 A different OpenCV version is beside the exe or on PATH than the one CMake linked
opencv_world4100.dll Release, OpenCV 4.10.0 A release build picked up a debug file, or the copy step only ever ran for Debug

Two installed OpenCV versions is how 4100 and 4110 get mixed up in the first place: the file beside your exe and the file CMake linked can differ silently, so treat the digits in the dialog as ground truth. One platform note: the prebuilt OpenCV Windows package ships 64-bit DLLs, so build an x64 profile such as x64-Debug; a 32-bit binary anywhere in the chain fails with this same dialog, or with a bad-image error, even when every file is present.

Where does Windows actually search for a DLL when your exe starts?

With default settings the loader checks five places, in order: the folder that contains your exe, C:\Windows\System32, C:\Windows, the current working directory, and finally every folder listed in PATH. CMAKE_PREFIX_PATH, your OpenCV build folder and your project folder appear nowhere in that list.

That order explains most of what you will see:

  1. The exe's own folder wins. This is why copying beside the executable works on any machine, and why the automatic copy step later in this page is the durable fix.
  2. PATH is checked last. A stray same-named DLL sitting in System32 outranks everything your project does; leave system folders alone.
  3. Dependencies cascade. Each DLL resolves its own imports with the same rules, so fixing the currently named file simply moves the dialog to the next name.
  4. The launch method changes nothing. Visual Studio's debugger and a double-click in Explorer use the same application-folder-first search; what differs between machines is file layout and PATH.

What is the quickest fix for the next test run?

Copy the exact file the dialog names into the folder that holds your exe — for OpenCV 4.10.0 that is opencv_world4100d.dll, taken from the bin folder of the OpenCV build directory you passed to CMAKE_PREFIX_PATH.

Four steps, two minutes:

  1. Read the exact name from the dialog, the d suffix and version digits included.
  2. Open the OpenCV build folder from your -DCMAKE_PREFIX_PATH=... argument; in the self-unpacking Windows package the DLLs sit in its bin subfolder, for example C:\opencv\build\bin.
  3. Copy the DLL into the exe's output folder. In a Visual Studio CMake build of an SDK example that folder sits under the profile directory, for instance out\build\x64-Debug\bin, sometimes one level deeper in bin\Debug — the build log names the exact path where it wrote the target.
  4. Start the exe. If another dialog appears it names the next missing dependency; repeat until the application window opens.

For interactive debug sessions there is a lighter variant: prepend the OpenCV bin folder to PATH in the project's debugging settings — the same property page that holds your command arguments — as PATH=C:\opencv\build\bin;%PATH%. That helps only processes launched from that project. The exe carried to the bench fails the same way as before, which is why the automatic copy in the next section is the fix that lasts.

How do you make every build copy the right DLL by itself?

Add a post-build rule to the example's CMakeLists that copies the linked OpenCV target's runtime file next to the executable. The generator expression resolves per configuration, so Debug builds get opencv_world4100d.dll and Release builds get opencv_world4100.dll with nothing edited by hand.

# vision_app is a placeholder for the example's real target name in its CMakeLists.txt
add_custom_command(TARGET vision_app POST_BUILD
  COMMAND ${CMAKE_COMMAND} -E copy_if_different
          $<TARGET_FILE:opencv_world>
          $<TARGET_FILE_DIR:vision_app>)

The CMake pieces are standard, documented behaviour: add_custom_command(TARGET ... POST_BUILD) runs after linking, ${CMAKE_COMMAND} -E copy_if_different is CMake's built-in copy tool, $<TARGET_FILE:target> expands to the runtime file of the linked target — the DLL — for the configuration being built, and $<TARGET_FILE_DIR:target> is the folder that holds the exe. opencv_world is the imported target OpenCV's config package defines when the build links the world module; if your example links individual modules instead, give each one the same treatment. GUI examples built on Qt link several more libraries — one copy line per target covers them.

Prove it once, then trust it. Delete the DLL from the output folder, rebuild, and check that it came back:

del out\build\x64-Debug\bin\opencv_world4100d.dll
cmake --build out\build\x64-Debug
dir out\build\x64-Debug\bin

The file reappears next to the exe and the dialog stays gone. From then on every rebuild refreshes the right file automatically, including the switch to the release DLL when you change configuration — the switch where hand-copied files usually get forgotten.

How do you list every DLL your executable will ask for?

The start-up dialog names one missing file at a time, so the quickest complete list comes from the import table: run dumpbin /DEPENDENTS on your exe from a Visual Studio developer command prompt and it prints every DLL name your build linked, suffix and version digits included.

From that list the work is mechanical:

  • Run dir on the exe folder and compare. Every name in the import table that is not beside the exe is a file to copy.
  • Point the same command at opencv_world4100d.dll itself and you will see its own imports — the Visual C++ runtime entries that decide deployment, covered in the final section.
  • Without the tool, repeated launches work too: each start resolves the next missing import, fine for two or three files and tedious beyond that.

If the failure appears earlier in the pipeline instead — unresolved externals at link time, a missing .lib at configure time — that is the build-time lookup misfiring, and it has its own diagnostics: CMake missing dependency diagnostics for vision builds.

Why does it run on one machine and fail on another?

Because run-time resolution travels with the exe rather than with CMake. The machine that works has the DLL beside the executable, or the OpenCV bin folder on its PATH, and the failing machine has neither. The identical binary loads there and fails here.

Ranked by how often each turns out to be the cause, with the test that settles it:

  1. The DLL sits beside the exe on one machine only. Run dir on both output folders and compare against the import list.
  2. PATH differs. Run echo %PATH% in the same user account and session the exe launches from; a Windows service or a second account does not inherit your session's PATH.
  3. Configuration mismatch. The d suffix in the dialog against the profile you launched: a Debug exe fails next to a release-only folder, and the reverse.
  4. Version mismatch. The dialog's digits against the OpenCV build folder named in CMAKE_PREFIX_PATH: 4100 and 4110 installed side by side is the classic trap.
  5. Bitness mismatch. The prebuilt OpenCV Windows package is 64-bit only; a 32-bit build fails with the same dialog even with the file sitting right there.

This is the load-time face of a split that runs through all of vision integration — set up there, failing here. The image-side twin is camera works in setup but grey image at runtime: same shape, one layer up. When the two machines differ in build environment rather than file layout — a container, a second SDK install — the same logic applies on the build side, as camera SDK header not found in a containerized build shows.

What has to change before the exe runs on a line-side controller?

Build Release and carry the release DLL. A Debug build asks for the debug Visual C++ runtime, which exists only on machines with Visual Studio installed. A Release build needs just the redistributable runtime, which any bench PC or line-side controller can have installed once.

Prevention, as a list you can run before every deployment:

  • Ship the configuration you tested, built as Release; keep Debug for the debugger.
  • Keep the post-build copy step so the matching DLL is part of the build output, not a manual favour.
  • Deploy the whole folder: the exe and the DLLs beside it are one application.
  • Install the Microsoft Visual C++ redistributable on each target machine once; the release OpenCV DLL loads it at start-up.
  • Keep one OpenCV version per machine wherever practical; two versions is where 4100-and-4110 confusion starts.
  • Leave build tools on the development PC — a line-side machine is a run-time machine, by design.

That last point is how vision controllers are meant to be used: a machine such as the MV-VC3301H-128G66 — Intel Core i3, 8 GB of RAM, a 128 GB SSD, 5+ LAN ports and 4 built-in light channels — runs your deployed folder and the cameras while Visual Studio stays on your desk.

Vision controllersHikrobot MV-VC3301H-128G66 I3-8100, 8GB+128G SSD, No PoE, PCIe expansion supported, Incl. VM6200Pro licenseMV-VC3301H-128G66
LAN ports
5+ LAN ports
USB 3 ports
3-4 USB 3 ports
Light outputs
4 built-in channels
Memory
8 GB
$2,419.00View partBuild a system with it

Once the exe starts and grabs frames, the next Windows-side stumbles are stream-format ones; if the SDK then reports no matching media type for a pixel format, that fix is its own short article: no matching media type for pixel format: fix stream setup on Windows. To size the machine that will run your build, start from the vision controllers category, or look at industrial mini PCs if you need general compute alongside the controller; the camera finder covers the camera side. More build-and-integration fixes sit on the systems topic page.

Questions

Can I just put the OpenCV bin folder on PATH instead of copying the DLL?

Yes, for interactive runs on your development PC: prepend C:\opencv\build\bin to PATH in the project's debugging settings or in your own session. PATH is checked last, so a same-named DLL in System32 still wins, and a Windows service, a scheduled task or a second user account reads the machine PATH rather than your session's edits. For anything that leaves your desk, use the post-build copy.

Why does the SDK example build and run out of the box for the vendor?

The vendor builds in the installed SDK location, with the exact OpenCV version the examples were tested against, so either their build copies the DLLs or their PATH already resolves them. Move the development folder, switch OpenCV versions or change the drive layout, and that silent resolution breaks. Check the example's CMakeLists for an existing copy rule first and align it with your versions before adding your own.

Do I need the debug DLLs if I only ever ship release builds?

No. Debug DLLs exist so you can step through code with full symbols on a development machine that has Visual Studio. Ship Release: link without the d suffix, copy opencv_world4100.dll instead, and install the Microsoft Visual C++ redistributable on the target once. If you never run Debug configurations you never need the debug DLLs on a target — though a Debug build will then fail there by design.

Can I link OpenCV statically so there are no DLLs to carry?

Only by building OpenCV from source with static libraries enabled: the prebuilt Windows package ships DLLs and import libraries only. Static linking removes the load-time dependency and suits locked-down, single-purpose tools, but it costs a full OpenCV build, larger executables and a rebuild whenever you update OpenCV. For SDK examples and day-to-day vision stations, the copy step is less work and easier to diagnose.

The dialog names a Qt or other toolkit DLL — is the fix the same?

Yes: find that DLL in the toolkit's own bin folder and add it to the same post-build copy rule. GUI samples usually need more than one file, and some toolkits also load plug-ins from fixed subfolders beside the executable rather than through the search path, so copy whole folders where that toolkit's deployment notes say to rather than only the main DLL.