1

How Can I link to external library that I have packed with my project?

Here is how my project is set up:

I have a folder called App and that is where my main.cpp sits.

C:\Raph\src\App main.cpp 

I also have a folder called "ExternalLibrary" and that is where I have bundled Qt Library that I need to use in my project:

C:\Raph\src\ExternalLibrary\Platform\Windows\Qt5.6\VS2013_64bit 

It contains 3 folders:

**bin** moc.exe rcc.exe uic.exe ...... bunch of Qt dll files **include** bunch of Qt header files **lib** bunch of Qt lib files 

I need to setup Cmake to do three things:

  1. Link to Qt library that I have packed in "ExternalLibrary" dynamically.

  2. Automatically performs moc.exe, uic.exe, rcc.exe every time I add a Qt class or a resource in the project. I also dont need any of the generated moc_myClassname.cpp to show up in the project.

  3. I want All the Qt dlls to end up in my bin folder where the executable sits. e.g:

    C:\Raph\build\Raph\Windows\x64\Debug\bin

    Raph.exe + all necessary Qt Dlls

1
  • 1
    Too broad: several unrelated questions. In short: 1. Google find_package + QT. 2. Automatic revealing of new source files is not a feature of CMake. Normally you need to modify CMakeLists.txt every time you add/remove source. 3. Just create rule which will copy files into destination directory. Try to concentrate on single problem and perform basic search for it before asking. Commented Apr 23, 2016 at 17:47

1 Answer 1

1

(1) You can find the Qt Library the following way:

find_package(Qt5Core [...] 5.6 REQUIRED) add_executable(someExe file1.cpp) target_link_libraries(someExe Qt5::Core) 

Note that you should keep the original directory stucture of Qt, also containing the Qt cmake scripts, e.g. lib/cmake/Qt5/Qt5Config.cmake

If you want a specific directory to be included when searching for Qt, you can do (before you search for Qt):

set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} "./your/path") 

This can for example be the directory you supply.

(2) You can use cmake's automoc feature. Just add

set(CMAKE_AUTOMOC ON) set(CMAKE_INCLUDE_CURRENT_DIR ON) 

at the beginning of your cmake script. CMake also supports AUTOUIC and AUTORCC. I haven't tried them yet, but the probably work similar.

(3) You can for example add a custom target to your project, that copies the dlls. When you build that target, all the dlls will be copied. The paths of the dlls you can get from the targets that the Qt find script defines (like Qt5::Core).

get_target_property(LOC_R Qt5::Core LOCATION_RELEASE) get_target_property(LOC_D Qt5::Core LOCATION_DEBUG) 

However, you should also scan these target for dependencies (other dlls they depend on). You could write a macro that scans a whole list of targets for the correspondig dlls and adds them to a list, let's call these RELEASE_DLLS and DEBUG_DLLS:

macro(copydlls RELEASE_DLLS DEBUG_DLLS MODULELIST) foreach(ELEMENT ${${MODULELIST}}) get_target_property(LOC_R ${ELEMENT} LOCATION_RELEASE) get_target_property(LOC_D ${ELEMENT} LOCATION_DEBUG) list(APPEND ${RELEASE_DLLS} ${LOC_R}) list(APPEND ${DEBUG_DLLS} ${LOC_D}) get_target_property(DEPENDENCIES_RELEASE ${ELEMENT} IMPORTED_LINK_DEPENDENT_LIBRARIES_RELEASE) foreach(DEPENDENCY ${DEPENDENCIES_RELEASE}) if(TARGET ${DEPENDENCY}) get_target_property(LOC_R ${DEPENDENCY} LOCATION_RELEASE) if(${LOC_R} MATCHES ".dll$") list(APPEND ${RELEASE_DLLS} ${LOC_R}) endif() endif() endforeach() get_target_property(DEPENDENCIES_DEBUG ${ELEMENT} IMPORTED_LINK_DEPENDENT_LIBRARIES_DEBUG) foreach(DEPENDENCY ${DEPENDENCIES_DEBUG}) if(TARGET ${DEPENDENCY}) get_target_property(LOC_D ${DEPENDENCY} LOCATION_DEBUG) if(${LOC_D} MATCHES ".dll$") list(APPEND ${DEBUG_DLLS} ${LOC_D}) endif() endif() endforeach() get_target_property(DEPENDENCIES_RELEASE ${ELEMENT} IMPORTED_LINK_INTERFACE_LIBRARIES_RELEASE) foreach(DEPENDENCY ${DEPENDENCIES_RELEASE}) if(TARGET ${DEPENDENCY}) get_target_property(LOC_R ${DEPENDENCY} LOCATION_RELEASE) if(${LOC_R} MATCHES ".dll$") list(APPEND ${RELEASE_DLLS} ${LOC_R}) endif() endif() endforeach() get_target_property(DEPENDENCIES_DEBUG ${ELEMENT} IMPORTED_LINK_INTERFACE_LIBRARIES_DEBUG) foreach(DEPENDENCY ${DEPENDENCIES_DEBUG}) if(TARGET ${DEPENDENCY}) get_target_property(LOC_D ${DEPENDENCY} LOCATION_DEBUG) if(${LOC_D} MATCHES ".dll$") list(APPEND ${DEBUG_DLLS} ${LOC_D}) endif() endif() endforeach() endforeach() endmacro() 

Then you could get all the Qt dlls in a list, by calling this macro with:

IF(MSVC) set(QT_MODULES "Qt5::Core" "Qt5::Gui" "Qt5::Widgets") set(RELEASE_DLLS) set(DEBUG_DLLS) copydlls(RELEASE_DLLS DEBUG_DLLS QT_MODULES) ENDIF(MSVC) 

When you've retrieved that information, you can create your custom target the following way. Let's assume you have all your dll paths in the lists RELEASE_DLLS and DEBUG_DLLS and your executable names as a list in TARGETS. Then you could do something like this:

if(MSVC) set(COPY_COMMAND_RELEASE "-E copy_if_different ") set(COPY_COMMAND_DEBUG "-E copy_if_different ") list(REMOVE_DUPLICATES RELEASE_DLLS) list(REMOVE_DUPLICATES DEBUG_DLLS) foreach(DLL ${RELEASE_DLLS}) string(CONCAT COPY_COMMAND_RELEASE "${COPY_COMMAND_RELEASE} \"${DLL}\" ") endforeach() foreach(DLL ${DEBUG_DLLS}) string(CONCAT COPY_COMMAND_DEBUG "${COPY_COMMAND_DEBUG} \"${DLL}\" ") endforeach() string(CONCAT COPY_COMMAND_RELEASE ${COPY_COMMAND_RELEASE} "\"${CMAKE_CURRENT_BINARY_DIR}/Release\" ") string(CONCAT COPY_COMMAND_DEBUG ${COPY_COMMAND_DEBUG} "\"${CMAKE_CURRENT_BINARY_DIR}/Debug\" ") add_custom_target(COPY_DLLS) foreach(EXECUTABLE ${TARGETS}) add_custom_command(TARGET COPY_DLLS PRE_BUILD COMMAND ${CMAKE_COMMAND} ${COPY_COMMAND_RELEASE} COMMENT "Copying dlls to executable directory...") add_custom_command(TARGET COPY_DLLS PRE_BUILD COMMAND ${CMAKE_COMMAND} ${COPY_COMMAND_DEBUG} COMMENT "Copying dlls to executable directory...") endforeach() endif() 

If you want this target to be executed every time one of your other targets is built, you can do:

foreach(EXECUTABLE ${TARGETS}) add_dependencies(${EXECUTABLE} COPY_DLLS) endforeach() 

Don't foget that you must also copy the platforms directory from plugins to your executable folder, for example by adding it to the copy dll target:

add_custom_command(TARGET COPY_DLLS PRE_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory ${PATH_QT_ROOT}/plugins/platforms ${CMAKE_CURRENT_BINARY_DIR}/Debug/platforms COMMAND ${CMAKE_COMMAND} -E copy_directory ${PATH_QT_ROOT}/plugins/platforms ${CMAKE_CURRENT_BINARY_DIR}/Release/platforms COMMENT "Copying Qt platforms to executable directory...") 
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.