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)