一个跨平台的安装(编译)工具
二次整理自网络教程。
1 cmake-examples总结
项目地址:GitHub
- ttroy50/cmake-examples: Useful CMake Examples
中文辅助学习网址:前言 · GitBook
(sfumecjf.github.io) (部分内容少于官方,比如01-E、01-L、03以后的部分)
01-basic
A 你好cmake
1 2 ├── CMakeLists.txt ├── main.cpp
1 2 3 cmake_minimum_required (VERSION 3.5 ) project (hello_cmake) add_executable (hello_cmake main.cpp)
在windows上如果要生成makefile而不是sln,不能用MSVC,应该用MinGW 。添加环境变量CMAKE_GENERATOR为MinGW
Makefiles,或者命令行中使用 -G “MinGW Makefiles”。
1 2 3 4 5 6 7 8 9 mkdir buildcd build/ cmake .. make cmake . -B build cmake --build build
B 头文件
1 2 3 4 5 6 ├── CMakeLists.txt ├── include │ └── Hello.h └── src ├── Hello.cpp └── main.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 cmake_minimum_required (VERSION 3.5 )project (hello_headers)set (SOURCES src/Hello.cpp src/main.cpp )add_executable (hello_headers ${SOURCES} ) target_include_directories (hello_headers PRIVATE ${PROJECT_SOURCE_DIR} /include )
C 静态库
1 2 3 4 5 6 7 ├── CMakeLists.txt ├── include │ └── static │ └── Hello.h └── src ├── Hello.cpp └── main.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 cmake_minimum_required (VERSION 3.5 )project (hello_library)add_library (hello_library STATIC src/Hello.cpp )target_include_directories (hello_library PUBLIC ${PROJECT_SOURCE_DIR} /include )add_executable (hello_binary src/main.cpp )target_link_libraries ( hello_binary PRIVATE hello_library )
target_include_directories范围
PRIVATE - 目录被添加到目标(库)的包含路径中。
INTERFACE -
目录没有被添加到目标(库)的包含路径中,而是链接了这个库的其他目标(库或者可执行程序)包含路径中
PUBLIC -
目录既被添加到目标(库)的包含路径中,同时添加到了链接了这个库的其他目标(库或者可执行程序)的包含路径中
D 共享库
1 2 3 4 5 6 7 ├── CMakeLists.txt ├── include │ └── shared │ └── Hello.h └── src ├── Hello.cpp └── main.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 cmake_minimum_required (VERSION 3.5 )project (hello_library)add_library (hello_library SHARED src/Hello.cpp )add_library (hello::library ALIAS hello_library)target_include_directories (hello_library PUBLIC ${PROJECT_SOURCE_DIR} /include )add_executable (hello_binary src/main.cpp )target_link_libraries ( hello_binary PRIVATE hello::library )
E 安装
1 2 3 4 5 6 7 8 ├── cmake-examples.conf ├── CMakeLists.txt ├── include │ └── installing │ └── Hello.h └── src ├── Hello.cpp └── main.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 cmake_minimum_required (VERSION 3.5 )project (cmake_examples_install)add_library (cmake_examples_inst SHARED src/Hello.cpp )target_include_directories (cmake_examples_inst PUBLIC ${PROJECT_SOURCE_DIR} /include )add_executable (cmake_examples_inst_bin src/main.cpp )target_link_libraries ( cmake_examples_inst_bin PRIVATE cmake_examples_inst )install (TARGETS cmake_examples_inst_bin DESTINATION bin)install (TARGETS cmake_examples_inst LIBRARY DESTINATION lib)install (DIRECTORY ${PROJECT_SOURCE_DIR} /include / DESTINATION include )install (FILES cmake-examples.conf DESTINATION etc)
windows上CMAKE_INSTALL_PREFIX 默认是C:Files
(x86)。如果要修改安装路径,使用 -DCMAKE_INSTALL_PREFIX='D:'。
F 构建类型
1 2 ├── CMakeLists.txt ├── main.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 cmake_minimum_required (VERSION 3.5 )if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) message ("Setting build type to 'RelWithDebInfo' as none was specified." ) set (CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose the type of build." FORCE) set_property (CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo" )endif ()project (build_type)add_executable (cmake_examples_build_type main.cpp)
cmake优化级别
Release ——
不可以打断点调试,程序开发完成后发行使用的版本,占的体积小。
它对代码做了优化,因此速度会非常快,
在编译器中使用命令: -O3 -DNDEBUG
可选择此版本。
Debug ——调试的版本,体积大。
在编译器中使用命令: -g
可选择此版本。
MinSizeRel—— 最小体积版本
在编译器中使用命令:-Os -DNDEBUG
可选择此版本。
RelWithDebInfo—— 既优化又能调试。
在编译器中使用命令:-O2 -g -DNDEBUG
可选择此版本。
命令行中使用-DCMAKE_BUILD_TYPE=Release可以设置
G 编译选项
1 2 ├── CMakeLists.txt ├── main.cpp
1 2 3 4 5 6 7 8 9 cmake_minimum_required (VERSION 3.5 )set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DEX2" CACHE STRING "Set C++ Compiler Flags" FORCE)project (compile_flags)add_executable (cmake_examples_compile_flags main.cpp)target_compile_definitions (cmake_examples_compile_flags PRIVATE EX3 )
除了以上两种方法设置编译选项,还可以在命令行中使用-DCMAKE_CXX_FLAGS=(是全局的)。
H 包含第三方库
1 2 ├── CMakeLists.txt ├── main.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 cmake_minimum_required (VERSION 3.5 )project (third_party_include)find_package (Boost 1.46 .1 REQUIRED COMPONENTS filesystem system)if (Boost_FOUND) message ("boost found" )else () message (FATAL_ERROR "Cannot find Boost" )endif ()add_executable (third_party_include main.cpp)target_link_libraries ( third_party_include PRIVATE Boost::filesystem )
I 使用clang编译工程
1 2 3 4 ├── CMakeLists.txt ├── main.cpp ├── pre_test.sh ├── run_test.sh
1 2 3 cmake_minimum_required (VERSION 3.5 )project (hello_cmake)add_executable (hello_cmake main.cpp)
此示例与hello-cmake 示例相同,不同之处在于它使用脚本将编译器从默认的gcc更改为clang 的最基本方法。
CMake提供了控制程序编译以及链接的选项,选项如下:
CMAKE_C_COMPILER - 用于编译c代码的程序。
CMAKE_CXX_COMPILER - 用于编译c++代码的程序。
CMAKE_LINKER - 用于链接二进制文件的程序。
J 使用ninja编译工程
1 2 3 4 ├── CMakeLists.txt ├── main.cpp ├── pre_test.sh ├── run_test.sh
1 2 3 cmake_minimum_required (VERSION 3.5 )project (hello_cmake)add_executable (hello_cmake main.cpp)
使用cmake
-h查看支持的构建工具生成器。有三种,分别是命令行构建工具生成器、IDE构建工具生成器、其它生成器。使用-G选择生成器。
K 导入目标
与H相似。
L C++标准
common-method .
可以与大多数版本的CMake一起使用的简单方法。
1 2 ├── CMakeLists.txt ├── main.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 cmake_minimum_required (VERSION 2.8 )project (hello_cpp11)include (CheckCXXCompilerFlag) CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11) CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)if (COMPILER_SUPPORTS_CXX11) set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11" )elseif (COMPILER_SUPPORTS_CXX0X) set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x" )else () message (STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler." )endif ()add_executable (hello_cpp11 main.cpp)
cxx-standard .
使用CMake v3.1中引入的CMAKE_CXX_STANDARD变量。
1 2 ├── CMakeLists.txt ├── main.cpp
1 2 3 4 5 6 7 cmake_minimum_required (VERSION 3.1 )project (hello_cpp11)set (CMAKE_CXX_STANDARD 11 )add_executable (hello_cpp11 main.cpp)
它会选择最近的正确标准而不会报错。
compile-features .
使用CMake v3.1中引入的target_compile_features函数。
1 2 ├── CMakeLists.txt ├── main.cpp
1 2 3 4 5 6 7 8 9 10 cmake_minimum_required (VERSION 3.1 )project (hello_cpp11)add_executable (hello_cpp11 main.cpp)target_compile_features (hello_cpp11 PUBLIC cxx_auto_type)message ("List of compile features: ${CMAKE_CXX_COMPILE_FEATURES}" )
02-sub-projects
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ├── CMakeLists.txt 最高层 ├── subbinary │ ├── CMakeLists.txt 生成可执行文件 │ └── main.cpp ├── sublibrary1 │ ├── CMakeLists.txt 生成静态库 │ ├── include │ │ └── sublib1 │ │ └── sublib1.h │ └── src │ └── sublib1.cpp └── sublibrary2 ├── CMakeLists.txt 生成仅有头文件的库 └── include └── sublib2 └── sublib2.h
将头文件移至每个项目include目录下的子文件夹可以防止文件名冲突
1 2 3 4 5 6 7 cmake_minimum_required (VERSION 3.5 )project (subprojects)add_subdirectory (sublibrary1)add_subdirectory (sublibrary2)add_subdirectory (subbinary)
CMake中有一些变量会自动创建:
PROJECT_NAME
当前project()设置的项目的名称。
CMAKE_PROJECT_NAME
由project()命令设置的第一个项目的名称,即顶层项目。
PROJECT_SOURCE_DIR
当前项目的源文件目录。
PROJECT_BINARY_DIR
当前项目的构建目录。
name_SOURCE_DIR
在此示例中,创建的源目录为 sublibrary1_SOURCE_DIR
,
sublibrary2_SOURCE_DIR
, and
subbinary_SOURCE_DIR
name_BINARY_DIR
本工程的二进制目录是sublibrary1_BINARY_DIR
,
sublibrary2_BINARY_DIR
,和
subbinary_BINARY_DIR
1 2 3 4 5 6 7 8 9 10 project (subbinary)add_executable (${PROJECT_NAME} main.cpp)target_link_libraries (${PROJECT_NAME} sub::lib1 sub::lib2 )
1 2 3 4 5 6 7 8 9 project (sublibrary1)add_library (${PROJECT_NAME} src/sublib1.cpp)add_library (sub::lib1 ALIAS ${PROJECT_NAME} )target_include_directories ( ${PROJECT_NAME} PUBLIC ${PROJECT_SOURCE_DIR} /include )
1 2 3 4 5 6 7 8 9 project (sublibrary2)add_library (${PROJECT_NAME} INTERFACE)add_library (sub::lib2 ALIAS ${PROJECT_NAME} )target_include_directories (${PROJECT_NAME} INTERFACE ${PROJECT_SOURCE_DIR} /include )
03-code-generation
代码生成是一个很好用的功能,它可以使用一份公共的描述文件,生成不同语言下的源代码。这个功能使得需要人工编写的代码大幅减少,同时也增加了互操作性。
使用CMake中的configure_file函数注入CMake变量
1 2 3 4 ├── CMakeLists.txt ├── main.cpp ├── path.h.in ├── ver.h.in
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 cmake_minimum_required (VERSION 3.5 )project (cf_example)set (cf_example_VERSION_MAJOR 0 )set (cf_example_VERSION_MINOR 2 )set (cf_example_VERSION_PATCH 1 )set (cf_example_VERSION "${cf_example_VERSION_MAJOR}.${cf_example_VERSION_MINOR}.${cf_example_VERSION_PATCH}" )configure_file (ver.h.in ${PROJECT_BINARY_DIR} /ver.h)configure_file (path.h.in ${PROJECT_BINARY_DIR} /path.h @ONLY)add_executable (cf_example main.cpp )target_include_directories ( cf_example PUBLIC ${CMAKE_BINARY_DIR} )
2 Protocol Buffers
使用Google Protocol Buffers来生成C++源码
1 2 3 ├── AddressBook.proto ├── CMakeLists.txt ├── main.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 cmake_minimum_required (VERSION 3.5 )project (protobuf_example)find_package (Protobuf REQUIRED)if (PROTOBUF_FOUND) message ("protobuf found" )else () message (FATAL_ERROR "Cannot find Protobuf" )endif () PROTOBUF_GENERATE_CPP(PROTO_SRCS PROTO_HDRS AddressBook.proto)message ("PROTO_SRCS = ${PROTO_SRCS}" )message ("PROTO_HDRS = ${PROTO_HDRS}" )add_executable (protobuf_example main.cpp ${PROTO_SRCS} ${PROTO_HDRS} )target_include_directories (protobuf_example PUBLIC ${PROTOBUF_INCLUDE_DIRS} ${CMAKE_CURRENT_BINARY_DIR} )target_link_libraries (protobuf_example PUBLIC ${PROTOBUF_LIBRARIES} )
04-static-analysis