I am new to Cmake. I have a CMakeLists.txt like below for an app which runs on Windows and Linux.
cmake_minimum_required(VERSION 3.16)
find_package(Qt5 COMPONENTS Qml Quick)
if(UNIX AND NOT APPLE)
find_package(Qt5 COMPONENTS Core Network)
endif()
Question:
I have a find_package call to get Qml and Quick which are two Qt5 components. This is good and required for both Windows and Linux cases. But in the case specific to Linux only, I want find_package to only look for Core and Network without mentioning Qt5. Is it possible?
I tried find_package(Core Network) and find_package(Qt5::Core Qt5::Network). Both didn't work.
Below if else is the only way?
if(WIN32)
find_package(Qt5 COMPONENTS Qml Quick)
else()
find_package(Qt5 COMPONENTS Qml Quick Core Network)
endif()
I don't want to do the above if else and thats my point here. I want to do something like this which looks incremental
find_package(Qt5 COMPONENTS Qml Quick)
if(UNIX AND NOT APPLE)
find_package(Core Network) # But this does not compile
else()
Related
My project is located in this filepath:
C:\Users\zaina\OneDrive\foo_directory\bar_projectname
The libraries and git repositories, which I want to use globally, are located in this file path:
C:\dev\github\foobar
For example This repository is about controlling Tello drone with c++ language, and I cloned this
I used Cmake GUI to configure the build and Visual Studio to build the libraries, but I simply can't include it in my project by invoking:
#include <tello/tello.hpp>
So there must be something that might help.
I tried git submodules and it worked fine, but it only works for a single project and not globally.
So I was wondering that is there a possibility to set a cloned repository as a global library or create one. If it is, then how?
I tried this as my CMakeLists.txt:
project(foo)
# Setup testing
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
enable_testing()
add_executable(foo main.cpp)
target_include_directories(foo PRIVATE ${tello_SOURCE_DIR}/src)
target_link_libraries(tello_test PRIVATE tello)
But that did not work, because my program can't find the tello header files.
Here is my source code structure:
cd my_git_repo/
CMakeLists.txt
src/
main.cpp
mylibrary/
a.hpp
b.hpp
a.cpp
b.cpp
CMakeLists.txt
Root CMakeLists.txt:
cmake_minimum_required(VERSION 3.9)
project(myexe CXX)
add_subdirectory(src/mylibrary)
find_library(mylib NAMES mylibrary.so PATHS "./src/mylibrary/mylibrary.so")
add_executable(myexe src/main.cpp)
target_link_libraries(myexe ${mylib})
mylibrary/CMakeLists.txt is very simple. It builds a shared library and installs them.
Ideally, mylibrary target should be built and installed before myexe is built. But this doesn't happen. mylibrary is built followed by myexe. Installation happens later. Because of this, find_library fails. pkg_check_modules() works for other shared libraries but fails here because of the same reason.
I appreciate your help.
Edit:
This question differs from the duplicate because the answers posted to that question seem to be statically linking the library target_link_libraries(game engine). I want to dynamically link the .so library.
The idea in CMake is to build modules and then link them together.
You haven't shared the CMakeLists.txt for my library, so we cannot tell what it is doing. However, assuming that it is something like:
ADD_LIBRARY(mylibrary
file1.cpp
file2.cpp
)
Since you specified that you want mylibrary to always be linked as shared, you need to tell CMake that as well by either setting BUILD_SHARED_LIBS TO ON or by specifying SHARED in add_library:
ADD_LIBRARY(mylibrary SHARED
file1.cpp
file2.cpp
)
This is your library module. We will keep it simple for now and not worry about packing the library archive and installation here.
Now, back to your main CMakeLists.txt and how to make myexe consume it. Since you have already add_subdirectory(src/mylibrary), CMake knows about mylibrary. So simply link it using the module name. There is no need to find_library as you have already defined the module.
add_executable(myexe src/main.cpp)
target_link_libraries(myexe mylibrary)
This should suffice.
Do note, however, this is a very basic example to explain to you how CMake is designed to work. If you aren't building the library, and it is already installed, you would call find_library. Modern CMake is a bit more sophisticated and uses generator expressions, so be sure to read up on that as you progress to more complex projects.
I use SDL2 in my game. I always was using custom FindSDL2.cmake, because there is no one in standard CMake set. However, some time ago posts about FindSDL2 did appeared. Example: Reddit post.
If your cmake is new enough and it has FindSDL2.cmake file, you can do this:
find_package(SDL2 REQUIRED)
But when I download latest CMake (3.13.2), it doesn't include FindSDL2.cmake.
What happened to it?
FindSDL2 has never appeared in CMake.
Following the reject reason in pull request #149, SDL2 ships with a SDL2Config.cmake, which provides a cmake package.
The documentation for find_package states that find_package(SDL2) will behave as follows:
Look for FindSDL2.cmake, use that if it exists. (module mode)
Otherwise, use the information in SDL2Config.cmake or sdl2-config.cmake. (config mode)
In short, make sure that your SDL2 package has installed the SDL2Config.cmake file and that is on your CMAKE_PREFIX_PATH. The documentation lists the exact paths and prefixes it looks under.
To easily integrate the SDL2 library, I developed cross-platform modern CMake modules for finding and using the SDL2 library as well as other related libraries:
SDL2: example, game example
SDL2_image: example
SDL2_ttf: example
SDL2_mixer: example
SDL2_net
SDL2_gfx: animation example
So the only things that you should do in order to integrate the SDL2 library are:
Clone SDL2 CMake modules inside your project:
git clone https://github.com/aminosbh/sdl2-cmake-modules cmake/sdl2
Add the following lines in your main CMakeLists.txt
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/sdl2)
find_package(SDL2 REQUIRED)
target_link_libraries(${PROJECT_NAME} SDL2::Main)
Note: If CMake didn't find the SDL2 library (in Windows), we can specify the CMake option SDL2_PATH as follows:
cmake .. -DSDL2_PATH="/path/to/sdl2"
For more details, please read the README.md file.
This is a list of SDL2 samples and projects: https://github.com/aminosbh/sdl-samples-and-projects
For the example CMakeLists.txt attached to CMake wiki. I also added below what is the actual make command to create just the component based TGZ. I am confused and not seeing any help in the documents.
CMakeLists.txt
cmake_minimum_required(VERSION 2.6.0 FATAL_ERROR)
project(MyLib)
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
set(CMAKE_INSTALL_PREFIX "/usr" CACHE PATH "Install path prefix prepended on to install directories." FORCE)
endif(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
set(CPACK_PACKAGE_NAME "MyLib")
set(CPACK_PACKAGE_VENDOR "CMake.org")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "MyLib - CPack Component Installation Example")
set(CPACK_PACKAGE_VERSION "1.0.0")
set(CPACK_PACKAGE_VERSION_MAJOR "1")
set(CPACK_PACKAGE_VERSION_MINOR "0")
set(CPACK_PACKAGE_VERSION_PATCH "0")
set(CPACK_PACKAGE_INSTALL_DIRECTORY "CPack Component Example")
add_library(mylib mylib.cpp)
add_executable(mylibapp mylibapp.cpp)
target_link_libraries(mylibapp mylib)
install(TARGETS mylib
ARCHIVE
DESTINATION lib
COMPONENT libraries)
install(TARGETS mylibapp
RUNTIME
DESTINATION bin
COMPONENT applications)
install(FILES mylib.h
DESTINATION include
COMPONENT headers)
set(CPACK_COMPONENTS_ALL applications libraries headers)
set(CPACK_COMPONENT_APPLICATIONS_DISPLAY_NAME "MyLib Application")
set(CPACK_COMPONENT_LIBRARIES_DISPLAY_NAME "Libraries")
set(CPACK_COMPONENT_HEADERS_DISPLAY_NAME "C++ Headers")
set(CPACK_COMPONENT_APPLICATIONS_DESCRIPTION
"An extremely useful application that makes use of MyLib")
set(CPACK_COMPONENT_LIBRARIES_DESCRIPTION
"Static libraries used to build programs with MyLib")
set(CPACK_COMPONENT_HEADERS_DESCRIPTION
"C/C++ header files for use with MyLib")
set(CPACK_GENERATOR "TGZ")
set(CPACK_ARCHIVE_COMPONENT_INSTALL ON)
set(CPACK_INCLUDE_TOPLEVEL_DIRECTORY OFF)
set(CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY OFF)
set(CPACK_SET_DESTDIR ON)
set(CPACK_PACKAGE_CONTACT "jhf")
# This must always be last!
include(CPack)
I have a similar CMakeLists.txt and when I do make package, I end up getting all my binaries and libraries in the TGZ. What should the make package command be if I need just a TGZ with application component from the above CMakeLists.txt?
It is simple.
Just set the CMAKE variable CPACK_COMPONENTS_ALL to the list of components you want to appear in the installation:
SET(CPACK_COMPONENTS_ALL applications) #only pack "applications" component
Take a look at CPackComponent.
I have exactly the same question with you.
I'm a beginner to cmake, and today I've try a whole day on this, just now I noticed a cmake module named CPackComponent which begins appeared in cmake 2.8.5 standard modules.
For now, I haven't made sure whether it is the reason yet. But the variables in the documents listed by you can be found in this module.
cmake 2.8.5 is the earliest version contained CPackComponent in its standard modules.
Have a check at http://www.cmake.org/cmake/help/v2.8.5/cmake.html#module:CPackComponent
And cmake 2.8.8 is the earliest version listed the variables you want. e.g. CPACK_COMPONENTS_ALL
Over here http://www.cmake.org/cmake/help/v2.8.8/cmake.html#module:CPackComponent
I'm sorry I'm a newbie too, could not help you any more.
I have a CMake project with two subprojects, a library and an application using it. The application needs several build configurations (custom values in CMAKE_CONFIGURATION_TYPES). However for the library there is no difference between those configurations. Is it possible to modify the configuration set in subproject and still use it's output in the parent or sibling project?
Hmm, did you tried something like this in library project:
if(CMAKE_BUILD_TYPE STREQUAL "Your_custom_config")
set(CMAKE_BUILD_TYPE "Release")
endif()