cmake¶
Minimal CMakeLists.txt¶
cmake_minimum_required(VERSION 3.10)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)
project(example)
add_executable(a.out a.cpp b.cpp)
Wildcard Sourse Files¶
cmake_minimum_required(VERSION 3.10)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)
file(GLOB src "*.cpp")
project(example)
add_executable(a.out ${src})
Set CXXFLAGS¶
cmake_minimum_required(VERSION 3.10)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)
file(GLOB src "*.cc")
project(example)
set(CMAKE_CXX_FLAGS "-Wall -Werror -O3")
add_executable(a.out ${src})
cmake_minimum_required(VERSION 3.10)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)
file(GLOB src "*.cc")
project(example)
add_executable(a.out ${src})
target_compile_options(a.out PRIVATE -Werror)
Set CXXFLAGS with Build Type¶
# common
set(CMAKE_CXX_FLAGS "-Wall -Werror -O3")
# debug
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS} -g")
# release
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_CXX_FLAGS} -O3 -pedantic")
Build Debug/Release¶
$ cmake -DCMAKE_BUILD_TYPE=Release ../
$ cmake -DCMAKE_BUILD_TYPE=Debug ../
Build with Type¶
cmake_minimum_required(VERSION 3.10)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)
project(example)
add_executable(a.out a.cc)
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
target_compile_options(a.out PRIVATE -g -O0 -Wall)
else()
target_compile_options(a.out PRIVATE -O3 -Wall -Werror)
endif()
Instead of checking CMAKE_BUILD_TYPE
, modern CMake prefers to use generator
expressions to examine conditions.
cmake_minimum_required(VERSION 3.10)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)
project(example)
add_executable(a.out a.cc)
target_compile_options(a.out PRIVATE
$<IF:$<CONFIG:Debug>, -g -O0 -Wall, -O3 -Wall -Werror>
)
Version File¶
cmake_minimum_required(VERSION 3.10)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)
file(GLOB src "*.cpp")
project(example VERSION 1.0)
configure_file(version.h.in version.h)
add_executable(a.out ${src})
target_include_directories(a.out PUBLIC "${PROJECT_BINARY_DIR}")
version.h.in
#pragma once
#define VERSION_MAJOR @example_VERSION_MAJOR@
#define VERSION_MINOR @example_VERSION_MINOR@
Build/Link a static library¶
cmake_minimum_required(VERSION 3.10)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)
file(GLOB src "*.cpp")
project(example VERSION 1.0)
configure_file(version.h.in version.h)
add_executable(a.out ${src})
add_library(b b.cpp)
target_link_libraries(a.out PUBLIC b)
target_include_directories(a.out PUBLIC "${PROJECT_BINARY_DIR}")
Subdirectory¶
subdirectory fib/
cmake_minimum_required(VERSION 3.10)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)
file(GLOB src "*.cpp")
add_library(b SHARED b.cpp)
target_include_directories(b PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}")
project dir
cmake_minimum_required(VERSION 3.10)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)
file(GLOB src "*.cpp")
project(example VERSION 1.0)
configure_file(version.h.in version.h)
add_executable(a.out ${src})
add_subdirectory(fib)
target_link_libraries(a.out PUBLIC b)
target_include_directories(a.out PUBLIC
"${PROJECT_BINARY_DIR}"
"${PROJECT_BINARY_DIR/fib}"
)
PUBLIC & PRIVATE¶
PUBLIC - only affect the current target, not dependencies
INTERFACE - only needed for dependencies
cmake_minimum_required(VERSION 3.10)
project(example)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)
find_package(Boost)
add_executable(a.out a.cpp)
add_library(b STATIC b.cpp b.h)
target_include_directories(a.out PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}")
target_include_directories(b PRIVATE "${Boost_INCLUDE_DIR}")
target_link_libraries(a.out INTERFACE b) # link b failed
Generator Expression¶
cmake_minimum_required(VERSION 3.10)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)
project(example)
set(target fib)
add_library(${target} src/fib.cc)
target_compile_options(${target} PRIVATE -Wall -Werror -Wextra)
target_include_directories(${target}
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src
)
Install¶
cmake_minimum_required(VERSION 3.10)
project(a)
add_library(b_static STATIC b.cc)
add_library(b_shared SHARED b.cc)
add_executable(a a.cc b.cc)
include(GNUInstallDirs)
set(INSTALL_TARGETS a b_static b_shared)
install(TARGETS ${INSTALL_TARGETS}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
install(FILES b.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
Run a command at configure time¶
execute_process(
COMMAND git submodule update --init --recursive
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
RESULT_VARIABLE GIT_SUBMOD_RESULT
)
Option¶
# $ make -p build
# $ cd build
# $ cmake -DBUILD_TEST=ON ../
option(BUILD_TEST "Build test" OFF)
if (BUILD_TEST)
message("Build tests.")
else()
message("Ignore tests.")
endif()
Alias a Library¶
When a CMakeLists.txt
export Foo in namespace Foo::
, it also need to
create an alias Foo::Foo
.
add_library(Foo::Foo ALIAS Foo)