首页 > 其他分享 >cmake 常用命令记录

cmake 常用命令记录

时间:2024-08-18 20:25:46浏览次数:8  
标签:cmake name 记录 测试 install 常用命令 test my

cmake 常用命令记录

命令

cmake_minimum_required

# 指定最低兼容版本
cmake_minimum_required(VERSION 3.22)

project

# 添加版本号和配置文件
project(step_base VERSION 1.1) 

当 project() 命令被调用时,CMake 在幕后定义了 step_base_VERSION_MAJOR 和 step_base_VERSION_MINOR

add_executable

# 指定源代码文件创建可执行文件
add_executable(exe_file_name xx.c)

set

# 指定 C++ 标准为 C11
set(CMAKE_CXX_STANDARD  11)
set(CMAKE_CXX_STANDARD_REQUIRED  True)

使用 set 命令自定义变量

set(MY_VAR "xxxx")

configure_file

configure_file 命令生成、替换配置文件

  • 创建一个配置文件模板 xx.h.in, 使用 configure_file() 传递的变量, 替换输入文件内容中的一些变量值 @VAR@,并输出文件 config.h
  • 在 configure_file 中,变量需要使用 ${} 语法来引用
  • 使用 @ONLY 参数表示只替换 @VAR@ 形式的变量,而不替换 $VAR 形式的变量(类 Unix shell 风格)
// config.h.in
#define MY_VAR @MY_VAR@
set(MY_VAR "Hello, World!") # 自定义变量
configure_file(config.h.in config.h @ONLY)

target_**

target_* 命令用于定义和管理目标(如库或可执行文件)的属性和依赖关系,PRIVATE、INTERFACE 和 PUBLIC 关键字指定了目标属性的可见性和传播方式。

  • PRIVATE: 属性(目录或库)只应用于目标自身,不传递给依赖项。
  • INTERFACE: 属性仅用于依赖项,不应用于目标自身。
  • PUBLIC: 属性应用于目标自身和依赖项。

比如项目一个子目录库,自身不需要使用该子目录的头文件,但项目里依赖该库的目标需要,那么子目录的 CMakeLists.txt 在添加路径时可以指定为 INTERFACE

# 将头文件目录添加到项目,只有 project_name 自身需要知道该目录
target_include_directories(project_name PRIVATE ${PROJECT_BINARY_DIR}) 

# 为项目链接库, project_name 自身和依赖于 project_name 的目标都依赖 mylib 库
target_link_libraries(project_name PUBLIC mylib) 

# 依赖于 MyFunc 的目标需要使用该子目录的头文件,但 MyFunc  本身不需要
add_library(MyFunc func.cc)
target_include_directories(MyFunc INTERFACE $(CMAKE_CURRENT_SOURCE_DIR))
# 添加编译定义,控制编译时条件,例如开启调试模式、启用特定的功能选项或者处理不同平台的兼容性问题
target_compile_definitions(target_name
    PUBLIC | PRIVATE | INTERFACE
    definition1 [definition2 ...]
)

option

# 增加配置项,默认打开
option(OPTION_1 "描述" ON) 
if (OPTION_1)
    # ...
endif()

message

message("path: ${CMAKE_INSTALL_PREFIX}")  # 打印信息

add_library

# 新增自定义库
add_library(MyFunc func.cc) 

add_subdirectory

# 增加编译子目录, 子目录有自己的CMakeLists.txt
add_subdirectory(xx/src) 

add_definitions

# 添加预定义宏, 影响整个 CMake 项目中的所有目标,建议用 target_compile_definitions
add_definitions(-DDEFINE_NAME)

install

cmake install, 指定如何安装生成的目标文件(可执行文件、库文件、头文件等)到指定的目录。

install(TARGETS <target> 
        [[ARCHIVE|LIBRARY|RUNTIME|OBJECTS|EXPORTED_TARGETS]
            [DESTINATION <dir>]
            [PERMISSIONS permissions...]
            [CONFIGURATIONS [Debug|Release|...]]
            [COMPONENT <component>]
            [OPTIONAL]
            [EXCLUDE_FROM_ALL]])
  • TARGETS :指定要安装的目标,可以是可执行文件、库文件或者其他 CMake 支持的目标类型。
  • ARCHIVE|LIBRARY|RUNTIME|OBJECTS|EXPORTED_TARGETS:可选项,用于指定安装目标的类型,例如静态库(ARCHIVE)、共享库(LIBRARY)、可执行文件(RUNTIME)、对象文件(OBJECTS)或者导出的目标(EXPORTED_TARGETS)。
  • DESTINATION < dir >:指定安装的目标目录。可以是绝对路径,也可以是相对于 CMAKE_INSTALL_PREFIX 的相对路径。
  • PERMISSIONS permissions…:可选项,指定安装文件的权限。
    CONFIGURATIONS [Debug|Release|…]:可选项,限定在特定的构建配置下安装。
  • COMPONENT :可选项,指定安装到哪个组件(Component),用于管理安装包中的逻辑组织。
  • OPTIONAL:可选项,指示安装目标不是必需的。
  • EXCLUDE_FROM_ALL:可选项,指示将安装目标排除在 make all 或 build 目标之外。
# 将名为 my_executable 的可执行文件安装到 bin 目录下。
install(TARGETS my_executable
        RUNTIME DESTINATION bin)

# 安装静态库和头文件, 将名为 my_library 的静态库安装到 lib 目录下,同时将头文件 my_header.h 安装到 include 目录下。
install(TARGETS my_library
        ARCHIVE DESTINATION lib
        LIBRARY DESTINATION lib
        RUNTIME DESTINATION bin)
install(FILES my_header.h DESTINATION include)

# 安装共享库并指定权限, 将名为 my_shared_library 的共享库安装到 lib 目录下,并设置文件权限为读取权限。
install(TARGETS my_shared_library
        LIBRARY DESTINATION lib
        PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ)

# 安装到特定的构建配置下, 只有在 Release 构建配置下才安装 my_executable。
# cmake --install . --config Release
install(TARGETS my_executable
        RUNTIME DESTINATION bin
        CONFIGURATIONS Release)

# 安装组件,将 my_library 安装到 lib 和 bin 目录下,并将其归为 libraries 组件。
install(TARGETS my_library
        ARCHIVE DESTINATION lib
        LIBRARY DESTINATION lib
        RUNTIME DESTINATION bin
        COMPONENT libraries)
  • CMake 使用 CMAKE_INSTALL_PREFIX 变量来确定安装目录的根路径,默认情况下,它被设置为 /usr/local。
  • 可以通过 -DCMAKE_INSTALL_PREFIX=/path/to/install 来自定义安装路径。
  • 如果使用 cmake --install 命令,可以通过 --prefix 参数覆盖安装前缀, cmake --install . --prefix “/home/myuser/installdir”
  • 执行安装,完成 install() 命令的配置后,在项目的根目录下执行以下命令来执行安装:
cmake --install .
cmake --install . --config Release
cmake --build . --target install --config Debug
cmake --install . --prefix "/home/myuser/installdir"

cpack

cpack 打包,可在编译完后将程序打包成 NSIS、ZIP、RPM、TGZ(tar.gz)、DEB 等格式的安装包

include(CPack) # 启用打包

set(CPACK_PACKAGE_NAME "pack_terst")
set(CPACK_PACKAGE_VERSION "1.0.0")
set(CPACK_PACKAGE_VENDOR "MyCompany")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Description of MyAwesomeSoftware")

 # 根据不同的生成器生成不同格式的安装包
set(CPACK_GENERATOR "ZIP;TGZ") 

set(CPACK_GENERATOR "DEB")
set(CPACK_DEBIAN_PACKAGE_DEPENDS "sshpass, can-utils") # 设置依赖
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Maintainer Name <[email protected]>")

install(TARGETS MyExecutable
        DESTINATION bin)

install(FILES README.md
        DESTINATION doc)

# 执行 cpack 命令开始打包
cpack

macro

在 CMake 中,宏类似于函数,用于封装重复使用的代码片段,以便在多个地方调用。它们可以接受参数,并执行一系列指令。宏通过 macro 和 endmacro 关键字定义,例如:

macro(print_message message)
    message(STATUS "Message: ${message}")
endmacro()

# 使用宏
print_message("Hello, world!")

string

string 提供了一些基本的字符串操作功能,用于处理变量中的文本。常见的字符串操作包括字符串连接、截取、替换等。以下是一些常见的字符串操作函数:

  • string(CONCAT varName string1 string2 …): 连接多个字符串。
  • string(SUBSTRING ): 获取子串。
  • string(REPLACE ): 替换字符串中的匹配项。
set(myString "Hello, World!")
string(SUBSTRING ${myString} 0 5 mySubString)
message(STATUS "Substring: ${mySubString}")

file

file 允许对文件进行多种操作,包括创建、复制、删除、读取等。常见的文件操作函数有:

  • file(WRITE ): 将内容写入文件。
  • file(READ ): 将文件内容读取到变量。
  • file(COPY … DESTINATION ): 复制文件到指定目录。
  • file(REMOVE …): 删除文件。
file(WRITE myfile.txt "Hello, World!")
file(READ myfile.txt content)
message(STATUS "File content: ${content}")

DEFINED

DEFINED 是一个条件判断关键字,用于检查一个变量是否已经被定义。它通常用于 if 语句的条件判断中。例如:

if(DEFINED myVar)
    message(STATUS "myVar is defined.")
else()
    message(STATUS "myVar is NOT defined.")
endif()

list

list 在 CMake 中是用来处理列表(数组)的关键字,CMake 中的列表是以分号分隔的字符串。常见的 list 操作包括:

  • list(LENGTH ): 获取列表中元素的个数。
  • list(GET ): 获取列表中指定索引位置的元素。
  • list(APPEND …): 将元素追加到列表末尾。
  • list(REMOVE_ITEM …): 从列表中移除指定的元素。
set(myList "apple;banana;cherry")
list(LENGTH myList len)
message(STATUS "Length of myList: ${len}")

list(GET myList 1 secondElement)
message(STATUS "Second element: ${secondElement}")

list(APPEND myList "orange")
message(STATUS "Updated list: ${myList}")

list(REMOVE_ITEM myList "banana")
message(STATUS "List after removal: ${myList}")

find_package

find_package 命令在 CMake 中用于查找和配置项目所需的外部依赖项

  • 格式:find_package(包名 [版本号] [EXACT] [QUIET] [MODULE] [REQUIRED] [COMPONENTS 组件名…])
  • 包名:需要查找的包的名称。CMake 会搜索提供该包的 Config.cmake 文件。
  • 版本号:可选。指定所需的包版本号。
  • EXACT:可选。要求精确的版本匹配。
  • QUIET:可选。如果找不到包,不显示警告。
  • MODULE:可选。强制 CMake 在 CMake 模块路径中搜索 .cmake 文件。
  • REQUIRED:可选。指定该包是必需的。如果找不到,CMake 将报错并停止配置。
  • COMPONENTS:可选。指定要使用的包的哪些组件。
find_package(Boost 1.70 REQUIRED COMPONENTS filesystem system)
if(Boost_FOUND)
    include_directories(${Boost_INCLUDE_DIRS})
    add_executable(my_program main.cpp)
    target_link_libraries(my_program ${Boost_LIBRARIES})
endif()

# find_package(Boost 1.70 REQUIRED COMPONENTS filesystem system) 查找 Boost 版本号为 1.70 或更高版本,需要 filesystem 和 system 组件。
# 如果找到 Boost(Boost_FOUND 为真),将 Boost 的包含目录添加到项目中(${Boost_INCLUDE_DIRS}),创建名为 my_program 的可执行文件,并链接 Boost 库(${Boost_LIBRARIES})。

特定包的查找模块:有些包可能没有提供 Config.cmake 文件,而是依赖于 CMake 的查找模块(例如 FindBoost.cmake)。可以通过设置 CMAKE_MODULE_PATH 变量来使用这些模块:

set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/modules/")
find_package(Boost REQUIRED COMPONENTS filesystem system)
# 这里,将 CMAKE_MODULE_PATH 设置为包含自定义查找模块的目录。

查找系统所有 cmake 模块

cmake --help-module-list |grep -E ^Find #

ctest

ctest 是 CMake 的测试驱动工具,用于执行和管理由 CMake 生成的测试。它可以自动执行测试,并生成有关测试结果的报告。

常用选项和参数

  • -R : 运行匹配正则表达式 的测试。
  • -E : 排除匹配正则表达式 的测试。
  • -j : 指定并行执行测试的数量。
  • -V: 显示详细的测试输出信息。
  • -C : 指定配置(如 Debug 或 Release)来运行测试。
# 运行所有测试:
cd build_directory
ctest
# 这将运行所有由 CMake 生成的测试,并显示测试执行的结果。

# 运行特定测试,可以通过 -R 选项来指定运行匹配特定正则表达式的测试名称。例如,要运行名称包含 "test_" 的测试:
ctest -R test_

# 显示更多信息,使用 -V 选项可以显示详细的测试输出信息,包括每个测试的输出和详细结果:
ctest -V

# 运行并行测试,如果系统支持并行执行测试,可以使用 -j 选项指定并行测试的数量:
ctest -j 4  # 使用4个线程并行执行测试
find_package(GTest REQUIRED)

enable_testing()  # 启用测试
add_executable(my_gtest ctest/gtest.cc)
target_link_libraries(my_gtest PRIVATE MyFunc GTest::Main)

# 注册测试
add_test(NAME MyGTests COMMAND my_gtest)

ctest  # 开始测试

构建类型

  • Release:
    • 优化编译:通常会启用各种编译器优化选项,以提高程序的执行效率和速度。
    • 关闭调试信息:生成的可执行文件会减少调试信息,从而减少文件大小。
    • 不包含断言:一些库和代码可能会在 Debug 模式下包含断言(assertions),但在 Release 模式下这些通常会被禁用,以避免运行时性能损失。
  • Debug:用于开发阶段,包含调试信息,并禁用优化,以方便调试和追踪问题。
  • RelWithDebInfo:结合了 Release 和 Debug 特性,生成带有调试信息的优化代码,用于开发和调试。
  • MinSizeRel:优化产物的大小,以最小化可执行文件的体积。
# 设置默认的构建类型为 Release
set(CMAKE_BUILD_TYPE "Release")

扩展

gtest

Google Test 提供了几种主要的测试宏,它们用于定义和运行测试用例。

// 定义一个测试用例,其中 test_case_name 是测试案例的名称,test_name 是具体的测试用例名称。
TEST(test_case_name, test_name):

TEST(MathTest, Addition) {
    // Test body
}
// 定义一个基于测试夹具(Fixture)的测试用例。测试夹具允许在多个测试用例之间共享初始化和清理代码。test_fixture_name 是测试夹具类的名称,test_name 是具体的测试用例名称。
TEST_F(test_fixture_name, test_name):

class MathTest : public ::testing::Test {
protected:
    void SetUp() override {
        // 初始化代码
    }

    void TearDown() override {
        // 清理代码
    }
};

TEST_F(MathTest, Addition) {
    // Test body
}
// 用于测试模板类型的测试宏。test_case_name 是测试案例名称,test_name 是具体的测试用例名称。
TYPED_TEST(test_case_name, test_name):

cpp
template<typename T>
class MathTest : public ::testing::Test {
    // Test body
};

using MyTypes = ::testing::Types<int, float>;
TYPED_TEST_SUITE(MathTest, MyTypes);

TYPED_TEST(MathTest, Addition) {
    // Test body
}
TYPED_TEST_P(test_case_name, test_name):

用于测试参数化测试夹具(Parameterized Fixture)。test_case_name 是测试案例名称,test_name 是具体的测试用例名称。例如:

class MathTest : public ::testing::TestWithParam<int> {
    // Test body
};

INSTANTIATE_TEST_SUITE_P(SimpleValues, MathTest, ::testing::Values(1, 2, 3));

TEST_P(MathTest, Addition) {
    // Test body
}
// 用于在测试中检查条件的宏,例如 ASSERT_TRUE, ASSERT_FALSE, EXPECT_EQ, EXPECT_NE, ASSERT_GT, EXPECT_LT 等等。这些宏用来验证测试中的实际值是否与预期值一致。

ASSERT_TRUE(expression); // 断言 expression 必须为真,否则测试失败
ASSERT_FALSE(expression); // 断言 expression 必须为假,否则测试失败
ASSERT_GT(val1, val2); // 断言 val1 大于 val2,否则测试失败。
ASSERT_LT(val1, val2); // 断言 val1 小于 val2,否则测试失败。
...

EXPECT_EQ(expected, actual); // 比较两个值是否相等
EXPECT_NE(expected, actual); // 比较两个值是否不相等
EXPECT_LT(val1, val2); // 比较 val1 小于 val2

// ASSERT_的宏若失败就不会继续测试,EXPECT_的宏失败了还能继续测试

标签:cmake,name,记录,测试,install,常用命令,test,my
From: https://blog.csdn.net/weixin_49599385/article/details/141286988

相关文章

  • (nice!!!)LeetCode 552. 学生出勤记录 II(动态规划dp递归版、记忆化dfs)
    题目:552.学生出勤记录II思路:记忆化搜索dfs,细节看注释classSolution{public:constintmod=1e9+7;//状态f[u][a][b]表示:在选择第u个位置前,缺勤次数为a次,且当前连续迟到次数为b次时,可以得到的合法出勤次数intf[100010][5][5];intdfs(intu,int......
  • Leetcode每日一题 20240818 551.学生出勤记录Ⅰ
    题目描述给你一个字符串s表示一个学生的出勤记录,其中的每个字符用来标记当天的出勤情况(缺勤、迟到、到场)。记录中只含下面三种字符:‘A’:Absent,缺勤‘L’:Late,迟到‘P’:Present,到场如果学生能够同时满足下面两个条件,则可以获得出勤奖励:按总出勤计,学生缺勤(‘A’)严......
  • unity中的问题记录(角色的控制)
    unity中的默认访问修饰符与c#相同,class不写public,则默认同一程序集(internal)中可以访问,在unity中,程序集表现为项目,即同一项目可以互相访问类里的成员默认与c#同样相同,都是private在C#中,将字段和方法都设为私有(private)并使用static修饰符并不是“多此一举”,而是根据具体的设......
  • vi 常用命令
    原文: https://www.cnblogs.com/qianxudetianxia/archive/2012/07/07/2578361.html1.移动指令  (1).hjkl,方向键,记忆技巧:左右方向的是最左边和最右边的,j向下打了个勾,所以是向下键,剩下的k就是向上的键了。  (2).b,before,上一个单词(词首)      w,w......
  • Unity项目优化记录
    背景:测试反馈项目组游戏存在内存泄露,来找到中台这边协调排查。好家伙,跑了两次看了内存快照,再看资源组织和管理方式,存在的问题确实比较多。1、修复内存泄露:结算界面由于资源引用丢失导致整个面板不会被释放,每次泄漏50MB左右的内存。2、改进资源卸载,通过引用计数管理资源,当引用......
  • 551.学生出勤记录Ⅰ
    1.题目描述给你一个字符串 s 表示一个学生的出勤记录,其中的每个字符用来标记当天的出勤情况(缺勤、迟到、到场)。记录中只含下面三种字符:'A':Absent,缺勤'L':Late,迟到'P':Present,到场如果学生能够 同时 满足下面两个条件,则可以获得出勤奖励:按 总出勤 计,学生缺勤('A')严格 ......
  • ubuntu常用命令
    安装deb文件命令sudodpkg-i文件名.deb 查找文件find-nametest_detectors_regression.impl.hppsudofind/-name"clion.sh"sudofind/-name"clion.png" ubuntu去掉文件夹的锁 问题描述:配置环境过程中莫名其妙文件带锁,不能读写甚至不能删除操作。遇到过不少......
  • 实习记录day05
    前言:周日了,明天又要上班了orz上午今天博客写的格外的早,因为今天确实比较闲。昨天的内容commit之后,大哥让我读一下已有模块的业务代码(准备copy他们写一个大模型的接口来实现新模块)。大概读了读梳理了一下流程,无非就是入参校验,调用接口返回内容。看得出来原来打算用websocket的流......
  • 正点原子领航者ZYNQ7020开发板 GMAC1 EMIO调试记录
    ZYNQ7020GMAC1EMIO裸机功能调试ZYNQ嵌入式系统开发流程1:创建Vivado工程2:创建ProcessSystem3:生成顶层HDL添加EMIO引脚约束4:生成Bitstream并导出到SDK启动SDK5:创建LWIPEcho测试工程6:编译工程并在开发板上进行测试LinuxKernel中GMIITORGMIIIP的......
  • 算法刷题记录 八十五【图论的广度优先搜索理论基础】
    前言图论章节第2篇。第1篇:记录八十二【图论理论基础及深度优先搜索算法】;本文:记录八十五【图论的广度优先搜索理论基础】一、广度优先搜索理论基础广度优先搜索理论基础参考链接1.1知识点框架1.2模拟广度搜索的过程在有向图中,以下图为例,如何进行广度优先搜索......