CMake
Table of Contents
1 Tmp
set(CMAKE_CXX_STANDARD 11)
2 Language
2.1 Organization
The entry point is CMakeLists.txt
. It can add other directories by
add_subdirectory()
command, and that directory should also contains a
CMakeLists.txt
. Use include()
command can include a <module>.cmake
file.
2.2 Option
CMAKE_EXPORT_COMPILE_COMMANDS=ON
- export
compile_commands.json
2.3 Syntax
The CMakeLists.txt
file contains commands separated by white spaces.
Command is an identifier with paren-enclosed arguments separated by
white spaces. The paren-enclosing can be nested.
Arguments can be
type | escape sequence | variable reference |
---|---|---|
bracket_argument |
\(\times\) | \(\times\) |
quoted_argument |
\(\checkmark\) | \(\checkmark\) |
unquoted_argument |
\(\checkmark\) | \(\checkmark\) |
The length of = can be 0 or more.
bracket_argument ::= bracket_open bracket_content bracket_close bracket_open ::= '[' '='{len} '[' bracket_content ::= <any text not containing a bracket_close of the same {len} as the bracket_open> bracket_close ::= ']' '='{len} ']'
2.4 Variable
Variable syntax is ${VAR}
or $ENV{VAR}
. The reference can be nested
and evaluate the inner first: ${outer_${inner_variable}_variable}
.
- set()
- unset()
Inside set and unset, the variable don't need $
. Two or more values are
connected into list (separated by ;
). Zero values is implicit unset.
set(<variable> <value>... [PARENT_SCOPE]) set(<variable> <value>... CACHE <type> <docstring> [FORCE]) set(ENV{<variable>} <value>...)
Variables have dynamic scope.
- function scope
- created by
function
command. Not visible outside function. - directory scope
- the
CMakeLists.txt
- persistent scope
- the "cache" variable is available across multiple runs within a project build tree
2.5 Comments
a leading #
is a line comment. A #
followed immediately by bracket
argument, i.e. #[=[xxx]=]
, can be multiple line or inline comments.
2.6 Control Structure
2.6.1 Conditional
- if()
- elseif()
- else()
- endif()
if(expression) COMMAND1(ARGS ...) elseif(expression2) COMMAND1(ARGS ...) COMMAND2(ARGS ...) else() COMMAND1(ARGS ...) endif()
The expression can be:
- constant: 0 OFF, NO FALSE, N are false
- variable: true if defined and not false constant
- NOT, AND, OR
- EXISTS path-to-file-or-dir
- …
2.6.2 Loop
- foreach()
- endforeach()
foreach(loop_var arg1 arg2 ...) COMMAND1(ARGS ...) COMMAND2(ARGS ...) ... endforeach(loop_var) foreach(loop_var RANGE total) foreach(loop_var RANGE start stop [step])
- while()
- endwhile()
while(condition) COMMAND1(ARGS ...) COMMAND2(ARGS ...) ... endwhile(condition)
- break()
- continue()
2.7 Command Definition
- macro()
- endmacro()
- function()
- endfunction()
3 Variables
Set by cmake -DXXX=1
CMAKE_INSTALL_PREFIX
: where to install. Default to/usr/local
CMAKE_BUILD_TYPE
: possible values: empty, Debug, Release, RelWithDebInfo, MinSizeRel
4 Trouble Shooting
When using find_package(PythonInterp 2.7 REQUIRED)
, it keeps find the 3.6 version.
To solve that, invoke cmake like this:
cmake -DPYTHON_EXECUTABLE=/usr/bin/python2 ..
To change the boost version, change the enviroment variable:
export BOOST_ROOT=/path/to/alternative/boost
To build the boost:
./bootstrap.sh --without-libraries=atomic,chrono,context,coroutine,exception,graph,graph_parallel,iostreams,locale,log,math,mpi,python,random,serialization,signals,test,timer,wave ./b2 --prefix=/path/to/custom/location link=static cxxflags="-fPIC -static -Wl,--whole-archive" threading=multi install
5 Idiom
cmake_minimum_required(VERSION 3.0) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) SET(CMAKE_EXPORT_COMPILE_COMMANDS ON) find_package (Threads) link_libraries(${CMAKE_THREAD_LIBS_INIT}) enable_testing() add_subdirectory (src) add_subdirectory (test)
src/CMakeLists.txt
to add libraries, executables
add_library (Sqr sqr.cpp sqr.h) add_executable (demo main.cpp) target_link_libraries (demo Sqr) add_executable(ast ast.cpp) add_executable(token token.cpp) add_executable(rewriter rewriter.cpp)
test/CMakeLists.txt
The only requirement is to have enable_testing
before add_test
. The
command can be in src
level list if no test source files.
add_test(NAME toktest COMMAND hetok ../test/a.c) add_test(NAME MyTest COMMAND Test)