Somehow I am totally confused by how CMake works. Every time I think that I am getting closer to understand how CMake is meant to be written, it vanishes in the next example I read. All I want to know is, how should I structure my project, so that my CMake requires the least amount of maintainance in the future. For example, I don't want to update my CMakeList.txt when I am adding a new folder in my src tree, that works exactly like all other src folders.
This is how I imagine my project's structure, but please this is only an example. If the recommended way differs, please tell me, and tell me how to do it.
myProject
src/
module1/
module1.h
module1.cpp
module2/
[...]
main.cpp
test/
test1.cpp
resources/
file.png
bin
[execute cmake ..]
By the way, it is important that my program knows where the resources are. I would like to know the recommended way of managing resources. I do not want to access my resources with "../resources/file.png"
The most basic but complete example can be find in the cmake tutorial :
For your project example you may have:
For your additional question, one way to go is again in the tutorial: create a configurable header file that you include in your code. For this, make a file
configuration.h.in
with the following contents:Then in your
CMakeLists.txt
add:Finally, where you need the path in your code, you can do:
after some research I have now my own version of the most simple but complete cmake example. Here it is, and it tries to cover most of the basics, including resources and packaging.
one thing it does non-standard is resource handling. By default cmake wants to put them in /usr/share/, /usr/local/share/ and something equivalent on windows. I wanted to have a simple zip/tar.gz that you can extract anywhere and run. Therefore resources are loaded relative to the executable.
the basic rule to understand cmake commands is the following syntax:
<function-name>(<arg1> [<arg2> ...])
without comma or semicolor. Each argument is a string.foobar(3.0)
andfoobar("3.0")
is the same. you can set lists/variables withset(args arg1 arg2)
. With this variable setfoobar(${args})
andfoobar(arg1 arg2)
are effectively the same. A non existent variable is equivalent to an empty list. A list is internally just a string with semicolons to separate the elements. Therefore a list with just one element is by definition just that element, no boxing takes place. Variables are global. Builtin functions offer some form of named arguments by the fact that they expect some ids likePUBLIC
orDESTINATION
in their argument list, to group the arguments. But that's not a language feature, those ids are also just strings, and parsed by the function implementation.you can clone everything from github