Colderleo's blog Colderleo's blog
首页
Linux
C++
Python
前端
工具软件
mysql
索引
关于
GitHub (opens new window)

Colder Leo

热爱代码的打工人
首页
Linux
C++
Python
前端
工具软件
mysql
索引
关于
GitHub (opens new window)
  • bug定位的一些情形
  • c++性能调优,可能的情况
  • total-编程知识点集锦
  • hpc_common.hpp
  • memory order 内存模型
  • 类型推导之auto-template-decltype
  • 完美转发forward源码分析
  • 左值和右值,右值引用、重载 std-move,引用折叠
  • cmake用法
    • 语法
    • 非常好用的CMakeLists.txt模板
    • 先在build文件夹中生成项目文件, 然后执行编译
    • cmake中常用的变量
      • 上面添加了git版本相关的宏定义,程序中用法如下:
    • 指定编译器路径
    • 设置build type
    • find_package用法
    • windows生成动态链接库时导出接口
    • 添加boost库
  • alignas、alignof、sizeof实现内存对齐分配
  • 通过宏定义控制debug打印
  • 程序耗时性能测试
  • 线程池开源项目阅读
  • C++类中包含没有默认构造函数的成员
  • C++可变参数模板
  • C++属性继承 public protected private
  • C++智能指针
  • C++导出so的方法,以及extern C 注意事项
  • 四种spin lock
  • condition_variable和unique_lock
  • dpdk、kernel bypass
  • 智能网卡solarflare、Mellanox、X10等
  • 汇编寄存器和常见指令
  • c++ 类的静态成员变量未定义
  • C++获取类成员函数地址
  • preload示例
  • C++异常安全和RAII
  • C++11单例模式
  • C++歪门邪道
  • boost-program-option用法
  • c++17通过模板获取类成员的个数
  • 通过模板实现结构体成员拷贝-按成员名匹配
  • STL学习路径
  • boost库安装使用方法
  • C++文件读写
  • linux下socket通信demo,server和client
  • makefile写法
  • RxCpp
  • C++
gaoliu
2021-10-06
目录

cmake用法

# 语法

  • 官方文档:https://cmake.org/cmake/help/v3.14/ (opens new window)
  • 设置和使用变量 https://cloud.tencent.com/developer/ask/121477
set(MyString "Some Text")
set(MyStringWithVar "Some other Text: ${MyString}")
1
2

从cmake命令行传入变量 -D

CMakeLists.txt:

set(aa 123)
MESSAGE(aa= ${aa})
MESSAGE(bb= ${bb})
1
2
3

执行cmake

mkdir -p build
cd build
cmake .. -Dbb=456
1
2
3

输出:

aa=123
bb=456
1
2

# 非常好用的CMakeLists.txt模板

假设项目文件夹名为cmake_demo,其包含了test1、test2两个(即两个子文件夹)。

首先在根目录下创建CMakeLists.txt:

CMAKE_MINIMUM_REQUIRED (VERSION 3.0)
cmake_policy(VERSION 3.0)

# 创建项目,相当于vs中创建了cmake_demo.sln
PROJECT (cmake_demo)

# 添加C++版本支持
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)

# * CMAKE_SOURCE_DIR 是最上层CMakeLists.txt所在的文件夹 (注意:子目录中用了project()后,该变量就是porject所在的文件夹了!!!)
# * CMAKE_CURRENT_SOURCE_DIR 当前CMakeLists.txt所在的文件夹
# * CMAKE_CURRENT_BINARY_DIR 是执行cmake时会拷贝当前CMakeLists.txt到build里对应的文件夹
# * CMAKE_BINARY_DIR 就是执行cmake的文件夹,一般是build文件夹

# 假设CMakeLists.txt位于项目根目录`rootdir`,设置lib的生成目录为`rootdir/lib`, 
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/lib)
# 设置可执行文件的生成目录为build/../bin
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin)

# 设置编译flag,debug和release, 不指定CMAKE_BUILD_TYPE时,默认release版本
# 编译debug版本: cmake -D CMAKE_BUILD_TYPE=debug ..   或者在CMakeLists设置set(CMAKE_BUILD_TYPE "debug")
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread" )
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wformat=0 -Wno-sign-compare -Wno-unused-variable" )
set( CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS} -g -O0 -DDEBUG" )
set( CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS} -O2 -DNDEBUG" )


# (根据需要)添加宏定义 "_GNU_SOURCE" 和 "_DEFAULT_SOURCE"
add_definitions("-D_GNU_SOURCE -D_DEFAULT_SOURCE")


# 添加git版本相关的宏定义
# 程序中打印: printf("%s\n", "version: git_tag=" GIT_TAG ", commit_it=" COMMIT_ID);
execute_process(COMMAND git describe --tag --always --dirty
    OUTPUT_VARIABLE  GIT_TAG
    OUTPUT_STRIP_TRAILING_WHITESPACE
  )
message(git_tag = ${GIT_TAG})
execute_process(COMMAND git rev-parse HEAD
    OUTPUT_VARIABLE  COMMIT_ID
    OUTPUT_STRIP_TRAILING_WHITESPACE
  )
message(commit_id = ${COMMIT_ID})

add_definitions(-DGIT_TAG="${GIT_TAG}")
add_definitions(-DCOMMIT_ID="${COMMIT_ID}")


# 添加头文件搜索路径(.h) 当前文件夹和include
include_directories(. include)
# 添加库文件搜索路径(.lib, .a, .so)
link_directories(lib)

# 创建可执行文件some_test
add_executable(some_test some_test.cpp)

# 链接libdl.so 和 libm.so
target_link_libraries(some_test dl m)

#添加test1和test2两个子文件夹,windows下相当于vs中的sln添加了两个project。
add_subdirectory(test1)
add_subdirectory(test2)
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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64

test1文件夹下的CMakeLists.txt, 添加一个可执行文件test

# 将该目录下的所有源文件名加入到变量DIR_SRCS中。这是偷懒的做法,最好把具体文件列出来
aux_source_directory(. DIR_SRCS)

# 将上面得到的${DIR_SRCS}这些源文件作为source,编译出可执行文件test或者test.exe
add_executable(test1 ${DIR_SRCS})

# 如果需要链接外部的动态库文件,则在 add_executable 后面加,比如test1要链接到libtrace.so:
target_link_libraries(test1 trace)
1
2
3
4
5
6
7
8

test2文件夹下的CMakeLists.txt, 添加一个lib

# 子项目test2也可以用cmake中的project(test2) 最好不要用。
# 创建LIB_SOURCE_FILES变量,存储一些文件名
SET(LIB_SOURCE_FILES aaa.cpp bbb.cpp ccc.cpp)

# 生成库,地位等同于 add_executable().  SHARED表示生成动态库,linux下会生成libtest2.so, windows应该会生成test2.dll
add_library(test2 SHARED ${LIB_SOURCE_FILES})

# 复制生成的so文件到lib文件夹,路径可能有问题需要调整
IF (WIN32)
    MESSAGE(STATUS "###########################OS is windows###########################")
ELSEIF (UNIX)
    MESSAGE(STATUS "###########################OS is UNIX-like OS's.###########################")
    FILE(COPY libtest2.so DESTINATION lib)
ENDIF ()
1
2
3
4
5
6
7
8
9
10
11
12
13
14

这样在windows下编译出的vs2017工程为cmake_demo.sln,它包含了test1.vcxproj、test2.vcxproj两个project。

在linux下会生成Makefile, 可以用make编译。

# 先在build文件夹中生成项目文件, 然后执行编译

先创建build文件夹,用cmake在build文件夹下生成项目文件,再编译

cd cmake_demo
mkdir build
cd build
cmake ..
cmake --build .
1
2
3
4
5

对于linux,最后一句 cmake --build .等同于 make

对于windows,最后一句相当于是调用visual studio编译。

windows下生成工程时指定vs版本:

cmake .. -G "Visual Studio 15 2017 Win64"
cmake .. -G "Visual Studio 15 2017" -A x64
cmake .. -G "Visual Studio 16 2019 Win32"

cmake --build . --config Debug
1
2
3
4
5
  • -G是generator, -A是generator支持的platform
  • 参考cmake官方文档 https://cmake.org/cmake/help/v3.18/generator/Visual%20Studio%2015%202017.html
  • vs2017对应的-A可以加 Win32 x64 ARM ARM64

# cmake中常用的变量

https://gitlab.kitware.com/cmake/community/-/wikis/doc/cmake/Useful-Variables (opens new window)

  • CMAKE_SOURCE_DIR 是最上层CMakeLists.txt所在的文件夹 (用了project()可能是porject所在的文件夹了)
  • CMAKE_CURRENT_SOURCE_DIR 当前CMakeLists.txt所在的文件夹
  • CMAKE_BINARY_DIR 就是执行cmake的文件夹,一般是build文件夹
  • CMAKE_CURRENT_BINARY_DIR 是执行cmake时会拷贝当前CMakeLists.txt到build里对应的文件夹

# 上面添加了git版本相关的宏定义,程序中用法如下:

main.cpp:

#include<stdio.h>

#ifndef GIT_TAG
    #define GIT_TAG "no_git_tag"
#endif
#ifndef COMMIT_ID
    #define COMMIT_ID "no_commit_id"
#endif

int main() {
  // 下面写法的好处是 strings a.out | grep version 即可得到commit_id
  printf("%s\n", "version: git_tag=" GIT_TAG ", commit_it=" COMMIT_ID);
}
1
2
3
4
5
6
7
8
9
10
11
12
13

# 指定编译器路径

cmake -DCMAKE_CXX_COMPILER=/path/to/your/g++

# 设置build type

命令行中指定build type: cmake -DCMAKE_BUILD_TYPE=Debug ..

CMakeLists.txt中指定build type

set(CMAKE_BUILD_TYPE "Debug")
1

CMakeLists.txt中配置不同的编译选项

# 设置不同build type对应的编译选项
set(CMAKE_CXX_FLAGS_DEBUG   "-O0  -pthread -g " )
set(CMAKE_CXX_FLAGS_RELEASE "-O2  -pthread -DNDEBUG " ) 

set(CMAKE_C_FLAGS_DEBUG   "-O0 -pthread " ) 
set(CMAKE_C_FLAGS_RELEASE "-O2 -pthread -DNDEBUG " )

# 如果不用build type, 则不要对应的type
set(CMAKE_CXX_FLAGS   "-O2 -pthread" )
set(CMAKE_C_FLAGS_DEBUG   "-O2 -pthread" )
1
2
3
4
5
6
7
8
9
10

# find_package用法

https://github.com/BrightXiaoHan/CMakeTutorial/tree/master/FindPackage

通过Find<LibaryName>.cmake 模块,找到相关的路径。

每一个模块都会定义以下几个变量:

  • <LibaryName>_FOUND
  • <LibaryName>_INCLUDE_DIRS or<LibaryName>_INCLUDES
  • <LibaryName>_LIBRARYS or<LibaryName>_LIBRARIES

你可以通过<LibaryName>_FOUND 来判断模块是否被找到,如果没有找到,可给出提醒或者中止编译。

如果<LibaryName>_FOUND 为真,则加入头文件目录,链接库文件。

find_package(CURL)
add_executable(curltest curltest.cc)
if(CURL_FOUND)
    include_directories(clib PRIVATE ${CURL_INCLUDE_DIRS})
    target_link_libraries(curltest ${CURL_LIBRARYS})
else(CURL_FOUND)
    message(FATAL_ERROR ”CURL library not found”)
endif(CURL_FOUND)
1
2
3
4
5
6
7
8

# windows生成动态链接库时导出接口

  • 一种方法是自动导出所有的函数

    # 可选在windows上生成dll时导出所有的函数,这样不用写def之类的了。
    set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
    
    # 添加动态链接库文件 nanomsg.dll, nanomsg.so
    target_link_libraries(test nanomsg)
    
    1
    2
    3
    4
    5
  • 另一种是利用cmake的函数GENERATE_EXPORT_HEADER自动生成辅助头文件

    • github上的一个例子:https://github.com/gklingler/sharedLibsDemo (opens new window)
    • 另一个例子:https://blog.csdn.net/LaineGates/article/details/83899961 (opens new window)
  • 其他就是不用cmake,直接手写__declspec(dllexport)

# 添加boost库

set(BOOST_ROOT /usr/local/src/boost_1_76_0)
find_package(Boost REQUIRED)
include_directories(${Boost_INCLUDE_DIRS})
MESSAGE( STATUS "Boost_INCLUDE_DIRS = ${Boost_INCLUDE_DIRS}.")
1
2
3
4
编辑 (opens new window)
上次更新: 2023/05/07, 17:27:54
左值和右值,右值引用、重载 std-move,引用折叠
alignas、alignof、sizeof实现内存对齐分配

← 左值和右值,右值引用、重载 std-move,引用折叠 alignas、alignof、sizeof实现内存对齐分配→

最近更新
01
通过模板实现结构体成员拷贝-按成员名匹配
05-07
02
c++17通过模板获取类成员的个数
05-01
03
avx-sse切换惩罚
04-30
更多文章>
Theme by Vdoing | Copyright © 2019-2023 Colder Leo | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
×