Adding module
This commit is contained in:
parent
ed2227e7a4
commit
e589556d29
@ -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)
|
||||
|
@ -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.
|
||||
|
88
chapters/features/modules.md
Normal file
88
chapters/features/modules.md
Normal 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
|
@ -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.
|
||||
|
Loading…
x
Reference in New Issue
Block a user