When using CMake on unix I dont have any issues. I can use CLion to do a cmake setup, cmake build and cmake install, open a different project and it will find the previously built library when using find_package. On windows this does not seem to be possible. By default it tries to install the build code into strange directories (like C:\Program Files). I have added a CMAKE_INSTALL_PREFIX to both my library CMakeLists.txt and the appliation CMakeLists.txt, however when using find_package(SDL2)CMake still complains there is no config file for CMake and SDL2. When checking the following file exists:
U:\various\cmake-cache\Program Files (x86)\SDL2\cmake\SDL2Config.cmake
The directory U:\various\cmake-cache was used as CMAKE_INSTALL_PREFIX for both SDL2 and my application. Yet it still refuses to compile.
What can I do to make CMake at least somewhat useful on windows? On Unix things work great, but it feels like a huge PITA on Windows so far... It seems like all the concepts dont work there. I would really like to have one central location that is used by every CMake build on my system and everything is installed there and when another project uses a library it is searched there. Is this possible?
Related
So I got into a problem where I needed to use linux for a while instead of windows, and figured linux doesn't have Visual Studio. I then also realized that I made my project Visual Studio only, which I don't want.
So I looked up some CMake tutorials and try'ed creating some examples that could be loaded in both Visual Studio and CodeBlocks. When I got that to work, I went and code a CMake script for my actual program by piecing together what I learned and what I found in tutorials.
See here:
cmake_minimum_required(VERSION 2.8.9)
add_subdirectory(libraries/glfw)
project (OpenGLEngine3D)
include_directories(libraries/glfw/include)
include_directories(libraries/glm)
include_directories(libraries/glad/include)
include_directories(libraries/whereami/src)
include_directories(libraries/stb)
file(GLOB SOURCES "src/*.cpp" "src/*.h" "libraries/whereami/src/whereami.c" "libraries/glad/src/glad.c")
add_executable(OpenGLEngine3D ${SOURCES})
target_link_libraries(OpenGLEngine3D glfw)
Its dirty(I think) but it works.
So now my first question is, how to improve my CMake script? What is redundant or done in a poor way?
Now my program also requires some resources(like shaders, textures) which I have stored in a directory along with my CMake script, libraries and c++ files.
So my second question is, how would I tell CMake to the ide/compiler to copy the files in a certain directory to the program build directory(where the compiled binaries are) after compiling?(And have it only do it when the files aren't there ofc.)
Thanks!
I recently came across this article, which might be help you with CMake.
Here are a couple suggestions from me:
You're safe to use newer version of CMake. Currently, it's 3.11. There's no point in sticking to old versions.
Consider listing all your sources in a variable (using set command) instead of using file(GLOB). file(GLOB) will be evaluated only once, when generating build files. If you add new sources, you'll have to re-generate it manually, so it doesn't help too much, and is harder to debug (and really, debugging more complex CMake projects can be painful).
Avoid using include_directories (and link_libraries). Prefer using target_include_directories which works per-target. It allows to express dependencies between targets (when you have more than one - which might happen as your project grows)
You might consider using find_package(GLFW), instead of including GLFW in your project. Edit: actually, CMake doesn't came with find module for GLFW, but you can use an external module for this (e. g. this one) as described here.
Edit:
Example below illustrates the idea behind point 2), assuming that sources are placed in "src/" directory on the same level as CMakeLists.txt file:
set(engine_sources
"src/header_1.hpp"
"src/source_1.cpp"
# and so on for reset of files...
)
add_executable(OpenGLEngine3D ${engine_sources})
As for the second question: that's what file(COPY) command is for. Alternatively, you could just leave assets in source directory, and set working directory in IDE.
Side note: if you choose the second options, there appears to be a way to set this from CMake for Visual Studio, by setting VS_DEBUGGER_WORKING_DIRECTORY property:
set_target_properties(OpenGLEngine3D PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
(I haven't checked if this works as expected, as I rarely use VS. I remember looking for something like that in the past, and just recently came across it.)
JetBrains has spoiled me. I'm familiar with the standard UNIX make file and the make, make install routine normally associated with installing software with traditional make files, but I'm not as familiar with cmake since CLion does it all for me.
I want to distribute my code to others and provide simple instructions for building it via cmake so that they have a binary they can execute. The official cmake tutorial shows writing install rules in the CMakeLists.txt file but it isn't clear if this is supported by CLion (or even if it needs to be).
For a simple, single-file (main.cpp) application, what would be an example of how to build it using cmake (assuming those it is distributed to don't have CLion nor use another IDE, they just want to build and use it)?
To build code that comes with a CMakeLists.txt file, you run cmake to generate a Makefile (or other build configuration file):
cmake <path_to_CMakeLists.txt>
Then you run
make;make install
as usual. (or as described in the comment, you can type cmake --build . instead of make - useful if you're on a platform with a different build system)
You don't want to check in the Makefile into your source control, though, as it needs to be generated on the computer that will actually be doing the building.
I've been using NetBeans for a while for my C++ projects. I previously used only make but not cmake. Some colleagues then requested that my codes be compiled using cmake to be "cross-platform"
However, I am having a hard time to set up the NetBeans project using a cmake on OS X. Either it complains that cmake is not found, or does not show the files correctly and completely. Also, cmake seems to be creating some mess in my project directory. Any idea on how to set them up?
In spite of many years of coding large-scale C++ applications, I do not understand how find_package is supposed to work in a medium-size CMake project, ASSUMING that I want to build the source to dependent packages myself and not simply rely on large systems like opencv, pcl or boost being installed somewhere in a system folder. I can't can't believe that I'm the only person in the world who has shipped multiple OpenCV and other open-source apps, has worked with meta-build systems like NAnt and SCons on major game projects, yet can't understand the most basic things about how CMake works or find a tutorial answering these questions.
In the past, I have essentially hacked around not understaning find_package by setting all the foo_DIR values by hand as CMake complains until I get a working folder.
I would like to run through a simple example which I'm working on right now, and dearly hope someone can explain what I'm doing so wrong.
Firstly, some assumptions:
I want to build everything for both MacOS and Windows, ideally via CMakeGUI. MacOS should build XCodeProjects and Windows should build Visual Studio Solutions.
Where there are dependencies, I want to compile them myself, so I have debug symbols and can modify the dependency source (or at least debug into it.)
No installation of pre-built binaries into system folders, i.e. no use of sudo port install opencv/pcl, etc on mac.
I have multiple projects, and prefer to keep a project and its dependencies in a single folder.
For the purposes of a concrete example, suppose I am building this project, although it's an arbitrary choice to illustrate the process and confusion I suffer:
https://github.com/krips89/opendetection
This lists dependencies, which I have intentionally reordered here so that I can take them in order, as follows:
find_package(OpenCV REQUIRED)
find_package(Eigen REQUIRED)
find_package(Boost 1.40 COMPONENTS program_options REQUIRED )
find_package(PCL REQUIRED)
find_package(VTK REQUIRED)
I would like to have all of these dependencies downloaded and configured in a single path (let's say c:\src on Windows, and ~\src on Mac for simplicity), NOT in a system path. Assume that the actual folder is a sub-folder for this project, and no a sub-folder for all projects. This should also allow for side-by-side installation of multiple projects on the same computer.
Taking this one step at a time:
(1) I clone openCV from https://github.com/opencv/opencv, sync to tag 3.1, configure into the folder opencv_build folder, build and install into opencv_install. I've done this so many times it's pretty straightforward.
(2) As above, but for eigen (although building for eigen doesn't actually do anything s it's a template library. I install to a folder eigen_install
Taking directory shows a series of folders for downloaded dependencies. I have assumed a convention where , and are source repos, and their following _build folders are the "WHere to build the binaries" folders in CMakeGui.
$ ls
boost_1_40_0 opencv opendetection_build
eigen opencv-build opendetection_data
eigen_build opencv_contrib pcl
eigen_install opendetection
All good so far, now let's try to configure opendetection and generate a solution into opendetection_build, and find pendetection's dependencies from within the ~/src folder, that is for the first two dependencies, I hope to find opencv and eigen in the opencv-build and eigen-build folders.
OpenCV immediately fails, as expected, saying:
Could not find a package configuration file provided by "OpenCV" with any of the following names:
OpenCVConfig.cmake
opencv-config.cmake
Add the installation prefix of "OpenCV" to CMAKE_PREFIX_PATH or set "OpenCV_DIR" to a directory containing one of the above files. If "OpenCV" provides a separate development package or SDK, be sure it has been installed.
That's good, because I want to explicitly tell CMake to look for dependent packages under my ~/src folder. Question: Is the use of CMAKE_PREFIX_PATH=/users/foo/src the recommended way to accomplish what I want - looking for all sub-packages under a specific path?
Following this, CMake finds OpenCV (good), and sets OpenCV_DIR = /Users/foo/src/opencv-build.
Question: Given that I have made an "install" to opencv-install (using CMAKE_INSTALL_PREFIX and building the Install Target Of OpenCV, shouldn't it find OpenCV in the opencv-install folder not opencv-build?
Moving on to eigen, I have configured and built eigen, and installed it to ~/src/eigen-install, which since it is a subfolder of CMAKE_PREFIX_PATH (~/src) I might expect to be found. But it doesn't seem to be. Can somebody explain to me what I'm not understanding? Particularly given that Eigen in a template library, and that there are at least three folders (eigen, eigen_build and eigen_install) under CMAKE_PREFIX_PATH which I would have thought CMake would find something in, I assume I must be doing something wrong here. I KNOW from past experience, I can set EIGEN_INCLUDE_DIR by hand in CMakeGUI by hand, and continue hacking forth, but that just seems wrong.
I'm more than willing to write up a web page explaining this for future people as dumb as me if one does not already exist, although I can't understand how use of CMake for basic project configuration and generation is apparently so obvious to everyone but so opaque for me. I have actually been using CMake for some years, usually by just manually setting Boost_INCLUDE_Dir, Foo_INCLUDE_PATH etc manually, but clearly this is not the right solution. Generally, after spending a couple of days fighting through the various packages to generate a solution by manually setting INCLUDE PATHS, LIBRARY PATHS and other options, I just deal with the solution and don't touch CMake again. But I would love to understand what I'm missing about find_package for my (surely not uncommon) use case of wanting to control my project dependencies rather than just using sudo port install * and installing random versions of projects to my global system folders.
As error message says, CMAKE_PREFIX_PATH should be set to installation prefix of the package. E.g., if the package has been built using CMake, this is CMAKE_INSTALL_PREFIX variable's value, if the package has been build using Autotools, this is value of --prefix option used for configure it, and so on.
CMake doesn't search every directory under CMAKE_PREFIX_PATH. That is why specifying it as /users/foo/src is useless if you have the package installed at /users/foo/src/eigen-install.
Instead, you may install all 3d-party packages into /users/foo/src/install, and use that path as CMAKE_PREFIX_PATH in your main project.
So basically I have the following setup:
A small test library called mylib with an according CMake file. The CMake file creates all the necessary information so that another project (which is going to be my binary) can use find_package to add the library. The library also has a install target.
A small binary called mybin again wih according CMake file which is depended on the mylib project. Using find_package I can add mylib either by specifying the location of the according myLibConfig.cmake (and myLibTargets.cmake etc.) files or by executing the install target of mylib and then letting CMake find the library itself.
Using CMake and XCode everything works like a charm. First, I configure and build the library. Second, I configure my binary project, specify the location of the library and then build it without any problems.
Now I want to do the same using CLion. My problem now is that CLion puts all the generated CMake file (which usually are placed in the build folder) in some cryptic location which can't be changed in the IDE. Now, when I want to build the mybin project I have to specify this cryptic location which seems kinda odd to me (especially because you have to find out first where CLion actually places those files).
So my question is: Is there a more convenient way to handle the described configuration? I guess this is more or less the standard use case which makes me wonder if I'm missing out on something. Being able to specify where CLion should put the generated CMake files would solve my problem I guess.
I know that i can install the library (using the install target) and then let CMake find it. The problem here is that CLion (to my understanding) doesn't support install targets and therefore I have to use (in my case) XCode to build and install the library first.
I was misunderstsanding the intention of find_package(as Tsyvarev pointed out). By using the solution proposed in this question I managed to add an install target to CLion which now allows me to conveniently build "mylib" and use it in the "mybin" project without having to configure anything manually.