# Adding a library to a qt6 cmake project

**URL:** https://discourse.cmake.org/t/adding-a-library-to-a-qt6-cmake-project/5529
**Category:** Usage
**Tags:** os:windows
**Created:** [April 25, 2022, 11:36am UTC](https://discourse.cmake.org/t/adding-a-library-to-a-qt6-cmake-project/5529 "2022-04-25T11:36:45Z")
**Posts on this page:** 12
**Page:** 1

<div class="post-metadata">

### Author: ![michaelhue](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/m/a4c791/32.png) [@michaelhue](https://discourse.cmake.org/u/michaelhue)
#### Post date: [April 25, 2022, 11:36am UTC](https://discourse.cmake.org/t/adding-a-library-to-a-qt6-cmake-project/5529/1 "2022-04-25T11:36:45Z")

</div>

Hello guys,

i am just trying to use a library for a robot in my qt6 project.

in my cmake file i have added the library.h file to the project sources and i have added the library.lib file like follows:

target\_link\_libraries(RadiationMaster PRIVATE C:/git/RadiationMaster/DobotM1Dll/DobotDllM1.lib)

there are also .dll files, i have added those to the Windows/System32 folder so they can be found.

But i still get undefined reference errors when trying to compile my program.

This is the first time i try to use dlls and have no idea how to properly add libs like that to a project.

Some help or even a link to a good tutorial on the topic would be very helpful!

Thanks a lot Michael

---

<div class="post-metadata">

### Author: ![ferdnyc](https://discourse.cmake.org/user_avatar/discourse.cmake.org/ferdnyc/32/267_2.png) [@ferdnyc](https://discourse.cmake.org/u/ferdnyc)
#### Post date: [April 25, 2022, 4:33pm UTC](https://discourse.cmake.org/t/adding-a-library-to-a-qt6-cmake-project/5529/2 "2022-04-25T16:33:19Z")

</div>

Yeah, you probably don’t want to do that. What you _should_ do depends a bit on the nature of the dependency.

If the DLL is from somewhere completely external to your project (meaning, it’s supplied precompiled and you aren’t building it), you’ll probably want to define an `IMPORTED TARGET` for it. You might do this by way of a [Find module](https://cmake.org/cmake/help/latest/manual/cmake-developer.7.html#id4) for compatibility, especially if you plan to make your project available for others to build. (That hardcoded disk path isn’t going to work out so well if the build system is generated on a different machine.)

But even if you don’t use a Find module, you should still set your dependency DLL up as its own `IMPORTED` target. Specifically, you’d want a `SHARED IMPORTED` target, which should have both the `.dll` and `.lib` file paths set as properties. (You really _shouldn’t_ ever install **ANYTHING** into `C:\Windows\System32\`, that’s major hackery and a recipe for trouble. You’re better off placing the DLLs you need in the same directory as the executable, Windows will always load them from there.)

As far as your CMake target goes, though, the brute-force hardcoded version would look something like this:

```cmake
add_library(mylib SHARED IMPORTED)
set_property(TARGET mylib PROPERTY
  IMPORTED_LOCATION "full_path_to_dll_file")
set_property(TARGET mylib PROPERTY
  IMPORTED_IMPLIB "full_path_to_lib_file")
target_include_directories(mylib INTERFACE
  "full_path_to_any_header_files_needed")
target_compile_definitions(mylib INTERFACE
  [any defines to apply when the library is used])
# etc...

# Then, assuming you've created an executable build target:
add_executable(myexe ${SOURCES})
# you can link the DLL into your project's executable with:
target_link_libraries(myexe PRIVATE mylib)

```

But like I said, for portability you should really wrap that logic in a [Find module](https://cmake.org/cmake/help/latest/guide/using-dependencies/index.html#id5) that you can bundle with your project. That link has some information, but one of the best resources is reading the set of Find modules that come with CMake, they should be in a `Modules` directory somewhere in your CMake install dir. Any file named `FindSomething.cmake` on the `CMAKE_MODULE_PATH` is interpreted as a Find module for the dependency “Something”, and can be invoked from your `CMakeLists.txt` using a [`find_package(Something)`](https://cmake.org/cmake/help/latest/command/find_package.html#command:find_package) call.

The biggest advantage to setting up proper `IMPORTED` targets, when building on Windows, is that you can then use features like the [`$<TARGET_RUNTIME_DLLS>` generator expression](https://cmake.org/cmake/help/latest/manual/cmake-generator-expressions.7.html#genex:TARGET_RUNTIME_DLLS) to copy all of the necessary DLLs into the install directory when installing your binary. (Instead of putting them in `C:\Windows\System32`; seriously just say no.)

---

<div class="post-metadata">

### Author: ![ferdnyc](https://discourse.cmake.org/user_avatar/discourse.cmake.org/ferdnyc/32/267_2.png) [@ferdnyc](https://discourse.cmake.org/u/ferdnyc)
#### Post date: [April 25, 2022, 4:43pm UTC](https://discourse.cmake.org/t/adding-a-library-to-a-qt6-cmake-project/5529/3 "2022-04-25T16:43:58Z")

</div>

> [@ferdnyc](#):
>
> What you _should_ do depends a bit on the nature of the dependency.

Oh, right: If, OTOH, the DLL is something you’re building from source, rather than building it _first_ and then incorporating it into your project already-built, one option is to import the source repo for the DLL as an [ExternalProject](https://cmake.org/cmake/help/latest/module/ExternalProject.html) and build it _with_ your own project. You can set the build up so that CMake will download the code directly from its source repo, compile the DLL, and incorporate it into your project as a library target constructed from the build directory, all as a prerequisite to compiling your code.

For projects that other people might have an interest in building for themselves, that’s a handy way to incorporate dependencies that aren’t already separately-installable parts of the CMake ecosystem.

---

<div class="post-metadata">

### Author: ![michaelhue](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/m/a4c791/32.png) [@michaelhue](https://discourse.cmake.org/u/michaelhue)
#### Post date: [April 26, 2022, 7:58am UTC](https://discourse.cmake.org/t/adding-a-library-to-a-qt6-cmake-project/5529/4 "2022-04-26T07:58:16Z")

</div>

Thanks a lot for the reply, i was not aware that windows will always load the DLLs if they are in the same folder than the executeable, thats for sure a better way than using the System32 folder!

When it comes to absolute paths you are correct, that it is not a good idea, i was just trying to get it working somehow and did not know better how to get my lib working.

I will try to get the library working with your information and will update the thread accordingly.

---

<div class="post-metadata">

### Author: ![xhustango](https://discourse.cmake.org/user_avatar/discourse.cmake.org/xhustango/32/1614_2.png) [@xhustango](https://discourse.cmake.org/u/xhustango)
#### Post date: [April 26, 2022, 8:59am UTC](https://discourse.cmake.org/t/adding-a-library-to-a-qt6-cmake-project/5529/5 "2022-04-26T08:59:04Z")

</div>

Hi Michael,

You should import the \*.lib files using the` target_link_libraries` to your RadiationMaster. The DLLs need to be copied to the same folder the RadiationMaster is. You could use an add\_custom\_command for that.

Something like

```
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E copy_if_different
    "PathOfDll/radiation.dll"
    $<TARGET_FILE_DIR:${PROJECT_NAME}>)
```

---

<div class="post-metadata">

### Author: ![ferdnyc](https://discourse.cmake.org/user_avatar/discourse.cmake.org/ferdnyc/32/267_2.png) [@ferdnyc](https://discourse.cmake.org/u/ferdnyc)
#### Post date: [April 28, 2022, 3:40am UTC](https://discourse.cmake.org/t/adding-a-library-to-a-qt6-cmake-project/5529/6 "2022-04-28T03:40:41Z")

</div>

👍 That’ll work, if you want to be able to run your executable from the build directory. Though, if you’ve set up an `IMPORTED` target for the dependenc(y/ies), you can easily copy the DLLs for any of its dependencies in one fell swoop using `TARGET_RUNTIME_DLLS`:

```cmake
add_custom_command(TARGET myexe POST_BUILD
  COMMAND ${CMAKE_COMMAND} -E copy_if_different
  $<TARGET_RUNTIME_DLLS:myexe>
  $<TARGET_FILE_DIR:myexe>
  COMMAND_EXPAND_LISTS)

```

If you also want to be able to _install_ it with the relevant DLLs, you can make use of CMake 3.21+'s [`IMPORTED_RUNTIME_ARTIFACTS` support](https://cmake.org/cmake/help/latest/command/install.html#installing-imported-runtime-artifacts), alongside installing the built targets themselves:

```cmake
install(TARGETS myexe
  RUNTIME DESTINATION bin)
install(IMPORTED_RUNTIME_ARTIFACTS mylib
  RUNTIME DESTINATION bin)

```

That’ll install the `myexe` target’s executable output file, and the `.dll` file associated with the `mylib` target, together into the directory `$<INSTALL_PREFIX>/bin/`. (As with `$<TARGET_RUNTIME_DLLS>`, this will only work if `mylib` is a `SHARED IMPORTED` target with the full path to the DLL set in its `IMPORTED_LOCATION` property.)

---

<div class="post-metadata">

### Author: ![michaelhue](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/m/a4c791/32.png) [@michaelhue](https://discourse.cmake.org/u/michaelhue)
#### Post date: [April 28, 2022, 1:20pm UTC](https://discourse.cmake.org/t/adding-a-library-to-a-qt6-cmake-project/5529/7 "2022-04-28T13:20:37Z")

</div>

thanks again for the answers, a short update on the topic:  
i had quite some issues with the dll and down the line dependencies. I solved these by porting everything back to Qt5/32Bit, for some reason i could not get the 64Bit version of the lib to work with qt6…

i will definitly tr out the add\_custom\_command to get the DLLs into the right folder

---

<div class="post-metadata">

### Author: ![michaelhue](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/m/a4c791/32.png) [@michaelhue](https://discourse.cmake.org/u/michaelhue)
#### Post date: [April 29, 2022, 11:16am UTC](https://discourse.cmake.org/t/adding-a-library-to-a-qt6-cmake-project/5529/8 "2022-04-29T11:16:18Z")

</div>

for some reason that does only work up until two DLLs, if i try to copy more i get the following:

```auto
Error copying file (if different) from "multiple_given_paths" to "destination_folder".

```

@ferdnyc  
the same does also happen when using $\<TARGET\_RUNTIME\_DLLS:myexe\>, it tries to copy multiple files but fails

---

<div class="post-metadata">

### Author: ![ferdnyc](https://discourse.cmake.org/user_avatar/discourse.cmake.org/ferdnyc/32/267_2.png) [@ferdnyc](https://discourse.cmake.org/u/ferdnyc)
#### Post date: [May 1, 2022, 1:14pm UTC](https://discourse.cmake.org/t/adding-a-library-to-a-qt6-cmake-project/5529/9 "2022-05-01T13:14:51Z")

</div>

Hmm, strange.

Did you make sure to include `COMMAND_EXPAND_LISTS` in the arguments to `add_custom_command()`?

If so, it’s possible `copy_if_different` doesn’t support multiple source files for some reason. You could try using just `copy` instead. That’s what [the example](https://cmake.org/cmake/help/latest/manual/cmake-generator-expressions.7.html?highlight=target_runtime_dlls#genex:TARGET_RUNTIME_DLLS) I cheesed that command from was using.

---

<div class="post-metadata">

### Author: ![michaelhue](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/m/a4c791/32.png) [@michaelhue](https://discourse.cmake.org/u/michaelhue)
#### Post date: [May 2, 2022, 7:23am UTC](https://discourse.cmake.org/t/adding-a-library-to-a-qt6-cmake-project/5529/10 "2022-05-02T07:23:48Z")

</div>

Aah thanks again, i forgot the COMMAND\_EXPAND\_LISTS!  
Now everything works just fine 🙂

---

<div class="post-metadata">

### Author: ![xhustango](https://discourse.cmake.org/user_avatar/discourse.cmake.org/xhustango/32/1614_2.png) [@xhustango](https://discourse.cmake.org/u/xhustango)
#### Post date: [May 2, 2022, 8:22am UTC](https://discourse.cmake.org/t/adding-a-library-to-a-qt6-cmake-project/5529/11 "2022-05-02T08:22:03Z")

</div>

You could also run windeployqt, something like:

```
# Run windeployqt

# Retrieve the absolute path to qmake and then use that path to find
# the binaries
get_target_property(_qmake_executable Qt6::qmake IMPORTED_LOCATION)
get_filename_component(_qt_bin_dir "${_qmake_executable}" DIRECTORY)
find_program(WINDEPLOYQT_EXECUTABLE windeployqt HINTS "${_qt_bin_dir}")
find_program(MACDEPLOYQT_EXECUTABLE macdeployqt HINTS "${_qt_bin_dir}")

add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
        COMMAND "${CMAKE_COMMAND}" -E
        env PATH="${_qt_bin_dir}" "${WINDEPLOYQT_EXECUTABLE}"
        "$<TARGET_FILE:${PROJECT_NAME}>"
        COMMENT "Running windeployqt...")

```

That’s for copying the qt dlls, the ones your target needs.

---

<div class="post-metadata">

### Author: ![michaelhue](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/m/a4c791/32.png) [@michaelhue](https://discourse.cmake.org/u/michaelhue)
#### Post date: [May 2, 2022, 11:54am UTC](https://discourse.cmake.org/t/adding-a-library-to-a-qt6-cmake-project/5529/12 "2022-05-02T11:54:13Z")

</div>

Thanks, that should also work.  
But i’m fine with how i have it now.  
It was just the COMMAND\_EXPAND\_LISTS parameter that was missing, that’s why it did not work…
