数据库检索网站建设,免费做店招哪个网站好,wordpress 底部代码,淘宝客导购网站模板个人博客:Sekyoro的博客小屋 个人网站:Proanimer的个人网站 最近常常使用cmake构建c项目有感,从创建项目到打包发布总结一下需要注意的事情.
项目组织方式
具体的项目组织方式因人而异,这里推荐一种,在src目录中创建模块目录,再在include目录中常见对应的同名目录包含头文件,…个人博客:Sekyoro的博客小屋 个人网站:Proanimer的个人网站 最近常常使用cmake构建c项目有感,从创建项目到打包发布总结一下需要注意的事情.
项目组织方式
具体的项目组织方式因人而异,这里推荐一种,在src目录中创建模块目录,再在include目录中常见对应的同名目录包含头文件,可执行程序的源代码或者最终生成库的源代码可以放在app目录中.
比如我看的一个项目组织如图 在src目录中包括demo,view,assignment三个项目,对应include目录相同,或者在生成程序的目录中包含头文件而不另外放include中. 此外也有src目录中放所有的源代码文件,include目录分别放每个模块对应的头文件,相对来说更方便.
针对第一种组织方式,cmake会在src目录添加模块
add_subdirectory(view)
add_subdirectory(demo)
add_subdirectory(assignments)每个模块再单独写cmake,甚至可以单独写project,这样方便模块化,可以看到下面利用不同的${PROJECT_NAME}设置库生成位置
project(demo_hello_world)
file(GLOB source${CMAKE_CURRENT_SOURCE_DIR}/demo_hello_world.cpp
)
add_executable(${PROJECT_NAME} ${source})
set_target_properties(${PROJECT_NAME} PROPERTIES DEBUG_POSTFIX _dRUNTIME_OUTPUT_DIRECTORY ${BINARY_DIR}LIBRARY_OUTPUT_DIRECTORY ${LIBRARY_DIR}ARCHIVE_OUTPUT_DIRECTORY ${LIBRARY_DIR})
target_link_libraries(${PROJECT_NAME} PUBLIC view) project(demo)
file(GLOB source${CMAKE_CURRENT_SOURCE_DIR}/demo.cpp${CMAKE_CURRENT_SOURCE_DIR}/window_demo.cpp${CMAKE_CURRENT_SOURCE_DIR}/window_demo.h
)
add_executable(${PROJECT_NAME} ${source})
set_target_properties(${PROJECT_NAME} PROPERTIES DEBUG_POSTFIX _dRUNTIME_OUTPUT_DIRECTORY ${BINARY_DIR}LIBRARY_OUTPUT_DIRECTORY ${LIBRARY_DIR}ARCHIVE_OUTPUT_DIRECTORY ${LIBRARY_DIR})
target_link_libraries(${PROJECT_NAME} PUBLIC view) 比较来看,如果给src目录中放所有的cpp源文件,那不好给模块分离,因为一个项目中一般包括一个生成可执行程序或最终库的源代码,一起一堆供这个目标依赖的模块,这些模块如果能单独提出来更好,也就是说这些模板的cpp代码如果放在分别的模块目录下虽然更麻烦但更好. 此外将main程序放在app目录中也更加清晰.
依赖图与文档生成
查看目标的依赖
下载graphviz
cd build cmake .. --graphvizgraph.dot dot -Tpng graph.dot -o graphImage.png使用Doxygen生成文档
需要按照规定格式撰写注释,根据注释生成文档Doxygen: Documenting the code.
doxygen支持许多格式注释,下面列举三种
/*** ... text ...*//** Brief description which ends at this dot. Details follow* here.*//*!* ... text ...*//*! \brief Brief description.* Brief description continued.** Detailed description starts here.*//*!... text ...
*/注释介绍file文件说明author作者的信息brief用于class 或function的批注中后面为class 或function的简易说明param参数介绍return函数传回值的说明 Doxygen 还需要一个 Doxyfile其包含文档生成的所有参数比如输出格式、排除的文件模式、 项目名称等。因为配置参数太多开始配置 Doxygen 可能会让人望而生畏但 CMake 可以自动生 成 Doxyfile。 doxygen -g # 生成doxyfile配置doxygenfile然后运行doxygen生成.
当然更好的方式是结合cmake,首先找到doxygen程序,然后设置需要的选项Doxygen: Configuration,最后生成文旦. 可以使用add_custom_target或者doxygen_add_docs(推荐)[FindDoxygen — CMake 3.30.3 Documentation](htt在这里插入图片描述 ps://cmake.org/cmake/help/latest/module/FindDoxygen.html)
find_package(Doxygen)
if (DOXYGEN_FOUND)
set(DOXYGEN_OUTPUT_DIRECTORY${CMAKE_CURRENT_BINARY_DIR}/docs)
set(DOXYGEN_GENERATE_HTML YES)
set(DOXYGEN_GENERATE_MAN YES)
set(DOXYGEN_MARKDOWN_SUPPORT YES)
set(DOXYGEN_AUTOLINK_SUPPORT YES)
set(DOXYGEN_HAVE_DOT YES)
set(DOXYGEN_COLLABORATION_GRAPH YES)
set(DOXYGEN_CLASS_GRAPH YES)
set(DOXYGEN_UML_LOOK YES)
set(DOXYGEN_DOT_UML_DETAILS YES)
set(DOXYGEN_DOT_WRAP_THRESHOLD 100)
set(DOXYGEN_CALL_GRAPH YES)
set(DOXYGEN_QUIET YES)
#add_custom_target(docs ${DOXYGEN_EXECUTABLE} WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/docs))
doxygen_add_docs(
docs
${CMAKE_CURRENT_LIST_DIR}
ALL
COMMENT Generating documentation for myproject
)
endif()
doxygen_add_docs(targetName [filesOrDirs…] [ALL] [USE_STAMP_FILE] [WORKING_DIRECTORY dir] [COMMENT comment] [CONFIG_FILE filename]) 第一个参数 targetName 是文档目标的名称,该函数将生成一个名为 targetName 的自定义目 标。这个目标将触发 Doxygen,并在构建时使用代码创建文档。filesOrDirs包含想要从文档生成的代码的文件或目录的列表。ALL 参数用于使 CMake 的 ALL 元目标依赖于 doxygen_add_docs(…) 创建的文档目标因此在构建 ALL 元目标时自动生成文档。WORKING_DIRECTORY默认是 CMAKE_CURRENT_SOURCE_DIR## 代码检查和格式化工具这部分工作其实完全可以交由IDE提供,不需要在cmake build时使用的,但为了保持兼容,这里简略写一点可以考虑使用clang-tidy和clang-format工具,在cmake文件中cmake
cmake_minimum_required(VERSION 3.28)
project(my-project)add_executable(my-app main.c)file(GLOB_RECURSE ALL_SOURCE_FILES*.c *.h *.cpp *.hpp *.cxx *.hxx *.cc *.hh *.cppm *.ipp *.ixx)
add_custom_target(formatCOMMAND clang-format-i${ALL_SOURCE_FILES}
)对于clang-tidy完全可以在.clang-tidy文件中设置并通过clangd进行检查Enabling clang-tidy checks in clangd - Clang Frontend / clangd - LLVM Discussion Forums
Configuration (llvm.org)
# .clangd
Diagnostics:ClangTidy:CheckOptions:readability-identifier-naming.VariableCase: CamelCase此外还可以设置编译器编译链接选项检查内存和初始化等错误
function (add_sanitier target)
message(STATUS Adding sanitizer to target ${target})if (CMAKE_CXX_COMPILER_ID MATCHES CLANG OR CMAKE_CXX_COMPILER_ID MATCHES GNU)add_compile_options(-fno-omit-frame-pointer)add_link_options(-fno-omit-frame-pointer)target_compile_options(${target} PRIVATE -fsanitizeaddress)target_link_libraries(${target} PRIVATE -fsanitizeaddress)target_compile_options(${target} PRIVATE -fsanitizeundefined)target_link_libraries(${target} PRIVATE -fsanitizeundefined)elseif (CMAKE_CXX_COMPILER_ID STREQUAL MSVC)target_compile_definitions(${target} PRIVATE /fsanitizeaddress)
else()message(WARNING Sanitier is not supported for ${CMAKE_CXX_COMPILER_ID})endif()
endfunction()除此之外,可以使用valgrind等工具动态debug查找内存问题.
进行测试
CTest
[Testing With CMake and CTest — Mastering CMake](https://cmake.org/cmake/help/book/mastering-cmake/chapter/Testing With CMake and CTest.html)
include(CTest)
add_executable(TestInstantiator TestInstantiator.cxx)
target_link_libraries(TestInstantiator vtkCommon)
add_test(NAME TestInstantiatorCOMMAND TestInstantiator)make testCTest 模块通常应该只包含在项目的顶层 CMakeLists.txt 中。自从 CMake 版本 3.21 以 来PROJECT_IS_TOP_LEVEL 可以用来测试当前的 CMakeLists.txt 是否为顶层文件。
对于项目的顶层目录和使用 ExternalProject 添加的项目顶层目录此变量为 True。对于使用 add_subdirectory 或 FetchContent 添加的目录该值为 False
project(CMakeBestPractice)
...
if(PROJECT_IS_TOP_LEVEL)
include(CTest)
endif()add_test(NAME name COMMAND command [arg...]
[CONFIGURATIONS config...]
[WORKING_DIRECTORY dir]
[COMMAND_EXPAND_LISTS])ctest --test-dir build_dir
cmake --build build_dir --target test # 注意这里目标就是test,而不是add_test中添加的NAME
ctest --build-and-test source_dir build_dir可以设置ctest多个lable,然后通过过滤查看对应结果
add_test(NAME labeled_test_1 COMMAND someTest)
set_tests_properties(labeled_test PROPERTIES LABELS example)
add_test(NAME labeled_test_2 COMMAND anotherTest)
set_tests_properties(labeled_test_2 PROPERTIES LABELS will_fail )
add_test(NAME labeled_test_3 COMMAND YetAnotherText)
set_tests_properties(labeled_test_3 PROPERTIES LABELS example;will_fail)ctest -L example|will_fail-L进行过滤
ctest -I [Start,End,Stride,test#,test#,...|Test file] 通过 Start、End 和 Stride可以指定要执行的测试的范围。这三个数字是与显式测试数字 test# 相结合的范围或传递包含参数的文件
处理大量测试
create_test_sourcelist (SourceListNameDriverNametest1 test2 test3EXTRA_INCLUDE include.hFUNCTION function)注意ctest并不提供方便测试的方法,可以使用第三方库提供的REQUIRE等方法 使用include(Ctest)和add_test可使得可以方便使用ctest命令进行测试
比如
cmake --build build
cd build ctest使用Catch2
catchorg/Catch2: A modern, C±native, test framework for unit-tests, TDD and BDD - using C14, C17 and later (C11 support is in v2.x branch, and C03 on the Catch1.x branch) (github.com)
创建tests目录,编写cmake文件
if(ENABLE_TESTING)set(TEST_MAIN unit_tests)set(TEST_SOURCES main.cpp)set(TEST_INCLUDES ./)add_executable(${TEST_MAIN} ${TEST_SOURCES})target_include_directories(${TEST_MAIN} PUBLIC ${TEST_INCLUDES})target_link_libraries(${TEST_MAIN} PUBLIC ${LIBRARY_NAME} Catch2::Catch2WithMain)
endif()自动发现测试
cmake_minimum_required(VERSION 3.5)
project(baz LANGUAGES CXX VERSION 0.0.1)
find_package(Catch2 REQUIRED)
add_executable(tests test.cpp)
target_link_libraries(tests PRIVATE Catch2::Catch2)
# list(APPEND CMAKE_MODULE_PATH ${catch2_SOURCE_DIR}/extras) # use FetchContent
include(CTest)
include(Catch)
catch_discover_tests(tests)使用GoogleTest
cmake_minimum_required(VERSION 3.14)
project(my_project)# GoogleTest requires at least C14
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)include(FetchContent)
FetchContent_Declare(googletestURL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip
)
# For Windows: Prevent overriding the parent projects compiler/linker settings
set(gtest_force_shared_crt ON CACHE BOOL FORCE)
FetchContent_MakeAvailable(googletest)enable_testing()add_executable(hello_test hello_test.cpp)
target_link_libraries(hello_test GTest::gtest_main)include(GoogleTest)
gtest_discover_tests(hello_test) # 自动发现测试代码覆盖检查
检查测试了哪些代码并生成覆盖率报告,使用Gcov生成覆盖率信息,使用覆盖分析程序,如 Gcovr 或 LCOVn分析覆盖文件并生成报告
小结
CTestCatch2即可
第三方库管理
使用FetchContent下载库
include(FetchContent)
FetchContent_Declare(nlohmann_json
GIT_REPOSITORY https://github.com/nlohmann/json
GIT_TAG v3.11.2
GIT_SHALLOW TRUE)
FetchContent_Makeavailable(nlohmann_json)需要项目是cmake项目
使用vcpkg等包管理工具下载库
包管理器与xmake介绍
{version: 6,configurePresets: [{name: my-preset,binaryDir: ${sourceDir}/build,toolchainFile: $env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake}]
}cmake_minimum_required(VERSION 3.28)
project(my-project)
find_package(ftxui REQUIRED)
add_executable(my-app main.cpp)
target_compile_features(my-app PRIVATE cxx_std_20)
target_link_libraries(my-app PRIVATE ftxui::dom ftxui::screen ftxui::component)vcpkg install
cmake --preset my-preset
cmake --build build
./build/my-app使用Conan
简单介绍一下使用流程
首先定义conanfile.txt和conan profile
[requires]
zlib/1.2.11[generators]
CMakeDeps
CMakeToolchainconan profile detect --force然后执行conan insatll会生成conan_toolchain.cmake
conan install . --output-folderbuild --buildmissing再在cmake中使用
cd build
cmake .. -G Visual Studio 15 2017 -DCMAKE_TOOLCHAIN_FILEconan_toolchain.cmake借助git submodule下载库
Git - git-submodule Documentation
Git submodule | Atlassian
git submodule add https://bitbucket.org/jaredw/awesomelibrary # 添加子模块(当前新版本git也会下载对应模块)
git submodule init //初始化子模块 (根据.gitmodules更新信息)
git submodule update //更新子模块
git submodule update --init --recursive # 更新映射关系并递归下载模块使用git submodule add之后会创建**.gitmodules**文件并写入相关信息,包括子模块path和url,其中path是安装路径,因此我们可以借助修改path,使得git update --init安装子模块时安装到3rd_party或vendor目录便于管理,比如
[submodule glfw]
path third_party/glfw
url https://github.com/glfw/glfw.git修改.gitmodules 文件中对应模块的名字或者path,然后使用git submodule sync进行更新.
git submodule sync --recursive
git submodule update --init --recursive此外还会在.git/config和.git/modules中添加子模块信息
update的作用是根据项目的配置信息,拉取更新子模块中的代码,也可以使用git clone --recurse-submodules直接下载子模块
卸载子模块
git submodule deinit project-sub # 在.gitmodules中对应的模块名
git rm project-sub # 删除模块目录与.git/config,.git/modules信息总结来说,可以使用第三方管理工具,下载链接非常方便. 对于自己写的一些库或者没有cmake的项目可以使用vendor/3rd_party方式,放在一个单独目录,如果是源代码,添加源文件和头文件,生成库,cmake如下
# glad
set(glad_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/glad CACHE STRING )
file(GLOB source${glad_SOURCE_DIR}/src/*.c
)
add_library(glad ${source})
target_include_directories(gladPUBLIC ${glad_SOURCE_DIR}/include
)
set_target_properties(glad PROPERTIES FOLDER third_party)如果是已经编译好的库,使用add_library(xxx SHARED IMPORTED)并设置库文件位置
add_library(glad SHARED IMPORTED)
set_target_properties(glad PROPERTIES IMPORTED_LOCATION /path/to/glad/library)
set_target_properties(glad PROPERTIES IMPORTED_IMPLIB /path/to/glad/library) # 针对windowsset_target_properties(glad PROPERTIES FOLDER third_party)IMPORTED_IMPLIB:用于指定导入库的导入库文件import library file。在 Windows 上通常用于 .lib 文件。这个属性通常用于静态链接的导入库 小结
vcpkg,conan的逻辑是使用一个文件声明项目信息和依赖,然后在cmake中添加toolchainfile用于下载对应的包,而CPM和FetchContent直接在cmake中声明需要添加的包.
优先使用第三方包管理工具,因为相比FetchContent提供更多功能,如果第三方库不是cmake项目,使用git submodule方式,下载到某个文件夹编译源代码、链接库
项目打包、安装与分发
install
安装target
具体来说install(TARGETS …)会安装生成的的东西,不会安装头文件或者项目中的json、txt等读取文件.
install(TARGETS target... [...])这里最需要注意的就是动态库不包括windows上的dll.
默认安装路径如下,安装目录在Unix上usr/local,Windows是C:/program files,前缀通过cmake --prefix或 CMAKE_INSTALL_PREFIX指定 install(TARGETS…) 如果 包 含 EXPORT 参 数, 用 于 从 给 定 的 install(…) 目 标 创 建 一 个 导 出 名 称,可以使用此导出名称导出这些目标
安装文件 安装的东西并不总是目标输出构件的一部分。它们可能是目标的运行时依赖项例如图片、源文件、脚本和配置文件 install (
DIRECTORY include/
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)install(FILES…) 指令接受一个或多个文件作为参数TYPE 和DESTINATION 用于确定指定文件的目标目录。TYPE 用于指示哪些文件将使用该文件类型的默认 路径作为安装目录
install(FILES ${CMAKE_CURRENT_LIST_DIR}/greeter_content
DESTINATION ${CMAKE_INSTALL_BINDIR})
install(PROGRAMS ${CMAKE_CURRENT_LIST_DIR}/greeter.py
DESTINATION ${CMAKE_INSTALL_BINDIR} RENAME chapter4_greeter)
安装目录
install(DIRECTORY dir1 dir2 dir3 TYPE LOCALSTATE)install(DIRECTORY dir2 DESTINATION ${CMAKE_INSTALL_
LOCALSTATEDIR} FILES_MATCHING PATTERN *.hpp
EXCLUDE PATTERN *)
可以指定匹配文件和排除文件模式.
config-file
当别人安装了你的库,也要方便使用.为了让其他用户使用find_package找到我们的包,需要config-file.
包配置文件Config.cmake设置如下
include(GNUInstallDirs) # 便于获取安装路径变量
set(FOO_INCLUDE_DIRS ${PREFIX}/include/foo-1.2)
set(FOO_LIBRARIES ${PREFIX}/lib/foo-1.2/libfoo.a)搜索包时,find_package(…) 会查找 /cmake 目录,所以包配置文件放在/cmake中.
# top level cmake
include(GNUInstallDirs)
set(project_INSTALL_CMAKEDIR cmake CACHE PATH
Installation directory for config-file package cmake files) # 于设置 config-file 打包配置文件的安装目录target_include_directories(ch4_ex05_lib PUBLIC
$BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include
)
target_compile_features(ch4_ex05_lib PUBLIC cxx_std_11)使用$BUILD_INTERFACE设置头文件目录,因为在安装时
install(TARGETS ex05_lib
EXPORT cex05_lib_export
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)
install (
DIRECTORY ${PROJECT_SOURCE_DIR}/include/
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)使用install(EXPORT)得到xxConfig.cmake文件
install(EXPORT ex05_lib_export
FILE ex05_lib-config.cmake
NAMESPACE ex05_lib::
DESTINATION ${project_INSTALL_CMAKEDIR}
)要实现对 find_package(…) 的完全支持还需要获取xxxConfig-version.cmake 文件
include(CMakePackageConfigHelpers)
write_basic_package_version_file(
ex05_lib-config-version.cmake
# Package compatibility strategy. SameMajorVersion is
essentially semantic versioning.
COMPATIBILITY SameMajorVersion # 与主版本号相同即可
)
install(FILES
${CMAKE_CURRENT_BINARY_DIR}/ex05_lib-config-version.
cmake
DESTINATION ${project_INSTALL_CMAKEDIR}
)cmake –S . -B ./build
cmake --build ./build
cmake --install ./build --prefix /3rdparty安装包并使用find_package使用包
if(NOT PROJECT_IS_TOP_LEVEL)
message(FATAL_ERROR The chapter-4, ex05_consumer project is
intended to be a standalone, top-level project. Do not
include this directory.)
endif()
find_package(ex05_lib 1 CONFIG REQUIRED)
add_executable(ex05_consumer src/main.cpp)
target_compile_features(ex05_consumer PRIVATE cxx_std_11)
target_link_libraries(ex05_consumer ex05_lib::ch4_ex05_
lib)CPack
[Packaging With CPack — Mastering CMake](https://cmake.org/cmake/help/book/mastering-cmake/chapter/Packaging With CPack.html)
cpack包含多种生成器生成包
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
常用cpack变量 cmake_minimum_required(VERSION 3.21)
project(
ch4_ex06_pack
VERSION 1.0
DESCRIPTION Chapter 4 Example 06, Packaging with CPack
LANGUAGES CXX)
if(NOT PROJECT_IS_TOP_LEVEL)
message(FATAL_ERROR The chapter-4, ex06_pack project is
intended to be a standalone, top-level project.
Do not include this directory.)
endif()
add_subdirectory(executable)
add_subdirectory(library)
set(CPACK_PACKAGE_VENDOR CTT Authors) # 作者
set(CPACK_GENERATOR DEB;RPM;TBZ2) # 包管理器
set(CPACK_THREADS 0)
set(CPACK_DEBIAN_PACKAGE_MAINTAINER CTT Authors)
include(CPack)CPACK_PACKAGE_NAME 和 CPACK_PACKAGE_VERSION_* 默认从顶层项目名称和版本中获取
cmake –S . -B build/项目配置后,生成CpackConfig.cmake 和 CpackConfigSource.cmake文件到build/CPack*中,使用cpack得到最终包
cmake --build build/
cpack --config build/CPackConfig.cmake -B build/注意设置generator时,其中每个都需要符合条件. 比如nsis需要安装对应的软件,否则设置generator包括它时会直接报错 经常遗忘的指令
add_custom_target(Name [ALL] [command1 [args1...]]
[COMMAND command2 [args2...] ...]
[DEPENDS depend depend depend ... ]
[BYPRODUCTS [files...]]
[WORKING_DIRECTORY dir]
[COMMENT comment]
[JOB_POOL job_pool]
[VERBATIM] [USES_TERMINAL]
[COMMAND_EXPAND_LISTS]
[SOURCES src1 [src2...]])add_custom_target 的核心是通过 COMMAND 选项传递的命令列表。虽然第一个命令可 以不带这个选项,但最好在 add_custom_target 中添加 COMMAND 选项。
默认情况下,定制目标只在显式请求时执行,除非指定了 ALL 选项。
自定义目标总认为是过时的因此总是运行指 定的命令而不管是否会反复产生相同的结果。
使用 DEPENDS 关键字可以使定制目标依赖于使用 add_custom_command 或其他目标定义的定制命令的文件和输出。
要使自定义目标依赖于另 一个目标可以使用 add_dependencies。若使用自定义目标创建文件可以在 BYPRODUCTS 选项下列出这些文件。
列出的文件都将使用 GENERATED 属性标记CMake 使用该属性来确定构建是否过期并找出需要清理的文件但使用 add_custom_command 创建文件的任务可能更适 合。
通常命令在当前二进制目录中执行该目录在 CMAKE_CURRENT_BINARY_DIRECTORY 缓存变量中。若需要修改这可以通过 WORKING_DIRECTORY 选项来更改。该选项可以是绝对 路径也可以是相对路径 (当前二进制目录的相对路径)。
add_custom_command(TARGET target
PRE_BUILD | PRE_LINK | POST_BUILD
COMMAND command1 [ARGS] [args1...]
[COMMAND command2 [ARGS] [args2...] ...]
[BYPRODUCTS [files...]]
[WORKING_DIRECTORY dir]
[COMMENT comment]
[VERBATIM] [USES_TERMINAL]
[COMMAND_EXPAND_LISTS])可以在以下时段将命令连接到构建中:
• PRE_BUILD: 在 Visual Studio 中此命令在执行其他构建步骤之前执行。当使用其他生成器 时会在 PRE_LINK 命令之前运行。
• PRE_LINK: 此命令将在编译源代码之后运行在可执行文件或存档工具链接到静态库之前运行。
• POS_BUILD: 这将在执行所有其他构建规则后运行该命令。 执行自定义步骤最常见的方法是使用 POST_BUILD; 其他两个选项很少使用要么是因为支持 有限要么是因为它们既不能影响链接也不能影响构建。
cmake_parse_arguments(prefix options one_value_keywordsmulti_value_keywords args...)cmake_parse_arguments(PARSE_ARGV N prefix optionsone_value_keywords multi_value_keywords)cmake_parse_arguments — CMake 3.30.3 Documentation
Great resoureces for learning
Effective Modern CMake (github.com)franneck94/CppProjectTemplate: C project template with unit-tests, documentation, ci-testing and workflows. (github.com)
书籍推荐CMake Best Practices (豆瓣) (douban.com)和Professional CMake (豆瓣) (douban.com)
如有疑问,欢迎各位交流!
服务器配置 宝塔:宝塔服务器面板一键全能部署及管理 云服务器:阿里云服务器 Vultr服务器: Vultr服务器 GPU服务器:Vast.ai 代码练习平台 CodeCrafters CodeCrafters