CMake: download precompiled binaries - c++

I am trying to download precompiled binaries from a webserver within cmake. So is there something similar like ExternalProject_Add but without the actual build step?
The downloaded file is a tar.gz and would need to be extracted. It contains /bin /include and /lib and especially also /lib/cmake which should be found by the calling CMake project.
If I ExternalProject_Add results in an error that the build folder does not contain a CMakeLists.txt file.
The minium example is something like
cmake_minimum_required(VERSION 3.0)
project(Foo)
if (TARGET Bar)
message(STATUS "Foo and Bar are unified - how beautiful is that")
else()
include (ExternalProject)
ExternalProject_Add ( Bar # <------ This doesn't work
URL "http://THE-INTERNET"
)
endif()
find_package(Bar REQUIRED)
add_executable(${PROJECT_NAME} main.cpp)
target_link_libraries(${PROJECT_NAME} Bar::Bar)
Ok, I figured out two things:
The command CONFIGURE_COMMAND "" can be provided to ExternalProject to not build anything.
The find_package() will never work like this. The ExternalProject is executed during compile time, while the find_package needs to find the target at configure time.
In the meantime I found this: https://cmake.org/cmake/help/latest/module/FetchContent.html - this might help to get targets ready during configure time and not just during compile time. However it is only supported from CMake 3.11 on :(

Related

How to include non Vcpkg on CMakeLists.txt?

So I have a project which depends on opencv, which is installed with vcpkg. The project is build with cmake.
CMakeLists.txt
cmake_minimum_required(VERSION 3.19.1)
project(mylib)
set (CMAKE_CXX_STANDARD 14)
find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})
link_libraries(${OpenCV_LIBS})
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS TRUE)
add_library(mylib SHARED mylib.cpp another_lib.cpp)
That works fine.
Now, instead of vcpkg provided opencv, I want to use opencv from
https://sourceforge.net/projects/opencvlibrary/files/4.4.0/opencv-4.4.0-vc14_vc15.exe/download
After installing it on C:\opencv I see there is opencv\build\OpenCVConfig.cmake, which find_package look for, right?
But how do I make cmake get this one instead of the one from vcpkg?
Use <PackageName>_DIR variable pointing to where the config file is located. It works for any library which comes with a config file.
For you it would look like this:
set(OpenCV_DIR "C:/opencv/build")
Since it is incorrect to add hard-coded paths into persistent scripts, you can choose among different methods of providing this variable to your script:
Console invocation: cmake OpenCV_DIR="C:/opencv/build"
CMake presets (user)
Local config by using some LocalConfig.cmake with the content above (set(...)), which you include in your main script like this: include(LocalConfig.cmake)

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 can I avoid linking directly to library files in cmake?

I'm writing a c project using cmake on a mac. I use homebrew. I installed libpqxx via homebrew. I have the following CMakeLists.txt.
cmake_minimum_required(VERSION 3.11)
project(imagedb)
set(CMAKE_CXX_STANDARD 14)
add_executable(imagedb main.cpp)
target_link_libraries( imagedb /usr/local/lib/libpqxx.dylib)
While this builds I would like to avoid using an absolute path here. How can I do this using cmake given that /usr/local is already in the path prefix?
Usually you should use find_package to find dependencies.
Looking at libpqxx's repo, you can see that they provide a CMake config file.
So in your CMakeLists.txt file you just have to do this:
find_package(libpqxx REQUIRED)
target_link_libraries(imagedb libpqxx::pqxx_shared)
If for some reason libpqxx-config.cmake is not shipped with the homebrew version, you have to write a find file.

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