mirror of
1
0
Fork 0

Adding module

This commit is contained in:
Henry Fredrick Schreiner 2018-04-05 14:54:25 +02:00
parent ed2227e7a4
commit e589556d29
4 changed files with 134 additions and 1 deletions

View File

@ -15,6 +15,7 @@
* [C++11 and Beyond](chapters/features/cpp11.md)
* [Small but common needs](chapters/features/small.md)
* [Utilities](chapters/features/utilities.md)
* [Useful modules](chapters/features/modules.md)
* [IDEs](chapters/features/ides.md)
* [Debugging](chapters/features/debug.md)
* [Including Projects](chapters/projects.md)

View File

@ -9,6 +9,23 @@ set(MY_VARIABLE "value")
The names of variables are usually all caps, and the value follows. You access a variable by using `${}`, such as `${MY_VARIABLE}`.[^1] CMake has the concept of scope; you can access the value of the variable after you set it as long as you are in the same scope. If you leave a function or a file in a sub directory, the variable will no longer be defined. You can set a variable in the scope immediately above your current one with `PARENT_SCOPE` at the end.
Lists are simply a series of values when you set them:
```cmake
set(MY_LIST "one" "two")
```
which internally become `;` separated values. So this is an identical statement:
```cmake
set(MY_LIST "one;two")
```
The `list(` command has utilities for working with lists, and `separate_arguments` will turn a space separated string into a list (inplace). Note that an unquoted value in CMake is the same as a quoted one if there are no spaces in it; this allows you to skip the quotes most of the time when working with value that you know could not contain spaces.
When a variable is expanded using `${}` syntax, all the same rules about spaces apply. Be especially careful with paths; paths may contain a space at any time and should always be quoted when they are a variable (never write `${MY_PATH}`, always should
be `"${MY_PATH}"`).
## Cache Variables
If you want to set a variable from the command line, CMake offers a variable cache. Some variables are already here, like `CMAKE_BUILD_TYPE`. The syntax for declaring a variable and setting it if it is not already set is:
@ -24,7 +41,11 @@ set(MY_CACHE_VARIABLE "VALUE" CACHE STRING "" FORCE)
mark_as_advanced(MY_CACHE_VARIABLE)
```
The first line will cause the value to be set no matter what, and the second line will keep the variable from showing up in the list of variables if you run `cmake -L ..` or use a GUI.
The first line will cause the value to be set no matter what, and the second line will keep the variable from showing up in the list of variables if you run `cmake -L ..` or use a GUI. This is so common, you can also use the `INTERNAL` type to do the same thing (though technically it forces the STRING type, this won't affect any CMake code that depends on the variable):
```cmake
set(MY_CACHE_VARIABLE "VALUE" CACHE INTERNAL "")
```
Since `BOOL` is such a common variable type, you can set it more succinctly with the shortcut:
@ -36,6 +57,10 @@ For the `BOOL` datatype, there are several different wordings for `ON` and `OFF`
See [cmake-variables] for a listing of known variables in CMake.
## Environment variables
You can also `set(ENV{variable_name} value)` and get `$ENV{variable_name}` environment variables, though it is generally a very good idea to avoid them.
## The Cache
The cache is actually just a text file, `CMakeCache.txt`, that gets created in the build directory when you run CMake. This is how CMake remembers anything you set, so you don't have to re-list your options every time you rerun CMake.

View File

@ -0,0 +1,88 @@
# Useful Modules
There are a ton of [modules] in CMake; but some of them are more useful than others. Here are a few highlights.
## [CMakeDependentOption]
This adds a command `cmake_dependent_option` that sets an option based on another set of variables being true. It looks like this:
```cmake
include(CMakeDependentOption)
cmake_dependent_option(BUILD_TESTS "Build your tests" ON "VAL1;VAL2" OFF)
```
which is just a shortcut for this:
```cmake
if(VAL1 AND VAL2)
set(BUILD_TESTS_DEFAULT ON)
else()
set(BUILD_TESTS_DEFAULT OFF)
endif()
option(BUILD_TESTS "Build your tests" ${BUILD_TESTS_DEFAULT})
if(NOT BUILD_TESTS_DEFAULT)
mark_as_advanced(BUILD_TESTS)
endif()
```
## [CheckCXXCompilerFlag]
This checks to see if a flag is supported. For example:
```cmake
include(CheckCXXCompilerFlag)
check_cxx_compiler_flag(-someflag OUPUT_VARIABLE)
```
Note that `OUTPUT_VARIABLE` will also appear in the configuration printout, so choose a good name.
This is just one of many similar modules, such as `CheckIncludeFileCXX`, `CheckStructHasMember`, `TestBigEndian`, and `CheckTypeSize` that allow you
to check for information about the system (and you can communicate that to your source code).
## [WriteCompilerDetectionHeader]
This is an amazing module similar to the ones listed above, but special enough to deserve its own section. It allows you
to look for a list of features that some compilers support, and write out a C++ header file that lets you know whether that
feature is available. It even can provide compatibility macros for features that have changed names!
To use:
```cmake
write_compiler_detection_header(
FILE myoutput.h
PREFIX My
COMPILERS GNU Clang MSVC Intel
FEATURES cxx_variadic_templates
)
```
This supports compiler features (defined to 0 or 1), symbols (defined to empty or the symbol), and macros that
support different names. They will be prefixed with the PREFIX you provide. You can separate compilers into different
files using `OUTPUT_FILES_DIR
The downside is that you do have to list the compilers you expect to support. If you use the `ALLOW_UNKNOWN_COMPILERS` flag(s),
you can keep this from erroring on unknown compilers, but it will still leave all features empty.
## [try_compile](https://cmake.org/cmake/help/latest/command/try_compile.html)/[try_run](https://cmake.org/cmake/help/latest/command/try_run.html)
This is not exactly a module, but is crutial to many of the modules listed above. You can attept to compile (and possibly run) a bit of code at configure time. This can allow you to get information about the capabilities of your system. The basic syntax is:
```cmake
try_compile(
RESULT_VAR
bindir
SOURCES
source.cpp
)
```
There are lots of options you can add, like `COMPILE_DEFINITIONS`. In CMake 3.8+, this will honor the CMake C/C++/CUDA standard settings. If you use `try_run` instead, it will run the resulting program and give you the output in `RUN_OUTPUT_VARIABLE`.
[modules]: https://cmake.org/cmake/help/latest/manual/cmake-modules.7.html
[CMakeDependentOption]: https://cmake.org/cmake/help/latest/module/CMakeDependentOption.html
[CheckCXXCompilerFlag]: https://cmake.org/cmake/help/latest/module/CheckCXXCompilerFlag.html
[WriteCompilerDetectionHeader]: https://cmake.org/cmake/help/latest/module/WriteCompilerDetectionHeader.html

View File

@ -23,4 +23,23 @@ add_test(NAME TestName COMMAND $<TARGET_FILE:${TESTNAME}>)
which would use the output location (thus, the executable) of the produced target.
## Building as part of a test
If you want to run CMake to build a project as part of a test, you can do that too (in fact, this is how CMake tests itself). For example, if your master project was called `MyProject` and you had an `examples/simple` project that could build by itself, this would look like:
```cmake
add_test(
NAME
ExampleCMakeBuild
COMMAND
"${CMAKE_CTEST_COMMAND}"
--build-and-test "${My_SOURCE_DIR}/examples/simple"
"${CMAKE_CURRENT_BINARY_DIR}/simple"
--build-generator "${CMAKE_GENERATOR}"
--test-command "${CMAKE_CTEST_COMMAND}"
)
```
## Testing Frameworks
Look at the subchapters for recipes for popular frameworks.