【CMake】Visual Studio CMake 教程 vs-cmake-examples

项目链接:
cmake-examples

01 Basic

A Hello CMake

目标:

  • CMake 基本框架
  • 使用Visual Studio 打开构建的项目

CMakeList.txt

# 设置最小的CMake版本
# 可以通过命令查询环境中 cmake 的版本    cmake --version
cmake_minimum_required(VERSION 3.0)
# 设置项目名称
project(hello_cmake)
# 添加一个可执行程序
add_executable(hello_cmake "main.cpp")

编译

  • 创建 Build 目录 并进入Build目录
  • 执行
cmake ..
  • 使用使用visual studio 打开 .sln文件,并编译。

B 添加头文件

目标:

  • 使用 cmake 导入头文件。

文件目录:

.
├── CMakeLists.txt
├── include
│   └── Hello.h
└── src
    ├── Hello.cpp
    └── main.cpp

在main.cpp 中引用 Hello.h

如果不在CMake中导入头文件,就会报错提示找不到 Hello.h 的头文件

CMake 地址相关的宏

Variable Info
CMAKE_SOURCE_DIR The root source directory
CMAKE_CURRENT_SOURCE_DIR The current source directory if using sub-projects and directories.
PROJECT_SOURCE_DIR The source directory of the current cmake project.
CMAKE_BINARY_DIR The root binary / build directory. This is the directory where you ran the cmake command.
CMAKE_CURRENT_BINARY_DIR The build directory you are currently in.
PROJECT_BINARY_DIR The build directory for the current project.

假如项目的路径是: D:\workSpace\cmake-examples\01-basic\B-hello-headers

Variable Info
CMAKE_SOURCE_DIR D:/workSpace/cmake-examples/01-basic/B-hello-headers
CMAKE_CURRENT_SOURCE_DIR D:/workSpace/cmake-examples/01-basic/B-hello-headers
PROJECT_SOURCE_DIR D:/workSpace/cmake-examples/01-basic/B-hello-headers
CMAKE_BINARY_DIR D:/workSpace/cmake-examples/01-basic/B-hello-headers/build
CMAKE_CURRENT_BINARY_DIR D:/workSpace/cmake-examples/01-basic/B-hello-headers/build
PROJECT_BINARY_DIR D:/workSpace/cmake-examples/01-basic/B-hello-headers/build

CMakeLists.txt

cmake_minimum_required(VERSION 3.0)
project(HelloHeaders)
message("This is a message with a pipe symbol: ||")
message(====================================================================)
message("|CMAKE_SOURCE_DIR          |"  ${CMAKE_SOURCE_DIR}              "|")
message("|CMAKE_CURRENT_SOURCE_DIR  |"  ${CMAKE_CURRENT_SOURCE_DIR}      "|")
message("|PROJECT_SOURCE_DIR        |"  ${PROJECT_SOURCE_DIR}            "|")
message("|CMAKE_BINARY_DIR          |"  ${CMAKE_BINARY_DIR}              "|")
message("|CMAKE_CURRENT_BINARY_DIR  |"  ${CMAKE_CURRENT_BINARY_DIR}      "|")
message("|PROJECT_BINARY_DIR        |"  ${PROJECT_BINARY_DIR}            "|")
message(====================================================================)


set(SOURCE 
    src/Hello.cpp
    src/main.cpp
)
add_executable(HelloHeaders ${SOURCE})

# 添加头文件
# PRIVATE 表示只为当前的目标添加头文件目录,不会影响其他目标
target_include_directories(HelloHeaders 
    PRIVATE
        ${PROJECT_SOURCE_DIR}/include
)

C 静态库

目标: 使用CMake打包静态库。在windows 下,将某一个模块,打包成静态库。将会生成:

  • xxx.lib 文件
  • xxx.h 头文件

在其他代码里就可以导入头文件,链接.lib文件来调用模块中的功能。

文件目录:

├── CMakeLists.txt
├── include
│   └── static
│       └── Hello.h
└── src
    ├── Hello.cpp
    └── main.cpp

CMakeLists.txt

cmake_minimum_required(VERSION 3.0)
project(hello_library)

############################################################
# 创建静态库
############################################################
add_library(hello_library_lib STATIC src/Hello.cpp)
# 导入include 头文件目录
target_include_directories(hello_library_lib 
    PUBLIC
        ${PROJECT_SOURCE_DIR}/include)
############################################################
# 创建可执行文件
############################################################
add_executable(hello_library_exe 
    src/main.cpp)
# 链接静态库
target_link_libraries(hello_library_exe 
    PRIVATE
        hello_library_lib)

添加一个静态库

add_library(hello_library_lib STATIC src/Hello.cpp)
  • STATIC 表示打包静态库

导入头文件

# 导入include 头文件目录
target_include_directories(hello_library_lib 
    PUBLIC
        ${PROJECT_SOURCE_DIR}/include)

在这里使用了 PUBLIC 的作用域,这将使得include目录在如下场景被使用:

  • 编译静态库时
  • 当编译以及链接目标库时

作用域的含义:

  • PRIVATE 目录被加在当前目标的 include路径
  • INTERFACE 目录将被加在任意链接这个库的 include 路径
  • PUBLIC 和上面一样, 目录将被加在任意链接这个库的 include 路径

TIPS:

  • 对于 public 头文件,通常最好将您的include文件夹,使用子目录进行"命名空间"化。
  • target_include_directories接收的目录将成为您的包含(include)目录树的根目录,您的C++文件应该包含从根目录到您的头文件的路径。
  • 在这个例子里面,你可以这样导入:
#include "static/Hello.h"
  • 使用这种方法意味着在您的项目中使用多个库时,头文件名称冲突的可能性较小。带上了库的名字,不然容易导致有重复的名字的库,带来很多意外的结果。

链接库

add_executable(hello_binary
    src/main.cpp
)

target_link_libraries( hello_binary
    PRIVATE
        hello_library
)

动态库

动态库,在Windows下会生成:

  • xx.dll
  • xx.lib
  • xx.h

在CMake上只有一点不同就是:

# 生成动态库
add_library(hello_libary_dll
    SHARED
        src/Hello.cpp)

在到处动态库时,在windows平台下,需要在要到处的类前面加上一个宏 __declspec, 如果不加,将不会生成 .lib文件,在windows平台下会导入出错的。

#ifndef __HELLO_H__
#define __HELLO_H__

class __declspec( dllexport ) Hello
{
public:
    void print();
};
#endif

安装

目的: 在编译后,我们希望我们编译的目标, 头文件或者配置文件等移动到相关的目录下,这时候在CMake中就有了 Installing 的概念。基础的安装位置是由变量 **CMAKE_INSTALL_PREFIX ** 控制的。我们在使用 cmake 编译时可以加上这个参数:

cmake .. -DCMAKE_INSTALL_PREFIX=/install/location

比如我这里默认的安装路径为:

CMAKE_INSTALL_PREFIX C:/Program Files (x86)/HelloHeaders
# - Install 二进制文件
install (TARGETS cmake_examples_inst_bin 				DESTINATION 	bin)


# - Install Library
install (TARGETS cmake_examples_inst 		LIBRARY 	DESTINATION 	lib)


# -install Header files
# - copy include directory to  CMAKE_INSTALL_PREFIX/include
install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/ DESTINATION include)


# - Config
# - Copy config file to CMAKE_INSTALL_PREFIX/etc
install (FILES cmake-examples.conf DESTINATION etc)

Windows install 编译结果

1>-- Install configuration: "Debug"
1>-- Installing: D:/workSpace/cmake-examples/01-basic/E-installing/install_dir/bin/cmake_examples_inst_bin.exe
1>-- Installing: D:/workSpace/cmake-examples/01-basic/E-installing/install_dir/lib/cmake_examples_inst.lib
1>-- Installing: D:/workSpace/cmake-examples/01-basic/E-installing/install_dir/bin/cmake_examples_inst.dll
1>-- Installing: D:/workSpace/cmake-examples/01-basic/E-installing/install_dir/include
1>-- Installing: D:/workSpace/cmake-examples/01-basic/E-installing/install_dir/include/installing
1>-- Installing: D:/workSpace/cmake-examples/01-basic/E-installing/install_dir/include/installing/Hello.h
1>-- Installing: D:/workSpace/cmake-examples/01-basic/E-installing/install_dir/etc/cmake-examples.conf

Note: 如果安装目录在C盘,并且没有用管理员权限,不会运行成功。!!!!

设置编译类型

CMake 提供了内置的编译类型:

  • Release - Adds the -O3 -DNDEBUG flags to the compiler
  • Debug - Adds the -g flag
  • MinSizeRel - Adds -Os -DNDEBUG
  • RelWithDebInfo - Adds -O2 -g -DNDEBUG flags
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 the possible values of build type for cmake-gui
  set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release"
    "MinSizeRel" "RelWithDebInfo")
endif()

编译选项

CMake 支持设置编译选项,并且提供如下方式:

  • 使用 ** target_compile_definitions()** 函数。 在现代CMake中设置C++标志的推荐方法是使用每个目标(target)的标志,可以通过target_compile_definitions()函数传递给其他目标。这将为库填充INTERFACE_COMPILE_DEFINITIONS,并根据作用域将定义传递给链接的目标。
target_compile_definitions(cmake_examples_compile_flags
    PRIVATE EX3
)
  • 使用 CMAKE_C_FLAGS and CMAKE_CXX_FLAGS 变量
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DEX2" CACHE STRING "Set C++ Compiler Flags" FORCE)
  • 在编译命令中设置
cmake .. -DCMAKE_CXX_FLAGS="-DEX3"

导入第三方库

以导入Boost 库为例:

find_package(Boost 1.46.1 REQUIRED COMPONENTS filesystem system)
  • find_package 函数将搜索 CMake 模块,这些模块通常是 Findxxx.cmake 的文件,文件通常在 CMAKE_MODULE_PATH 下面。 例如,我的默认模块文件在:C:/Program Files/CMake/share/cmake-3.26/Modules/ 下。
  • Boost 库的名字,通常会去找 FindBoost.cmake这个模块文件
  • 1.46.1 三方库的版本必须大于这个版本
  • REQUIRED 如果找不到会编译失败
  • COMPONENTS 查找的库的组件。

检查是否已经找到库了

许多的包都会包含一个变量 XXX_FOUND ,用来表示这个包是否在系统中是可用的。
比如:

if(Boost_FOUND)
    message ("boost found")
    include_directories(${Boost_INCLUDE_DIRS})
else()
    message (FATAL_ERROR "Cannot find Boost")
endif()

你可能感兴趣的:(Git,驱动开发,ide)