Specifying Build Options for External CMake Dependency - build

I am in the process of writing my project's CMakeLists.txt file. My project relies on an external dependency, GLFW, luckily for me GLFW also uses CMake for its build system. I am using find_package() and git submodules to handle dependency management, currently this is how my CMakeLists.txt file looks like:
# CMake version
cmake_minimum_required(VERSION 3.0)
# project name
project(CHIP-8)
# dependency management
find_package(OpenGL REQUIRED)
find_package(glfw)
if(NOT glfw)
message("Unable to locate glfw.")
message("Cloning the repository.")
execute_process(
COMMAND
git submodule update --init -- libs
WORKING_DIRECTORY
${CMAKE_CURRENT_SOURCE_DIR}
)
message("Building glfw.")
add_subdirectory(libs/glfw)
endif()
From my limited understanding of CMake the command add_subdirectory(libs/glfw) runs CMake on the recently cloned glfw sub-module. The problem is a lot of unnecessary features are part of the default build for GLFW such as examples, unit tests, and documentation.
The documentation for compiling GLFW lists the CMake options for disabling these features GLFW_BUILD_EXAMPLES, GLFW_BUILD_TESTS, and GLFW_BUILD_DOCS.
I have two questions, the first being how can I specify these options, and the second is the argument I pass for find_package accurate (I do have GLFW installed on my system yet every time I build it still attempts to clone and build the repository).

Found my answer in a similar question.
All I had to do was add:
option(GLFW_BUILD_EXAMPLES OFF)
option(GLFW_BUILD_TESTS OFF)
option(GLFW_BUILD_DOCS OFF)
right before add_subdirectory(libs/glfw).

Related

AUTOMOC set to true makes fail cmake build

I'm at the very first day of Qt + Cmake and Conan, trying to make things work. I'm not using qmake because I'll integrate everything into a bigger project using cmake.
By following QT's tutorial, I figured out that I need to compile QT macros, and for that there's a useful AUTOMOC CMake property, as suggested here.
The point is that it's making me fail cmake builds.
My conanfile.txt:
[requires]
qt/5.15.2
[generators]
cmake
My CMakeLists.txt:
cmake_minimum_required(VERSION 3.20)
project(qttest)
set(CMAKE_CXX_STANDARD 20)
set_target_properties(${PROJECT_NAME} PROPERTIES AUTOMOC TRUE)
set (PROJECT_SOURCE_DIR ${PROJECT_SOURCE_DIR}/src)
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup()
add_executable(${PROJECT_NAME} src/main.cpp)
target_link_libraries(${PROJECT_NAME} ${CONAN_LIBS})
with the following output:
CMake Warning (dev) in CMakeLists.txt:
AUTOGEN: No valid Qt version found for target qttest. AUTOMOC disabled.
Consider adding:
find_package(Qt<QTVERSION> COMPONENTS Core)
to your CMakeLists.txt file.
This warning is for project developers. Use -Wno-dev to suppress it.
ouch, but adding the find doesn't make things better:
CMake Warning at CMakeLists.txt:6 (find_package):
By not providing "FindQt5.cmake" in CMAKE_MODULE_PATH this project has
asked CMake to find a package configuration file provided by "Qt5", but
CMake did not find one.
Could not find a package configuration file provided by "Qt5" with any of
the following names:
Qt5Config.cmake
qt5-config.cmake
Actually the project compiles, Qt is there in its conan dir:
matteo#MacBook-Pro-de-matteo 96a68a791abfc7a246f2bc28aa2f6fc210be0f9f % cd ~/.conan/data/qt
matteo#MacBook-Pro-de-matteo qt % ls
5.15.2 6.2.2
matteo#MacBook-Pro-de-matteo qt %
how could I enable it, or make things easier to compile it along with cmake?
You need to tell CMake, where to find Qt.
So, as CMake suggests by itself:
find_package(Qt5 COMPONENTS Core)
for the most basic stuff, you might want to add some of the other components later.
Depending on the system you are working on and your Qt installation, you need to tell CMake where to search for the package configuration files (second error message). CMake has some default directories, where it looks for these files, but obviously, there is none. On Linux, this can be solved by installing Qt with a package manager (this will install the CMake config files to one of the Qt default locations). If you are on Windows or if you installed Qt to a different location, this can be solved by providing the path with the PREFIX_PATH-variable.
cmake -B $BUILD_DIR -S $SOURCE_DIR -DCMAKE_PREFIX_PATH=$QT_INSTALL_PATH/5.15.2/$ARCHITECTURE $OTHER_OPTIONS
(You can have different versions installed in the same installation path, that's why Qt adds an other folder with the version number. And you can have different compilers/architectures. On Windows for example, you might have a mingw73_32 and a msvc2017 folder to choose.)
As already mentioned in the comments, a project is no CMake target. CMake targets are either libraries (add_library), executables (add_executable) or custom targets (add_custom_target); the project is not. If you want to set the AUTOMOC property target wise, that's ok and even suggested by CMake, but you can also set it globally by using:
set(CMAKE_AUTOMOC ON)

How to include third party tools with cmake?

I have been working on a CPP project but was using configuration on visual studio IDE. Now, I wanted to use a build system generator CMake. It is a little difficult to getting started with this.
I am trying to add cppunit third-party tool for my testing. For that, I have added include and lib file in a folder third_party. But not sure how to include it in the CMakeLists.txt.
Please find CMakeList.txt
# CMake version setting
cmake_minimum_required(VERSION 3.8)
if(${CMAKE_VERSION} VERSION_LESS 3.19)
cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
else()
cmake_policy(VERSION 3.19)
endif()
# Set project name and version
project(myproject
VERSION 1.0
DESCRIPTION "Setup cmake build system"
LANGUAGES CXX
)
# Third party dependencies
set(THIRD_PARTY_DIR "${PROJECT_SOURCE_DIR}/third_party")
# CPP unit
set(CPP_UNIT_LIB_NAME "cppunit")
set(CPP_UNIT_VERSION "1.13.2")
set(CPP_UNIT_DIR "${THIRD_PARTY_DIR}/${CPP_UNIT_LIB_NAME}/${CPP_UNIT_VERSION}")
# NOT sure what to do here
# add_subdirectory(${CPP_UNIT_DIR})
# target_include_directories(${PROJECT_NAME} PRIVATE "${CPP_UNIT_DIR}/include/cppunit")
# target_link_libraries(${PROJECT_NAME} ${CPP_UNIT_LIB_NAME} ${CPP_UNIT_LIBRARIES})
# target_compile_definitions(${PROJECT_NAME} PRIVATE "CPP_UNIT_INCLUDE_NONE")
add_subdirectory(src)
Please find the snap-shot of the folder structure
add_subdirectory(${CPP_UNIT_DIR}) will look in the directory specificied for a CMakeLists.txt and since CppUnit has a CMakeLists.txt file (https://github.com/Ultimaker/CppUnit/blob/master/CMakeLists.txt) it will build the library specified add_library(cppunit STATIC ${Sources}) which is cppunit.
And then when you specify your target to build, you can link in cppunit using target_link_libraries(your_target cppunit). But you need to create your target such as by using add_executable(one two.cpp three.h) which creates the target one.
https://cliutils.gitlab.io/modern-cmake/ is a good introductory resource for CMake. And there are different ways to bring in external projects such as through a git submodule.
If you have a CMakeLists.txt file in the src subdirectory, where you create a target you can link in cppunit.
As for the comment about include_directories, it is generally considered good practice to use target_include_directories instead, see What is the difference between include_directories and target_include_directories in CMake? and the above linked resource for more.

How to find (configure) Qt for cmake project of iOS?

I install Qt via online installer on my macOS (Qt for iOS and macOS).
And qmake project works just fine, now I need compile with cmake Qt project:
cmake_minimum_required(VERSION 3.5)
project(demo LANGUAGES CXX)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(Qt5 COMPONENTS Core Quick REQUIRED)
And I can not find Qt.
Direct build configuration:
cmake .. -GXcode -DQt5_DIR=/Users/user/Qt/5.14.1/clang_64/lib/cmake/Qt5
...
-- Configuring done
-- Generating done
-- Build files have been written to:
Cross-compiling for iOS:
cmake .. -GXcode -DCMAKE_SYSTEM_NAME=iOS -DQt5_DIR=/Users/user/Qt/5.14.1/ios/lib/cmake/Qt5
...
CMake Error at /Users/user/Qt/5.14.1/ios/lib/cmake/Qt5/Qt5Config.cmake:28 (find_package):
Could not find a package configuration file provided by "Qt5Core" with any
of the following names:
Qt5CoreConfig.cmake
qt5core-config.cmake
Add the installation prefix of "Qt5Core" to CMAKE_PREFIX_PATH or set
"Qt5Core_DIR" to a directory containing one of the above files. If
"Qt5Core" provides a separate development package or SDK, be sure it has
been installed.
Obviously Qt5CoreConfig.cmake is just fine and it is in relatively the same place as for "direct" compilation, but for some reason cmake can not find it
$ find /Users/user/Qt/5.14.1/ios/lib/cmake/ -name Qt5CoreConfig.cmake
/Users/user/Qt/5.14.1/ios/lib/cmake//Qt5Core/Qt5CoreConfig.cmake
How can I fix this?
When building for iOS CMAKE_SYSROOT is set to iPhoneOS.sdk path.
find_package:
The CMAKE_SYSROOT variable can also be used to specify exactly one directory to use as a prefix. Setting CMAKE_SYSROOT also has other effects. See the documentation for that variable for more.
These variables are especially useful when cross-compiling to point to the root directory of the target environment and CMake will search there too. By default at first the directories listed in CMAKE_FIND_ROOT_PATH are searched, then the CMAKE_SYSROOT directory is searched, and then the non-rooted directories will be searched.
So, adding the option -DCMAKE_FIND_ROOT_PATH=/Users/user/Qt/5.14.1/ios will help.

How can I add Vulkan to a cross platform CMake project?

In order to make a CMake project as simple and as portable as it can get I have consider to add the "whole" repositories of the libraries I need to the project.
The project structure is as follows:
MyProject/
└──CMakeLists.txt
└──src/
└──MyProject/
└── *.h & *.cpp
└── CMakeLists.txt
└──ThirdParty/
└──Vulkan-Hpp/
└──(Vulkan Files)
└──glfw/
└──(glfw Files)
└──SFML/
└──(SFML Files)
All the third party directories are the git submodules of the following repositories:
https://github.com/KhronosGroup/Vulkan-Hpp
https://github.com/SFML/SFML
https://github.com/glfw/glfw
Summarizing everything up, I'm having trouble integrating the vulkan and sfml libraries to the project.
MyProject/CMakeLists.txt is as follows:
cmake_minimum_required (VERSION 3.8 FATAL_ERROR)
project ("MyProject")
set (MyProject_VERSION_MAJOR 0)
set (MyProject_VERSION_MINOR 2)
set (MyProject_VERSION_PATCH 1)
set (CMAKE_CXX_STANDARD 17)
# Include sub-projects.
add_subdirectory ("src/MyProject")
add_subdirectory ("ThirdParty/glfw")
add_subdirectory ("ThirdParty/SFML")
add_subdirectory ("ThirdParty/Vulkan-Hpp")
MyProject/src/MyProject/CMakeLists.txt:
cmake_minimum_required (VERSION 3.8 FATAL_ERROR)
project ("MyProject")
find_package(Vulkan REQUIRED FATAL_ERROR) # error
find_package(SFML REQUIRED network audio) # error
find_package(glfw REQUIRED FATAL_ERROR) # error
# Add source to this project's executable.
add_executable (MyProject "MyProject.cpp")
target_include_directories (MyProject
PUBLIC ${GLFW_INCLUDE_DIRS}
PUBLIC ${SFML_INCLUDE_DIR}
PUBLIC ${VULKAN_INCLUDE_DIRS}
)
target_link_libraries (MyProject glfw)
target_link_libraries (MyProject ${VULKAN_LIB_LIST})
target_link_libraries (MyProject ${SFML_LIBRARIES})
How can I tweak CMake in order to use the third party libraries at my main project?
Is the project structure incorrect?
If your find_package(Vulkan REQUIRED FATAL_ERROR) line is failing, you need to make sure the Vulkan SDK is properly installed, i.e. that you have a VULKAN_SDK environment variable that points to the correct location.
Additionally, do not embed the KhronosGroup/Vulkan-Hpp repository. This repository is for building the Vulkan C++ bindings, but shouldn't be used directly. Instead you should be using the vulkan.hpp header that is bundled with your installation of the Vulkan SDK. Otherwise when people try to build your project and have a different version of the Vulkan SDK installed than is referred to by your embedded KhronosGroup/Vulkan-Hpp
More generally, you are using find_package and then later you're using add_subdirectory to try to incorporate these external projects. That's not how it works. find_package will look for a pre-existing binary of the package, while add_subdirectory isn't designed to just swallow entire existing external CMake projects.
If you want to have your project build these others from source you should investigate the use of CMake's external project functionality. However, you'll probably find this to be more of a burden than it's worth. Alternatively, install vcpkg for your target platform, and use vcpkg to build and install glfw and sfml, then tell CMake to use the vcpkg dependencies (see the vcpkg docs on how to pass the CMAKE_TOOLCHAIN_FILE to your cmake configure line.

C++ How to run programs in Clion when you need to include OpenGL libraries?

Hello I need to work with OpenGL and want to create my project in Clion. But Clion cannot compile and run my projects because of the libraries I need to include. I can create my own makefile and run the program in terminal, but I want to do it in the IDE. How can I make this happen?
First make sure you installed all libraries correctly using the compiler you configured in clion/cmake. Assuminf you have a fresh CMakeLists.txt like
cmake_minimum_required(VERSION 3.3.2)
project(MyGL CPP)
add_executable(demo-run main.cpp)
For linking your libraries you need two things. First tell the compiler where to find the include files and second which libraries to link. You could just hard code you local installation like
target_link_libraries(demo-run path/to/glfw.lib path/to/opengl.lib path/to/jpeg.lib ...)
target_include_directories(demo-run PRIVATE path/to/glfw/include path/to/opengl/include path/to/jpeg/include ...)
however this is not very portable and if you want to work with another compiler or on another machine your project file will fail. Instead you can use the package system of cmake
find_package(PkgConfig REQUIRED)
pkg_search_module(GLFW REQUIRED glfw3)
find_package(JPEG REQUIRED)
find_package(GLEW REQUIRED)
find_package (OpenGL REQUIRED)
find_package (GLM REQUIRED)
target_link_libraries(demo-run ${GLFW_LIBRARIES} ${GLEW_LIBRARIES} ${JPEG_LIBRARIES} ${OPENGL_LIBRARIES})
target_include_directories(demo-run PRIVATE ${GLFW_INCLUDE_DIRS} ${GLEW_INCLUDE_DIR} ${JPEG_INCLUDE_DIR} ${OPENGL_INCLUDE_DIR} ${GLM_INCLUDE_DIR})
The glfw part is a bit tricky and works only on linux i guess see http://www.glfw.org/docs/3.0/build.html.
This code is not tested at all and you may need to specify some enviroment variables so cmake can find the packages or provide additional find scripts like https://github.com/lighttransport/nanogi/blob/master/cmake/FindGLM.cmake.
I would recommend to use the CMake build tool which does the work generating Makefiles for you and is also directly supported by clion. When you open the directory containing a CMakeLists.txt (CMake Project File) with clion, it should be automatically be loaded and compiled (if not just hit build)
A very simple example CMake project would look like this
cmake_minimum_required (VERSION 2.8.9)
project (OpenGl-Stuff)
include_directories(src)
add_executable(your-binary src/your-code.c src/your-code.h)
target_link_libraries(your-binary opengl)
# target_link_libraries will search for libopengl on standard system paths,
# maybe the library is not called libopengl, then you have to adjust the name above
this cmake project will generate the binary for you and link it against opengl