I have a simple project structure derived from the amazing tutorial
https://rix0r.nl/blog/2015/08/13/cmake-guide/
It looks as follows:
- src
- CMakeLists.txt
- mylib
- include/mylib/mylibclass.h
- src/mylibclass.cpp
- CMakeLists.txt
- myapp
- src/myapp.cpp
- CMakeLists.txt
The top level CMakeLists.txt contains:
cmake_minimum_required( VERSION 3.6 )
project( sample_project VERSION 0.1 LANGUAGES CXX )
set( BUILD_SHARED_LIBS ON CACHE BOOL "" )
add_subdirectory( mylib )
add_subdirectory( myapp )
The CMakeLists.txt in the mylib folder contains:
add_library( mylib src/mylibclass.cpp include/mylib/mylibclass.h )
set_target_properties( mylib PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON )
target_include_directories( mylib
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> PRIVATE src )
And the one in the myapp folder contains:
add_executable( myapp src/myapp.cpp )
target_link_libraries( myapp mylib )
I want to use this structure to develop both mylib (as a shared or static library as determined by BUILD_SHARED_LIBS) and myapp. For this, I want to set myapp as my startup project in Visual Studio and compile and run in the MSVC debugger. This is not possible for the shared library case without extra CMake code, as the myapp.exe doesn't know where to find the mylib.dll.
What is best CMake practice to tell the program where to find the dll?
Edit:
Based on the suggestions by #Andre, I've added the following lines to the top level CMakeLists.txt:
set( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/out CACHE STRING "" )
set( CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/out CACHE STRING "" )
The problem occurs, because your mylib.dll is not in the same folder as your myapp.exe nor is it in the %PATH% environment variable when Visual Studio tries to start your myapp.exe
The obvious solution is to make sure both dll and exe are in the same folder. There are several ways to do this:
Put both exe and dll into a single "output" directory by setting the RUNTIME_OUTPUT_DIRECTORY and the LIBRARY_OUTPUT_DIRECTORY properties on your targets:
set_target_properties( myapp PROPERTIES RUNTIME_OUTPUT_DIRECTORY
${sample_project_BINARY_DIR}/build_results/bin )
set_target_properties( mylib PROPERTIES LIBRARY_OUTPUT_DIRECTORY
${sample_project_BINARY_DIR}/build_results/bin )
This will produce the myapp.exe and mylib.dll into a single build_results/bin folder in your top-level build folder.
Or by setting the the global CMAKE_RUNTIME_OUTPUT_DIRECTORY and CMAKE_LIBRARY_OUTPUT_DIRECTORY variables which will do this for all targets in your sample_project.
Copy the dll to the exe location after building, e.g. with
add_custom_command(TARGET mylib
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy mylib.dll ${myapp_BINARY_DIR}/.
)
Related
I have the following CMake file that CLion picked up automatically and created a run-debug profile for:
cmake_minimum_required(VERSION 3.23)
project(shadowgate)
set(CMAKE_CXX_STANDARD 20)
include_directories(I:/onedrive/SDL2/include libs)
link_directories(I:/onedrive/SDL2/lib/x64 libs)
#lua54.dll needs to be copied to windows/system32 folder
add_library(Lua STATIC IMPORTED GLOBAL)
set_target_properties(Lua PROPERTIES
IMPORTED_LOCATION "I:/onedrive/lua4/liblua54.a"
INTERFACE_INCLUDE_DIRECTORIES "I:/onedrive/lua4/include"
)
file(GLOB_RECURSE SRC_FILES CONFIGURE_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp
${CMAKE_CURRENT_SOURCE_DIR}/libs/imgui/*.cpp)
add_executable(${PROJECT_NAME} ${SRC_FILES} )
#looks for a file with .lib extension
target_link_libraries(${PROJECT_NAME} SDL2main SDL2 SDL2_ttf SDL2_image SDL2_mixer Lua)
#AssetManager
add_custom_target(copy_assets
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_LIST_DIR}/assets ${CMAKE_CURRENT_BINARY_DIR}/assets
)
add_dependencies(${PROJECT_NAME} copy_assets)
I don't see any options in CLion to copy this debug profile to a 'release' profile. I tried moving the executable to a seperate folder and add the needed .dll files next to it, but then it's still not finding the dlls.
How can I make a proper release of this project, where it will look for the .dll files in it's own directory?
I want to build an application that depends on the OpenCV (version 3.4.6) viz module. This module has the VTK library (version 7.1.1) as dependency. I want to use ExternalProject to build both, the vtk library and the opencv viz module and subsequently want to build the main application, all in one cmake run.
.
├── CMakeLists.txt
├── deps
│ └── CMakeLists.txt
└── main.cpp
I am using the cmake ExternalProject module to build both opencv and vtk inside a subdirectory like this:
deps/CMakeLists.txt
cmake_minimum_required(VERSION 3.14)
project(dependencies)
include(ExternalProject)
ExternalProject_add(
vtklib
GIT_REPOSITORY https://github.com/Kitware/vtk
GIT_TAG v7.1.1
GIT_PROGRESS TRUE
UPDATE_COMMAND ""
CMAKE_ARGS
-DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}
-DBUILD_TESTING=OFF
-DBUILD_EXAMPLES=OFF
-DVTK_DATA_EXCLUDE_FROM_ALL=ON
-DVTK_USE_CXX11_FEATURES=ON
-Wno-dev
)
add_library(vtk INTERFACE IMPORTED GLOBAL)
add_dependencies(vtk vtklib)
ExternalProject_add(
ocv
GIT_REPOSITORY https://github.com/opencv/opencv
GIT_TAG 3.4.6
GIT_PROGRESS TRUE
UPDATE_COMMAND ""
CMAKE_ARGS
-DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}
-DWITH_VTK=ON
-Wno-dev
)
# ExternalProject_Get_Property(ocv install_dir)
# include_directories(${install_dir}/src/ocv/include)
include_directories(${CMAKE_INSTALL_PREFIX}/include)
set(ocv_libdir ${CMAKE_INSTALL_PREFIX}/${CMAKE_VS_PLATFORM_NAME}/vc15)
set(OCV_VERSION 346)
add_dependencies(ocv vtklib)
add_library(opencv_core SHARED IMPORTED)
set_target_properties(opencv_core PROPERTIES
IMPORTED_IMPLIB "${ocv_libdir}/lib/opencv_core${OCV_VERSION}.lib"
IMPORTED_LOCATION "${ocv_libdir}/bin/opencv_core${OCV_VERSION}.dll"
)
add_library(opencv_viz SHARED IMPORTED)
set_target_properties(opencv_viz PROPERTIES
IMPORTED_IMPLIB "${ocv_libdir}/lib/opencv_viz${OCV_VERSION}.lib"
IMPORTED_LOCATION "${ocv_libdir}/bin/opencv_viz${OCV_VERSION}.dll"
)
the main CMakeLists.txt looks like this:
cmake_minimum_required(VERSION 3.14)
project(cmaketest VERSION 0.1 DESCRIPTION "" LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_Flags "${CMAKE_CXX_FLAGS} -std=c++17")
# include_directories(${CMAKE_INSTALL_PREFIX}/include)
add_subdirectory(deps)
add_executable(${PROJECT_NAME} main.cpp)
target_link_libraries(${PROJECT_NAME} opencv_core opencv_viz)
install(
TARGETS ${PROJECT_NAME}
EXPORT "${PROJECT_NAME}-targets"
LIBRARY DESTINATION lib/
ARCHIVE DESTINATION lib/${CMAKE_PROJECT_NAME}
RUNTIME DESTINATION bin
PUBLIC_HEADER DESTINATION include/${CMAKE_PROJECT_NAME}/${PROJECT_NAME}
)
the main.cpp for completeness:
#include <opencv2/viz.hpp>
int main(){}
but it seems that the include_directories and add_library calls inside deps/CMakeLists.txt do not work on the correct scope as i am getting the following error messages:
error C1083: File (Include) can not be opened: "opencv2/viz.hpp"
if i uncomment the include_directories inside the main CMakeLists.txt then i get a linker error (this is not what i want, included directories should be specified inside deps/CMakeLists.txt):
LNK1181: opencv_core.lib can not be opened
If i just copy the contents of deps/CMakeLists.txt in the main CMakeLists.txt in place of the add_subdirectory call everything works fine.
So, how do i get the include directories and the created targets from the subdirectory in my main CMakeLists?
edit:
call to cmake configure:
cmake.exe -B build -S . -G "Visual Studio 17 2022" -A x64 -T v141 -DCMAKE_INSTALL_PREFIX=D:/test
call to cmake build:
cmake.exe --build build --config Release --target install
Unlike to normal targets, which are global, an IMPORTED target by default is local to the directory where it is created.
For extend visibility of the IMPORTED target, use GLOBAL keyword:
add_library(opencv_core SHARED IMPORTED GLOBAL)
This is written in the documentation for add_library(IMPORTED):
The target name has scope in the directory in which it is created and below, but the GLOBAL option extends visibility.
cmake has couple steps:
configuration
generation (depends on configuration)
build (depends on generation)
test (depends on build)
install (depends on build)
Now problem is that your build step depends on result of install step. This happens here:
set(ocv_libdir ${CMAKE_INSTALL_PREFIX}/${CMAKE_VS_PLATFORM_NAME}/vc15)
and when this variable is used.
This is causing that to be able to complete build step you need success in install step. And cmake will do install step after successful build. So you have dependency cycle.
Instead importing opencv as shared library:
add_library(opencv_viz SHARED IMPORTED)
Link your target with targets created by imported project of opnecv.
I am currently working on a project that has multiple libraries and multiple executables. Some of the executables will link some of the libraries statically and others will be linked dynamically. My question is how to go about having the option to link a library statically or dynamically using find_package. I noticed boost has the option to set Boost_USE_STATIC_LIBS before calling find_package but I am not quite sure how Boost goes about using this. Does boost build both shared/static and then Boost_USE_STATIC_LIBS just picks the target? Would I strictly need to use MODULE mode or can I use CONFIG mode and what would be the benefit/costs of using either mode for this kind of behaviour?
My current approach uses config mode as all a library needs to do is just call rn_lib(<target_name>) and everything is set up for them. I am guessing the logic to pick the static vs shared target is done in the config/find file for the library.
Desired Behaviour
set(<lib_name>_USE_STATIC_LIBS TRUE)
find_package(<lib_name> REQUIRED)
Current CMakeLists.txt for libraries
function(rn_lib)
cmake_parse_arguments(RN_LIB
""
"NAME"
"SRCS;HEADERS"
${ARGN}
)
if (RN_LIB_NAME)
set(target_name ${RN_LIB_NAME})
else()
set(target_name ${PROJECT_NAME})
endif()
set(static_target_option ${target_name}_STATIC)
option(${static_target_option} "Force build as static library" OFF)
set(_config_file ${target_name}_config.h)
configure_file("cmake/${_config_file}.in" ${CMAKE_CURRENT_BINARY_DIR}/${_config_file})
if (${PROJECT_VERSION})
set(project_version ${PROJECT_VERSION})
else()
set(project_version 1.0)
endif()
if (static_target_option)
message("Build Static ${target_name}")
add_library(${target_name} STATIC
${RN_LIB_SRCS}
${RN_LIB_HEADERS}
)
else()
message("Build Shared ${target_name}")
# This could still produce a static library
add_library(${target_name}
${RN_LIB_SRCS}
${RN_LIB_HEADERS}
)
endif()
# setup lib variables
set(include_install_dir include)
set(include_install_abs ${RN_INSTALL_PATH}/${include_install_dir})
set(config_install_dir lib/cmake/${target_name})
set(generated_dir ${CMAKE_CURRENT_BINARY_DIR}/generated)
set(version_config ${generated_dir}/${target_name}ConfigVersion.cmake)
set(project_config ${generated_dir}/${target_name}Config.cmake)
set(package_namespace RustyNail::)
set(target_export_name ${target_name}Targets)
install(
FILES ${RN_LIB_HEADERS}
DESTINATION ${include_install_dir}/${base_name}
)
target_include_directories(
${target_name}
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<INSTALL_INTERFACE:${include_install_dir}>
)
write_basic_package_version_file(
${version_config}
VERSION ${project_version}
COMPATIBILITY AnyNewerVersion
)
configure_package_config_file(
${RN_CMAKE_PATH}/Config.cmake.in
${project_config}
INSTALL_DESTINATION ${config_install_dir}
)
install(
TARGETS ${target_name}
EXPORT ${target_export_name}
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
RUNTIME DESTINATION bin
INCLUDES DESTINATION ${include_install_dir}
)
install(
FILES ${project_config} ${version_config}
DESTINATION ${config_install_dir}
)
install(
EXPORT ${target_export_name}
NAMESPACE ${package_namespace}
DESTINATION ${config_install_dir}
)
endfunction()
Project Tree
- < root>
- output dir
- lib
- bin
- build
- src
- lib
- lib1
- lib2
- apps
- app1
- app2
I have been working on a project that uses cmake as the build system and working in QtCreator just fine. There are sub-projects (some Qt related and others just plain c++) and up until now all of them were able to find header files and hence provide auto-complete functionality.
At some point, I added a Qt project and noticed that my headers for Qt proejcts were not being found by the editor. The really odd thing is they compile and run just fine via QtCreator 'Build->Build All'. It is almost like QtCreator just can't find them for auto-complete.
I looked around and users had problems in earlier versions of QtCreator finding Qt classes, but did not seem to have a problem finding their defined header files.
I put together a simplified "project" and added two fresh Qt Widget Application projects with the main window being a QDialog instead of QMainWindow. I added the following CMakeLists.txt file to each project:
My Standard CMake File For Qt
cmake_minimum_required(VERSION 3.0.2)
project("FooProj")
set(EXECUTABLE_NAME "Foo")
# Find Qt packages.
find_package(Qt5Core)
find_package(Qt5Widgets)
find_package(Qt5Gui)
set(CMAKE_AUTOMOC ON)
set(SOURCES
"src/main.cpp"
"src/Dialog.cpp"
)
set(HEADERS
"includes/Dialog.h"
)
set(UI_FORMS
"forms/Dialog.ui"
)
set(RESOURCES_FILES
"resources/resources.qrc"
)
# Convert Qt UI and resource files to C/C++ files.
qt5_wrap_ui(UI_HEADERS ${UI_FORMS})
qt5_add_resources(RESOURCES ${RESOURCES_FILES})
# Define the executable to be built.
add_executable(${EXECUTABLE_NAME}
${SOURCES}
${HEADERS}
${UI_HEADERS}
${RESOURCES}
)
# Include paths for this project.
target_include_directories(${EXECUTABLE_NAME} PRIVATE
"${CMAKE_CURRENT_SOURCE_DIR}/includes"
"${CMAKE_CURRENT_BINARY_DIR}"
)
# Link to appropriate libraries.
target_link_libraries(${EXECUTABLE_NAME}
Qt5::Core
Qt5::Widgets
Qt5::Gui
)
# Set distribution location and project structure.
set(DIST_DIR "${CMAKE_BINARY_DIR}/dist/${EXECUTABLE_NAME}")
set_property(TARGET ${EXECUTABLE_NAME} PROPERTY FOLDER "Guis")
# Setup distribution environment and copy final executable.
add_custom_command(TARGET ${EXECUTABLE_NAME}
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E make_directory ${DIST_DIR}
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:${EXECUTABLE_NAME}> ${DIST_DIR}
)
# OS specific deployment setup for sytems without Qt installed.
if(WIN32)
add_custom_command(TARGET ${EXECUTABLE_NAME}
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/QtDeploymentFiles/run.bat" ${DIST_DIR}/${EXECUTABLE_NAME}.bat
COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/QtDeploymentFiles/qt.conf" ${DIST_DIR}
)
elseif(UNIX AND NOT APPLE)
add_custom_command(TARGET ${EXECUTABLE_NAME}
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/QtDeploymentFiles/run.sh" ${DIST_DIR}/${EXECUTABLE_NAME}.sh
)
endif()
Along with this top level CMakeLists.txt:
Top Level CMakeLists.txt
cmake_minimum_required(VERSION 3.0.2)
project("Test")
add_subdirectory("FooProj")
add_subdirectory("BarProj")
Everything makes, compiles, and runs just fine. Auto-complete also works.
I add a Qt library project I need and everything still works fine even when I use the library files. Here is the cmake file for my library:
Qt Library CMakeLists.txt
cmake_minimum_required(VERSION 3.0.2)
project("QtLib")
set(LIB_NAME "QtLib")
# Find Qt packages.
find_package(Qt5Core)
find_package(Qt5Widgets)
set(CMAKE_AUTOMOC ON)
# Set source files to be built.
set(SOURCES
"src/LibFile1.cpp"
"src/LibFile2.cpp"
.
.
.
)
set(HEADERS
"includes/LibFile1Header.h"
"includes/LibFile2Header.h"
"includes/OtherHeaders.h"
.
.
.
)
add_library(${LIB_NAME} ${SOURCES} ${HEADERS})
set_property(TARGET ${LIB_NAME} PROPERTY FOLDER "Libs")
target_include_directories(${LIB_NAME} PRIVATE
"${Qt5Core_INCLUDE_DIRS}"
"${Qt5Widgets_INCLUDE_DIRS}"
"${CMAKE_CURRENT_BINARY_DIR}"
)
target_include_directories(${LIB_NAME} PUBLIC
"${CMAKE_CURRENT_SOURCE_DIR}/includes"
)
target_link_libraries(${LIB_NAME}
Qt5::Core
Qt5::Widgets
)
Lastly I add one of my real projects (one of the ones that does not auto-complete) The structure is as follows:
-forms
-MainForm.ui
-resources
-resources.qrc
-resource files and dirs
-src
-main.cpp
-MainWindow.cpp
-includes
-MainWindow.h
The CMake file is exactly the same as the ones above. Everything makes, compiles, and runs just fine, but auto-complete stops working. I also noticed that ui_MainWindow.h (the one being auto-generated in my project binary directory) is not found.
The really odd thing is, if I just the exact same files with no changes and just open it as a stand alone project, auto-complete works.
Is there something off about my cmake files or is this a Qt related issue? The same thing happens in VS2013 which makes me think it is not QtCreator related, but I am not sure.
After reading around a little more, it seemed like this might be a QtCreator issue (although I don't know why I had problems in VS2013 when I first tested it). I ended up upgrading my QtCreator to 3.6 and my auto-complete problem went away.
I have a large, modular CMake project.
Some modules are static libraries, some are executables that may or may not use some of these libraries. I already have a system of requirement/dependency checking in place that would stop cmake and tell the user if he's trying to build an executable but not the library that it requires.
The project compiles fine as is. I would like to split this into subprojects, i.e. set project(${module_name}) for each of the modules' CMakeLists.txt. Unfortunately, as soon as I insert this line into the apppropriate macro, I immediately get linker errors, i.e. the executables can no longer see the symbols defined in the static libraries.
The c++ command (I happen to be using gcc 4.8) that is invoked on the executables is unchanged, so something else must be different. How can I fix this and retain the subproject structure?
EDIT: per #Gerald's comment, additional information.
Project folder structure:
root
|
|-bin
|-lib
|-cmake(various CMake scripts, added to module path)
|-third_party
|-...
|-CMakeLists.txt
|-modules(top-level module directory, expanded)
|
|-CMakeLists.txt
|-exec_module_a
|-exec_module_b
|-... (other exec modules)
|-lib_module_a
|-lib_module_b
|- ... (other lib modules)
|-lib_module_N (expanded)
|
|-CMakeLists.txt
|-include/root/module_N (various include files)
|-src (various source files)
|-tests
Structure of a typical leaf-level CMakeLists.txt (same but one arg. to root_add_subproject for both lib and exec modules):
include(RootUtils)
set(module_name ${EXEC_MODULE_A})
#---------------------------CHECK REQUIREMENTS---------------------------------#
root_check_module_requirements(module_name
BUILD_${LIB_MODULE_A}
BUILD_${LIB_MODULE_G}
#...
WITH_QT
WITH_THIRD_PARTY_BLAH1
WITH_THIRD_PARTY_BLAH2
#...
)
#---------------------------ADD SOURCES AND TARGET-----------------------------#
root_add_subproject(${module_name} executable qt_on)
#---------------------------ADD INCLUDES---------------------------------------#
target_include_directories(${TARGET_NAME} PUBLIC
#third-party includes
${THIRD_PARTY_BLAH1_INCLUDE_DIRS}
${THIRD_PARTY_BLAH1_INCLUDE_DIRS}
#...
#module includes
"${MODULES_DIR}/${LIB_MODULE_A}/include"
"${MODULES_DIR}/${LIB_MODULE_B}/include"
#...
)
#---------------------------LINK LIBRARIES-------------------------------------#
target_link_libraries(${TARGET_NAME} PUBLIC
#third-party libraries
${QT5_TARGETS}
${THIRD_PARTY_BLAH1_LIBRARIES}
${THIRD_PARTY_BLAH2_LIBRARIES}
#...
#module libraries
${LIB_MODULE_A}
${LIB_MODULE_B}
#...
)
if(UNIX)
#... link third-party dependencies conditional on platform
endif()
#---------------------------ADD TESTS------------------------------------------#
#SET(BUILD_TESTS FALSE)#comment out to build the local unit tests
root_add_tests(${module_name})
#==============================================================================#
The relevant script in RootUtils.cmake looks like this:
macro(augmentarium_add_subproject module_name proj_type qt_on)
if(${qt_on} STREQUAL "qt_on" OR ${qt_on} STREQUAL "YES" OR ${qt_on} STREQUAL "TRUE")
set(QT_ON TRUE)
else()
set(QT_ON FALSE)
endif()
#---------------------------DEFINE SUBPROJECT----------------------------------#
#TODO: fix problems with macro (figure out how to set up library as a subproject w/o destroying linking capability)
#project(${module_name}) # <------- THIS is the line that causes linker errors
set(TARGET_NAME ${module_name})
string(TOUPPER "${TARGET_NAME}" TARGET_NAME_UPPER)
if(QT_ON)
set(CMAKE_AUTOMOC ON)
endif()
#---------------------------DEFINE SOURCE FILES--------------------------------#
include_directories(include)
SET(${TARGET_NAME_UPPER}_TOP_INCLUDE_DIR include/${PROJECT_NAME}/${TARGET_NAME})
file(GLOB ${TARGET_NAME_UPPER}_CMAKELISTS ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt)
file(GLOB ${TARGET_NAME_UPPER}_SOURCES src/*.cpp)
file(GLOB ${TARGET_NAME_UPPER}_HEADERS src/*.h src/*.h.in src/*.hpp src/*.tpp
${${TARGET_NAME_UPPER}_TOP_INCLUDE_DIR}/*.h
${${TARGET_NAME_UPPER}_TOP_INCLUDE_DIR}/*.h.in
${${TARGET_NAME_UPPER}_TOP_INCLUDE_DIR}/*.hpp
${${TARGET_NAME_UPPER}_TOP_INCLUDE_DIR}/*.tpp)
file(GLOB ${TARGET_NAME_UPPER}_TEST_SOURCES tests/*.cpp)
if(QT_ON)
file(GLOB_RECURSE MOC_${TARGET_NAME_UPPER}_SOURCES moc_*.cpp *_automoc.cpp qrc_*.cpp)
#remove generated moc files
foreach(FILE_NAME ${MOC_${TARGET_NAME_UPPER}_SOURCES})
list(REMOVE_ITEM ${TARGET_NAME_UPPER}_SOURCES ${FILE_NAME})
endforeach()
endif(QT_ON)
if(QT_ON)
#---------------------------ADD UI FILES---------------------------------------#
file(GLOB ${TARGET_NAME_UPPER}_UI src/*.ui)
if(BUILD_${TARGET_NAME})
#this macro doesn't get defined unless QtWidgets is found
qt5_wrap_ui(${TARGET_NAME_UPPER}_UI_HEADERS ${${TARGET_NAME_UPPER}_UI})
endif()
#---------------------------ADD RESOUCE FILES----------------------------------#
file(GLOB ${TARGET_NAME_UPPER}_RESOURCE_FILES *.qrc)
if(BUILD_${TARGET_NAME})
#this macro doesn't get defined unless QtWidgets is found
qt5_add_resources(${TARGET_NAME_UPPER}_GENERATED_RESOURCES ${${TARGET_NAME_UPPER}_RESOURCE_FILES})
endif()
endif(QT_ON)
#..........................organize source/header files........................#
source_group("Source Files" FILES ${${TARGET_NAME_UPPER}_SOURCES})
source_group("Header Files" FILES ${${TARGET_NAME_UPPER}_HEADERS})
if(QT_ON)
source_group("Resource Files" FILES ${${TARGET_NAME_UPPER}_RESOURCE_FILES})
source_group("UI Files" FILES ${${TARGET_NAME_UPPER}_UI})
source_group("Generated Files" FILES ${${TARGET_NAME_UPPER}_GENERATED_RESOURCES} ${${TARGET_NAME_UPPER}_UI_HEADERS})
endif()
#---------------------------ADD TARGET-----------------------------------------#
set(ALL_${TARGET_NAME_UPPER}_FILES
${${TARGET_NAME_UPPER}_CMAKELISTS}
${${TARGET_NAME_UPPER}_SOURCES}
${${TARGET_NAME_UPPER}_HEADERS}
${${TARGET_NAME_UPPER}_RESOURCE_FILES}
${${TARGET_NAME_UPPER}_UI}
${${TARGET_NAME_UPPER}_GENERATED_RESOURCES}
)
if(${proj_type} STREQUAL "executable")
add_executable(${TARGET_NAME} ${ALL_${TARGET_NAME_UPPER}_FILES})
elseif(${proj_type} STREQUAL "library")
add_library(${TARGET_NAME} STATIC ${ALL_${TARGET_NAME_UPPER}_FILES})
else()
add_custom_target(${TARGET_NAME} ${ALL_${TARGET_NAME_UPPER}_FILES})
endif()
endmacro()
If that's still not enough, here's how the subprojects are included in the module-level CMakeLists.txt:
foreach (MODULE_NAME ${MODULES})
add_subdirectory (${MODULE_NAME})
endforeach()
CMake version used: 3.1.3
How do you manage dependencies between libs with CMake? This should be done using TARGET_LINK_LIBRARIES(myexe mylib1 mylib2)