uWebSockets 的使用为例。

参考:

https://www.hahack.com/codes/cmake/

https://chenxiaowei.gitbook.io/cmake-cookbook/

  • 新建工程,结构如下:
    1. .
    2. ├── CMakeLists.txt
    3. ├── build
    4. ├── src
    5. └── main.cc
    6. └── third_party
    7. ├── CMakeLists.txt
    8. ├── include
    9. └── uWebSockets


目录结构说明:

  • CMakeLists.txt 为项目工程的 cmake 描述文件。
  • build 为构建输出目录。cmake 没有清理命令,所以,一般将输出放到独立的目录下,方便区分。
  • src 为源码跟目录。
  • third_party 为第三方依赖。在 third_party 目录下也创建 CMakeLists.txt,管理所有的第三方依赖。
    • 增加依赖 uWebSockets:

      第三方依赖是通过 git submodulecmake 结合的方式。

  • 在项目跟目录下执行 git init 初始化。

  • 增加 submodule

    git submodule add https://github.com/uNetworking/uWebSockets.git third_party/uWebSockets
    
  • 由于 uWebSockets 本身也包含了 submodule,需在工程目录下执行 git submodule update —init —recursive
  • 创建项目的 CMakeLists.txt: ```cmake

    项目依赖的cmkae最低版本,注意括号中的 VERSION 要带上。

    cmake_minimum_required(VERSION 3.16.2)

指定项目名称为 websockets,语言框架为C++

project(websockets CXX)

指定C++标准版本为17

set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_CXX_STANDARD_REQUIRED ON)

指定项目编译时需要依赖 zlib 库

link_libraries(z)

设置 third_party 作为子模块,在编译项目时,会先编译子模块

add_subdirectory指定的目录下需要包括 CMakeLists.txt

add_subdirectory(third_party)

指定源码目录

aux_source_directory(src SRC_DIR)

指定项目需要引入的第三方头文件,注意中间分隔符是 空格,不是逗号

include_directories(“third_party/uWebSockets/src” “third_party/uWebSockets/uSockets/src”)

设置项目可执行文件,即将 SRC_DIR 指定的源码编译为以 项目名 命名的二进制文件

add_executable(${PROJECT_NAME} ${SRC_DIR})

添加第三方依赖编译输出的静态链接库,uwebsockets为库名称

target_link_libraries(${PROJECT_NAME} uwebsockets)


<br />`link_libraries(z)`是为了引入`zlib`包,否则在执行`make`时报错:
```bash
[100%] Linking CXX executable websockets
undef: _deflateEnd
undef: _inflateEnd
Undefined symbols for architecture x86_64:
  "_deflateEnd", referenced from:
      uWS::DeflationStream::~DeflationStream() in main.cc.o
  "_inflateEnd", referenced from:
      uWS::InflationStream::~InflationStream() in main.cc.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
  • 创建管理依赖的 third_party/CMakeLists.txt: ```cmake cmake_minimum_required(VERSION 3.16.2)

设置uWebSockets编译输出的静态链接库路径,注意,uWebSockets本身没有静态链接库,只有头文件,只有其依赖的uSockets才有静态链接库输出

注意:CMAKE_CURRENT_SOURCE_DIR指的是 当前 CMakeLists.txt文件所在的目录,并不是项目工程的跟目录。

set(UWEBSOCKETS_LIB ${CMAKE_CURRENT_SOURCE_DIR}/uWebSockets/uSockets/uSockets.a)

设置编译输出的头文件所在目录,需要提前在 third_party 目录下创建 include,否则编译会失败

set(LIB_HEADER ${CMAKE_CURRENT_SOURCE_DIR}/include)

设置构建uWebSockets的构建命令

OUTPUT指定输出的静态链接库的路径

COMMAND指定了构建命令,后面可以跟多个命令,LIBUS_NO_SSL=1为构建参数

WORKING_DIRECTORY指定命令执行的目录,即源码中Makefile目录所在

add_custom_command(OUTPUT ${UWEBSOCKETS_LIB} COMMAND LIBUS_NO_SSL=1 make WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/uWebSockets)

add_custom_target通过用户指定的指令来增加一个新的编译目标

add_custom_target(build_uwebsockets DEPENDS ${UWEBSOCKETS_LIB})

创建静态链接库,依赖上述自定义编译输出

注意: 在测试中发现,GLOBAL一定要设置,否则,在项目中找不到该静态库

add_library(uwebsockets STATIC IMPORTED GLOBAL) add_dependencies(uwebsockets build_uwebsockets)

指定该静态库的路径信息以及头文件信息

set_target_properties(uwebsockets PROPERTIES IMPORTED_LOCATION ${UWEBSOCKETS_LIB} INTERFACE_INCLUDE_DIRECTORIES ${LIB_HEADER})


> 其中 `add_custom_command` 和 `add_custom_target`可以合并为一条:

> ```cmake
add_custom_target(build_uwebsockets COMMAND ${CMAKE_MAKE_PROGRAM} 
    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/uWebSockets)


third_party目录结构:

.
├── CMakeLists.txt
├── include
└── uWebSockets
    ├── BroadcastingEchoServer
    ├── EchoServer
    ├── EchoServerThreaded
    ├── HelloWorld
    ├── HelloWorldThreaded
    ├── LICENSE
    ├── Makefile
    ├── README.md
    ├── benchmarks
    ├── examples
    ├── fuzzing
    ├── misc
    ├── src
    ├── tests
    └── uSockets

注意:由于 uWebSockets 不是cmake项目,只有Makefile文件,所以上述示例中介绍的是在cmake中直接引用Makefile项目。对于引用cmake项目,通过 add_subdirectory指令。

  • 构建
    # 在build目录下执行
    cmake ..
    make