基本命令
# Head Enlarger With CMake
# CMake 真是十分甚至九分的令人头大喵message("\n======================================================================")
message(" -- 基本命令喵")
message("======================================================================\n")message(" -- 输出消息喵 \n")# =============================================================================
# 普通消息喵: message([mode] "消息文本" ...)
# 其中 mode 默认为 NOTICE
# 其中 mode 可为 FATAL_ERROR SEND_ERROR WARNING AUTHOR_WARNING DEPRECATION NOTICE STATUS VERBOSE
message(STATUS " 输出消息: CMake Head Enlarger Started! \n")# =============================================================================
# 检查消息喵: message([检查类型] "消息文本" ...)
# 检查类型 可为 CHECK_START CHECK_PASS CHECK_FAIL
# 可嵌套喵, CHECK_PASS 及 CHECK_FAIL 需与 CHECK_START 配套使用喵
message(CHECK_START "检查消息,检查开始喵!")
message(CHECK_FAIL "不通过喵!")
message(CHECK_START "再次检查喵!")
message(CHECK_PASS "通过喵!\n")message(" -- CMake 版本喵 \n")# =============================================================================
# 设置需要的 CMake 版本喵: cmake_minimum_required(VERSION 最低版本[...最高版本] [FATAL_ERROR])
# 如 cmake_minimum_required(VERSION 3.8...3.16 FATAL_ERROR) 或 cmake_minimum_required(VERSION 3.8)
# 指定 FATAL_ERROR 则 CMake 版本不满足时将报错喵,否则为警告喵
cmake_minimum_required(VERSION 3.30)
message("CMake 版本需要高于 " ${CMAKE_MINIMUM_REQUIRED_VERSION} "\n")# =============================================================================
# cmake_policy 命令用于设置策略喵,细节略喵
# cmake_policy(VERSION <min>[...<max>]) # 根据 CMake 设置策略
# cmake_policy(SET CMP<NNNN> NEW 或 OLD) # 显式设置策略
# cmake_policy(GET CMP<NNNN> <variable>) # 检查策略设置
# cmake_policy(PUSH或POP) # 操作策略栈message(" -- 创建项目喵 \n")# =============================================================================
# 设置项目,同时还将设置目录信息喵,以 PROJECT 开头的全局项目信息的新值会覆盖旧值喵
project(HeadEnlarger # 项目名称喵,存储在 PROJECT_NAME 和 CMAKE_PROJECT_NAMEVERSION 1.0.0.0 # 版本喵DESCRIPTION "CMake 真是十分令人头大,甚至九分喵!" # 项目描述喵HOMEPAGE_URL 127.0.0.1 # 项目主页网址喵LANGUAGES CXX) # 语言喵
message("项目名称喵 : ${PROJECT_NAME} ${CMAKE_PROJECT_NAME}")
message("项目源目录喵 : ${PROJECT_SOURCE_DIR} ${HeadEnlarger_SOURCE_DIR}")
message("项目二进制目录喵 : ${PROJECT_BINARY_DIR} ${HeadEnlarger_BINARY_DIR}") # 即输出目录喵
message("项目版本喵 : ${PROJECT_VERSION} ${HeadEnlarger_VERSION}")
message("项目版本喵 : ${PROJECT_VERSION_MAJOR} . ${PROJECT_VERSION_MINOR} . ${PROJECT_VERSION_PATCH} . ${PROJECT_VERSION_TWEAK}")
message("项目描述喵 : ${HeadEnlarger_DESCRIPTION}")
message("项目主页喵 : ${HeadEnlarger_HOMEPAGE_URL}\n")# =============================================================================
# =============================================================================add_subdirectory(ScriptCmd) # CMake 脚本命令解说喵
add_subdirectory(ProjectCmd) # CMake 项目命令解说喵
脚本命令
cmake_minimum_required(VERSION 3.30)# CMake 脚本命令喵message("\n======================================================================")
message(" -- 脚本命令喵 CMake Script Command")
message("======================================================================\n")message(" -- 作用域喵 \n")# =============================================================================
# 子项目、函数都会生成新的作用域喵,宏不会生成新的作用域喵# 用 block 和 endblock 可用于创建作用域喵
# block(PROPAGATE 外传的变量 ...) # 创建变量作用域喵, endblock 之后变量将置空,只会覆盖 PROPAGATE 指定的变量
# block(SCOPE POLICIES) # 不创建变量作用域喵, endblock 之后变量保持原值set(var1_for_block "OldVal1喵")
set(var2_for_block "OldVal2喵")
unset(var3_for_block)
message("block VARIABLES 测试喵: var1 = " ${var1_for_block} ", var2 = " ${var2_for_block} ", var3 = " ${var3_for_block})
block(PROPAGATE var1_for_block) # 创建新作用域喵,指定 var1 将回传至父作用域message(" in block VARIABLES var1 = " ${var1_for_block} ", var2 = " ${var2_for_block} ", var3 = " ${var3_for_block})set(var1_for_block "NewVal1喵") # 操作新作用域的变量, endblock 之后将置空喵,只会覆盖 PROPAGATE 指定的变量喵set(var2_for_block "NewVal2喵")set(var3_for_block "NewVal3喵")message(" out block VARIABLES var1 = " ${var1_for_block} ", var2 = " ${var2_for_block} ", var3 = " ${var3_for_block})
endblock()
message(" after block VARIABLES var1 = " ${var1_for_block} ", var2 = " ${var2_for_block} ", var3 = " ${var3_for_block} "\n")set(var1_for_block "OldVal1喵")
set(var2_for_block "OldVal2喵")
unset(var3_for_block)
message("block POLICIES 测试喵: var1 = " ${var1_for_block} ", var2 = " ${var2_for_block} ", var3 = " ${var3_for_block})
block(SCOPE_FOR POLICIES) # 不创建作用域,仍然是原来作用域喵message(" in block POLICIES var1 = " ${var1_for_block} ", var2 = " ${var2_for_block} ", var3 = " ${var3_for_block})set(var1_for_block "NewVal1喵")set(var2_for_block "NewVal2喵")set(var3_for_block "NewVal3喵")message(" out block POLICIES var1 = " ${var1_for_block} ", var2 = " ${var2_for_block} ", var3 = " ${var3_for_block})
endblock()
message(" after block POLICIES var1 = " ${var1_for_block} ", var2 = " ${var2_for_block} ", var3 = " ${var3_for_block} "\n")message(" -- 变量喵 \n")# =============================================================================
# 用 ${变量} 获取变量的值喵
# 用 set(变量 [值] [PARENT_SCOPE]) 设置变量的值喵,未指定值则设置为空喵,指定 PARENT_SCOPE 则操作父作用域的变量喵
# 用 unset(变量 [PARENT_SCOPE]) 置空变量喵,指定 PARENT_SCOPE 则操作父作用域的变量喵
set(var1_for_tsps "OldVal1喵")
set(var2_for_tsps "OldVal2喵")
message("变量作用域测试喵: var1 = " ${var1_for_tsps} ", var2 = " ${var2_for_tsps})
block() # 新作用域喵message(" in function var1 = " ${var1_for_tsps} ", var2 = " ${var2_for_tsps})set(var1_for_tsps "NewVal1喵") # 操作新作用域的变量, endblock 之后将置空喵set(var2_for_tsps "NewVal2喵" PARENT_SCOPE) # 操作父作用域的变量喵message(" out function var1 = " ${var1_for_tsps} ", var2 = " ${var2_for_tsps})
endblock()
message(" after function var1 = " ${var1_for_tsps} ", var2 = " ${var2_for_tsps} "\n")# =============================================================================
# 其他变量喵# 用 set(<variable> <value>... CACHE <type> <docstring> [FORCE]) # 设置缓存的值喵,type 可为 BOOL FILEPATH PATH STRING INTERNAL ,指定 FORCE 则覆盖现有值,默认不覆盖# 用 set(ENV{<variable>} [<value>]) # 设置环境变量的值喵# 用 option(变量 "帮助信息" 默认值) 指定一个开关喵,可以显示在 cmake GUI ,命名不可以冲突
option(SWITCH1_DEFAULT_ON "这是一个默认打开开关喵" ON)
option(SWITCH2_DEFAULT_OFF "这是一个默认不打开的开关喵") # 不指定默认值默认为关喵
message("开关演示喵: 开关1 = " ${SWITCH1_DEFAULT_ON} " 开关2 = " ${SWITCH2_DEFAULT_OFF} "\n")# 用 mark_as_advanced([CLEAR|FORCE] <var1> ...) 将变量设置为高级喵。指定 FORCE 将变量设置为高级, CLEAR 将变量设置为普通
# 高级变量不会显示在任何 cmake GUI 中,除非 "显示高级" 选项打开喵message(" -- 函数和宏喵 \n")# =============================================================================
# 用 function(函数名 形参 ...) 和 endfunction() 用声明一个函数喵
# 使用 return(PROPAGATE 变量 ...) 将变量传出为返回值喵
# 传入的参数数量为 ARGC ,参数分别被命名为 ARGV0, ARGV1, ARGV2 ... ,不匹配形参列表的参数的保存在 ARGN 中
function(f_test_fun val_a val_b)message("传参测试喵: 函数参数数量 argc = " ${ARGC})set(argv_index 0) # i = 0while(argv_index LESS ${ARGC}) # while(i < ARGC)set(argvi "ARGV${argv_index}") # 设置 argvi 为字符串 ARGV0, ARGV1, ARGV2 ...message(${argvi} " : " ${${argvi}})math(EXPR argv_index "${argv_index} + 1" OUTPUT_FORMAT DECIMAL) # i++endwhile()message("函数剩余参数 ARGN : " ${ARGN})set(f_test_fun_ret ${ARGV0} " - " ${ARGV1}) # 函数内部创建新作用域,操作新作用域变量喵message("函数 a_in = " ${val_a} " b_in = " ${val_b} " ret = " ${f_test_fun_ret})return(PROPAGATE f_test_fun_ret) # 使用 return(PROPAGATE 变量 ...) 将变量传出喵
endfunction()
f_test_fun("A_sub喵" "B_sub喵" "C_etc喵" "D_etc喵")
message("ret = " ${f_test_fun_ret} "\n")# =============================================================================
# 宏的用法类似于函数喵,区别:
# 宏中 ARGN、ARGC、ARGV0、ARGV1 等在宏中为字符串替换而不是变量喵
# 宏不产生新的作用域喵
macro(f_test_macro val_a val_b ref_ret)message("宏测试喵: in macro A = " ${val_a} " B = " ${val_b} " ret = " ${ref_ret})set(${ref_ret} ${val_a} " - " ${val_b})message("in macro ref_ret.name = " ${ref_ret} " , ref_ret.value = " ${${ref_ret}}) # 变量的名称和值喵
endmacro()
f_test_macro("A_sub" "B_sub" ret_macro)
message("ret = " ${ret_macro} "\n")message(" -- 参数类型喵 \n")# =============================================================================
# 参数有三种类型喵,分别是 开关、单值参数、多值参数# 可用 cmake_parse_arguments 解析变量并自动生成名为 "prefix_变量名" 的变量,仅用于函数
# 形式 1 喵
# cmake_parse_arguments(<prefix> # 生成的变量的前缀
# <options> <one_value_keywords> <multi_value_keywords>
# <args>...) # 要解析的变量列表喵
# 形式 2 喵
# cmake_parse_arguments(PARSE_ARGV <N> # 用于读取从第 N 个开始的参数喵
# <prefix> # 生成的变量的前缀
# <options> <one_value_keywords> <multi_value_keywords>) # 参数表喵
function(test_parse_args_parser)set(optionArgs OPTA) # 开关喵 值为 True 或 False,名称后不跟值,出现为 True 不出现为 Falseset(oneValArgs ONEA) # 单值变量喵 名称后跟一个值,其余值舍弃set(mulValArgs MULA) # 多值变量喵 名称后跟多个值cmake_parse_arguments(arg "${optionArgs}" "${oneValArgs}" "${mulValArgs}" ${ARGN})message("参数解析测试喵: ARGN " ${ARGN})message("开关喵 arg_OPTA : " ${arg_OPTA})message("单值变量喵 arg_ONEA : " ${arg_ONEA})message("多值变量喵 arg_MULA : " ${arg_MULA})message("其他参数喵 arg_UNPARSED_ARGUMENTS " ${arg_UNPARSED_ARGUMENTS}) # 不匹配形参的参数喵message("缺省参数喵 arg_KEYWORDS_MISSING_VALUES " ${arg_KEYWORDS_MISSING_VALUES} "\n") # 未传入值的形数喵
endfunction()
test_parse_args_parser(MULA mul_1 mul_2 ONEA one_a OPTA)message(" -- 流程控制喵 \n")# =============================================================================
# 条件语法喵# 基本条件语法喵
# 真值: 1、ON、YES、TRUE、Y、非零数(包括浮点数)
# 假值: 0、OFF、NO、FALSE、N、IGNORE、NOTFOUND、空字符串、"-NOTFOUND"结尾
# 布尔运算: AND、OR、NOT
# 数学运算: LESS、LESS_EQUAL、GREATER、GREATER_EQUAL、EQUAL
# 字符串运算: STRLESS、STRLESS_EQUAL、STRGREATER、STRGREATER_EQUAL、STREQUAL
# 版本运算: VERSION_LESS、VERSION_LESS_EQUAL、VERSION_GREATER、VERSION_GREATER_EQUAL、VERSION_EQUAL
# 路径运算: PATH_EQUAL
# 其他条件语法喵
# if(COMMAND <command-name>) # 给定名称是可以调用的命令、宏或函数为真
# if(POLICY <policy-id>) # 是现有策略为真
# if(TARGET <target-name>) # 给定目标通过 add_executable add_library 或 add_custom_target 等正确创建为真
# if(TEST <test-name>) # 给定测试由 add_test 等命令正确创建为真
# if(DEFINED <name>|CACHE{<name>}|ENV{<name>}) # 定义了名为 <name> 的变量、缓存变量或环境变量为真
# if(<variable|string> IN_LIST <variable>) # 在列表中为真
# if(EXISTS <path-to-file-or-directory>) # 存在该文件或目录为真
# if(IS_READABLE <path-to-file-or-directory>) # 文件或目录可读为真
# if(IS_WRITABLE <path-to-file-or-directory>) # 文件或目录可写为真
# if(IS_EXECUTABLE <path-to-file-or-directory>) # 文件或目录可执行为真
# if(<file1> IS_NEWER_THAN <file2>) # file1 新或一个文件不存在为真,一样新也为真
# if(IS_DIRECTORY <path>) # 是目录为真
# if(IS_SYMLINK <path>) # 是符号链接为真
# if(IS_ABSOLUTE <path>) # 是绝对路径为真,空路径为假
# if(<variable|string> MATCHES <regex>) # 满足正则表达式为真# =============================================================================
# if 分支喵
# if(<condition>)
# <commands>
# elseif(<condition>)
# <commands>
# else()
# <commands>
# endif()# =============================================================================
# 循环喵,循环中可使用 break() 和 continue() 控制流程# while 循环喵
# while(<condition>)
# <commands>
# endwhile()# for "初值、末值、步长" 型循环喵
# foreach(<loop_var> <items>)
# items 可为:
# RANGE <stop> # 从 0 <= loop_var <= stop
# RANGE <start> <stop> [<step>] # 初值 末值 步长
foreach(X RANGE 3)message(" RANGE 循环测试喵: X = " ${X})
endforeach()
message("\n")# foreach 遍历列表循环喵
# foreach(<loop_var> IN [LISTS [<lists>]] [ITEMS [<items>]])
# foreach(<loop_var> IN LISTS <lists>...) 与 foreach(<loop_var> IN ITEMS <item>...) 等价
set(A_list_test_for_each "Hello" "World")
set(B_list_test_for_each "Head" "Enlarger")
foreach(X IN LISTS A_list_test_for_each B_list_test_for_each)message("遍历循环测试喵: X = " ${X})
endforeach()
message("\n")# =============================================================================
# 事件喵# 可使用 variable_watch(<variable> [<command>]) 监视变量喵,当变量变化时触发事件
# 事件 command 的格式为 COMMAND(<variable> <access> <value> <current_list_file> <stack>)
function(test_watcher variable access value current_list_file stack)message("变量监视测试喵: variable: " ${variable}) # 变量名喵message("access: " ${access}) # READ_ACCESS、UNKNOWN_READ_ACCESS、MODIFIED_ACCESS、UNKNOWN_MODIFIED_ACCESS、REMOVED_ACCESSmessage("value: " ${value}) # 值喵message("current_list_file: " ${current_list_file}) # 进行访问的文件的完整路径喵message("stack: " ${stack} "\n") # 调用栈喵
endfunction()
variable_watch(test_wathcer_var test_watcher)
set(test_wathcer_var 0)message(" -- Config File 配置文件喵 \n")# =============================================================================
# 配置文件喵,使用输入文件为模版生成文件
# 输入文件中 "@变量@" "${变量}" "$CACHE{变量}" 的变量以及被引用为 "$ENV{变量}" 的环境变量会被替换为对应变量值
# 输入文件中 "#cmakedefine 变量 ..." 会根据开关 "变量_ENABLE" 的值被替换为 "#define 变量 ..." 或 "/* #undef 变量 */"
# configure_file(<input> # 输入文件,默认目录为 CMAKE_CURRENT_SOURCE_DIR
# <output> # 输出文件,默认目录为 CMAKE_CURRENT_BINARY_DIR
# [permissions] # 输出文件的权限设置,默认为 USE_SOURCE_PERMISSIONS ,可为 NO_SOURCE_PERMISSIONS USE_SOURCE_PERMISSIONS FILE_PERMISSIONS
# [COPYONLY] # 指定该值则原样复制不替换变量,与 NEWLINE_STYLE 设置冲突
# [ESCAPE_QUOTES] # 用反斜杠转义任何替换的引号
# [@ONLY] # 将变量替换限制为 "@变量@" 形式的引用
# [NEWLINE_STYLE [UNIX|DOS|WIN32|LF|CRLF]) # 换行样式message(" -- Package 管理喵 \n")# =============================================================================
# 用 cmake_pkg_config 加载一个 Package 文件并生成相关变量和目标喵
# cmake_pkg_config(EXTRACT <package> [<version>] # 库名称和版本喵
# [REQUIRED] # 如果未找到则报错喵
# [EXACT] # 要求版本完全匹配喵
# [QUIET] # 不显示消息喵
# [STRICTNESS <mode>] # 指定验证包文件的严格程度喵,可为 STRICT PERMISSIVE BEST_EFFORT
# [ENV_MODE <mode>] # 指定查询的环境变量喵,可为 FDO PKGCONF IGNORE
# [DISABLE_UNINSTALLED <bool>] # 禁用搜索已卸载的软件包喵
# [PC_LIBDIR <path>...] # pkg-config 环境变量 PKG_CONFIG_LIBDIR
# [PC_PATH <path>...] # pkg-config 环境变量 PKG_CONFIG_PATH
# [PC_SYSROOT_DIR <path>] # pkg-config 环境变量 PKG_CONFIG_SYSROOT_DIR
# [TOP_BUILD_DIR <path>] # pkg-config 环境变量 PKG_CONFIG_TOP_BUILD_DIR
# [SYSTEM_INCLUDE_DIRS <path>...] # 系统包含目录
# [SYSTEM_LIBRARY_DIRS <path>...] # 系统库目录
# [ALLOW_SYSTEM_INCLUDES <bool>] # 保留系统包含目录
# [ALLOW_SYSTEM_LIBS <bool>]) # 保留系统库目录cmake_path(SET sample_package_path "Resources/sample_package.pc")
cmake_path(ABSOLUTE_PATH sample_package_path)
message("加载包测试喵,加载: " ${sample_package_path})
cmake_pkg_config(EXTRACT ${sample_package_path})
message("CMAKE_PKG_CONFIG_NAME = " ${CMAKE_PKG_CONFIG_NAME})
message("CMAKE_PKG_CONFIG_DESCRIPTION = " ${CMAKE_PKG_CONFIG_DESCRIPTION})
message("CMAKE_PKG_CONFIG_VERSION = " ${CMAKE_PKG_CONFIG_VERSION})
message("CMAKE_PKG_CONFIG_PROVIDES = " ${CMAKE_PKG_CONFIG_PROVIDES})
message("CMAKE_PKG_CONFIG_REQUIRES = " ${CMAKE_PKG_CONFIG_REQUIRES})
message("CMAKE_PKG_CONFIG_CONFLICTS = " ${CMAKE_PKG_CONFIG_CONFLICTS})
message("CMAKE_PKG_CONFIG_CFLAGS = " ${CMAKE_PKG_CONFIG_CFLAGS})
message("CMAKE_PKG_CONFIG_INCLUDES = " ${CMAKE_PKG_CONFIG_INCLUDES})
message("CMAKE_PKG_CONFIG_COMPILE_OPTIONS = " ${CMAKE_PKG_CONFIG_COMPILE_OPTIONS})
message("CMAKE_PKG_CONFIG_LIBS = " ${CMAKE_PKG_CONFIG_LIBS})
message("CMAKE_PKG_CONFIG_LIBDIRS = " ${CMAKE_PKG_CONFIG_LIBDIRS})
message("CMAKE_PKG_CONFIG_LIBNAMES = " ${CMAKE_PKG_CONFIG_LIBNAMES})
message("CMAKE_PKG_CONFIG_LINK_OPTIONS = " ${CMAKE_PKG_CONFIG_LINK_OPTIONS})
# message("CMAKE_PKG_CONFIG_*_PRIVATE = " ${CMAKE_PKG_CONFIG_*_PRIVATE}) # 从 CFLAGS LIBS REQUIRES 派生的变量内容
message("CMAKE_PKG_CONFIG_LIBS_PRIVATE = " ${CMAKE_PKG_CONFIG_LIBS_PRIVATE} "\n")# =============================================================================
# find_package 重载喵# 依赖提供将重定向 find_package() 或 FetchContent_MakeAvailable() 等到自定义实现喵
# 如无满足要求的自定义实现,将使用默认实现喵# 使用 cmake_language(SET_DEPENDENCY_PROVIDER) 重定义 find_package 或 FetchContent_MakeAvailable
# cmake_language(SET_DEPENDENCY_PROVIDER <command> # 自定义的支持方法,应该是一个宏喵
# SUPPORTED_METHODS <methods>...) # 替换的支持方法喵, method 可为 FIND_PACKAGE 或 FETCHCONTENT_MAKEAVAILABLE_SERIAL# 使用时,需在顶级项目中,将重定义提供依赖的 cmake 文件添加到 CMAKE_PROJECT_TOP_LEVEL_INCLUDES 中
# 然后在第一次创建项目时将加载并执行喵,如:
# set(CMAKE_PROJECT_TOP_LEVEL_INCLUDES Resources/my_provide.cmake) # 将在第一次运行 project 命令时被包含喵
# project(HelloTest_ForMyProvide) # 创建项目并包含 my_provide.cmake ,重定向 find_package
# find_package(Test) # 将使用重载的方法喵
# 本文件为子项目,该测试不可用喵# =============================================================================
# 查找包, find_package 和其他查找命令实现通用的选项喵
# find_package(<PackageName> [version] # 包名和版本喵
# [EXACT] [QUIET] [MODULE] # 使用哪种模式查找喵, MODULE 则不能使用 Config 模式, EXACT 要求严格匹配, QUIET 表示查找失败不输出提示
# [[COMPONENTS] [components...]] # 查找包的特定组件
# [OPTIONAL_COMPONENTS components...] # 可选的组件
# [CONFIG|NO_MODULE] # 采用 Config 模式
# [GLOBAL] # 全局
# [NO_POLICY_SCOPE] # 不创建新的策略
# [BYPASS_PROVIDER] # 重定义 find_package 时使用该选项调用系统的 find_package
# [CONFIGS config1 [config2 ...]] # 可能的配置文件的名字
# [NO_CMAKE_PACKAGE_REGISTRY] # 排除目录 CMAKE_PACKAGE_REGISTRY
# [NO_CMAKE_SYSTEM_PACKAGE_REGISTRY] # 不使用系统软件包注册表
# [NO_CMAKE_BUILDS_PATH] # Deprecated; does nothing 弃用项喵没有用喵
# [NAMES name1 [name2 ...]]
# [REQUIRED]
# [HINTS path1 [path2 ... ]] [PATHS path1 [path2 ... ]]
# [REGISTRY_VIEW (64|32|64_32|32_64|HOST|TARGET|BOTH)]
# [PATH_SUFFIXES suffix1 [suffix2 ...]]
# [NO_DEFAULT_PATH]
# [NO_PACKAGE_ROOT_PATH]
# [NO_CMAKE_PATH]
# [NO_CMAKE_ENVIRONMENT_PATH]
# [NO_SYSTEM_ENVIRONMENT_PATH]
# [NO_CMAKE_SYSTEM_PATH]
# [NO_CMAKE_INSTALL_PREFIX]
# [CMAKE_FIND_ROOT_PATH_BOTH |
# ONLY_CMAKE_FIND_ROOT_PATH |
# NO_CMAKE_FIND_ROOT_PATH])# =============================================================================
# 查找成功后,将从包中获取包名开头(有时候是大写)的一系列变量喵,变量后缀为约定俗成,如:
# Xxx_INCLUDE_DIRS Xxx_LIBRARIES Xxx_DEFINITIONS Xxx_EXECUTABLE
# Xxx_YYY_EXECUTABLE Xxx_LIBRARY_DIRS Xxx_ROOT_DIR Xxx_VERSION_VV
# Xxx_WRAP_YY Xxx_Yy_FOUND Xxx_FOUND Xxx_NOT_FOUND_MESSAGE
# Xxx_RUNTIME_LIBRARY_DIRS Xxx_VERSION Xxx_VERSION_MAJOR Xxx_VERSION_MINOR
# Xxx_VERSION_PATCH Xxx_LIBRARY Xxx_Yy_LIBRARY Xxx_INCLUDE_DIR Xxx_Yy_INCLUDE_DIRcmake_path(SET sh_getline_path "Resources/GetLine.sh")
cmake_path(ABSOLUTE_PATH sh_getline_path)
message("Shell 脚本的路径: " ${sh_getline_path})
message("即将加载 Shell 脚本 GetLine 通过黑魔法获取实时输入喵,请输入要查找的包!") # 黑魔法的解析在 execute_process 章节
execute_process(COMMAND bash ${sh_getline_path} OUTPUT_VARIABLE sh_getline_str COMMAND_ECHO STDOUT) # 执行 shell 命令 echo
message("你要查找的包: " ${sh_getline_str} " 马上开始查询!")
find_package(${sh_getline_str})
set(pkg_suffix "_FOUND" "_VERSION" "_ROOT_DIR" "_DIR" "_DEFINITIONS" "_INCLUDES" "_INCLUDE_DIR" "_INCLUDE_DIRS" "_LIBS" "_LIBRARY" "_LIBRARIES" "_LIBRARY_DIRS" "_EXECUTABLE" "_RUNTIME_LIBRARY_DIRS")
foreach (suffix_item IN LISTS pkg_suffix)set(item_fullname ${sh_getline_str})string(TOUPPER ${sh_getline_str} item_fullname_upper)string(APPEND item_fullname ${suffix_item})message("${item_fullname} = " ${${item_fullname}})string(APPEND item_fullname_upper ${suffix_item})message("${item_fullname_upper} = " ${${item_fullname_upper}})
endforeach()# =============================================================================
# 生成包配置文件,生成 <PackageName>Config.cmake 文件,需先包含 CMakePackageConfigHelpers
# configure_package_config_file(<input> <output> # 输入和输出文件,与 configure_file 类似
# INSTALL_DESTINATION <path> # 安装位置
# [PATH_VARS <var1> <var2> ... <varN>] # 安装位置的变量,由 input 使用
# [NO_SET_AND_CHECK_MACRO] # 不检查引用的文件或目录是否实际存在
# [NO_CHECK_REQUIRED_COMPONENTS_MACRO] # 不检查是否找到所需的组件
# [INSTALL_PREFIX <path>]) # 安装路径前缀# =============================================================================
# 生成包版本文件,生成 <PackageName>ConfigVersion.cmake 文件,需先包含 CMakePackageConfigHelpers
# write_basic_package_version_file(<filename> # 文件名
# [VERSION <major.minor.patch>] # 版本
# COMPATIBILITY <AnyNewerVersion|SameMajorVersion|SameMinorVersion|ExactVersion> # 兼容模式
# [ARCH_INDEPENDENT]) # 安装的包版本是兼容的,适用于只有头文件的库或没有二进制文件的类似包message(" -- 查找喵 find \n")# =============================================================================
# 通用基本选项喵
# [HINTS [path | ENV var]... ] [PATHS [path | ENV var]... ] # 除默认位置外,指定要搜索的目录
# [REGISTRY_VIEW (64|32|64_32|32_64|HOST|TARGET|BOTH)] # 查找注册表
# [PATH_SUFFIXES suffix1 [suffix2 ...]] # 在每个目录位置下面指定要检查的其他子目录
# [VALIDATOR function] # 过滤器
# [DOC "cache documentation string"] # 指定 <VAR> 缓存项的文档字符串
# [NO_CACHE] # 搜索结果将存储在一个普通变量中,不保存在缓存中
# [REQUIRED] # 如果没有找到任何东西,则停止处理并给出错误消息
# [NO_DEFAULT_PATH] # 排除目录 DEFAULT_PATH
# [NO_PACKAGE_ROOT_PATH] # 排除目录 PACKAGE_ROOT_PATH
# [NO_CMAKE_PATH] # 排除目录 CMAKE_PATH
# [NO_CMAKE_ENVIRONMENT_PATH] # 排除目录 CMAKE_ENVIRONMENT_PATH
# [NO_SYSTEM_ENVIRONMENT_PATH] # 排除目录 SYSTEM_ENVIRONMENT_PATH
# [NO_CMAKE_SYSTEM_PATH] # 排除目录 CMAKE_SYSTEM_PATH
# [NO_CMAKE_INSTALL_PREFIX] # 排除目录 CMAKE_INSTALL_PREFIX
# [CMAKE_FIND_ROOT_PATH_BOTH | # 按默认的顺序搜索
# ONLY_CMAKE_FIND_ROOT_PATH | # 仅搜索重根目录和 CMAKE_STAGING_PREFIX 以下目录
# NO_CMAKE_FIND_ROOT_PATH]) # 不使用 CMAKE_FIND_ROOT_PATH# =============================================================================
# 其他查找喵, find_file 查找文件的完整路径, find_library 查找库, find_program 查找程序
# find_file find_library 或 find_program
# (<VAR> # 保存结果的变量
# name | NAMES name1 [name2 ...] # 在 find_library 和 find_program 中 name 为文件夹喵
# [HINTS [path | ENV var]... ] [PATHS [path | ENV var]... ]
# [REGISTRY_VIEW (64|32|64_32|32_64|HOST|TARGET|BOTH)]
# [PATH_SUFFIXES suffix1 [suffix2 ...]]
# [VALIDATOR function]
# [DOC "cache documentation string"]
# [NO_CACHE]
# [REQUIRED]
# [NO_DEFAULT_PATH]
# [NO_PACKAGE_ROOT_PATH]
# [NO_CMAKE_PATH]
# [NO_CMAKE_ENVIRONMENT_PATH]
# [NO_SYSTEM_ENVIRONMENT_PATH]
# [NO_CMAKE_SYSTEM_PATH]
# [NO_CMAKE_INSTALL_PREFIX]
# [CMAKE_FIND_ROOT_PATH_BOTH |
# ONLY_CMAKE_FIND_ROOT_PATH |
# NO_CMAKE_FIND_ROOT_PATH])message(" -- 数学表达式喵 \n")# 用 math(EXPR <variable> "<expression>" [OUTPUT_FORMAT <format>]) 执行一个数学表达式
# format 可为 HEXADECIMAL(十六进制) 或 DECIMAL(十进制)
math(EXPR value_math "100 * 0xFF + 66" OUTPUT_FORMAT DECIMAL)
message("数学表达式测试喵: 100 * 0xFF + 66 = " ${value_math} "\n")message(" -- 执行 CMake 喵\n")# =============================================================================
# 使用 add_subdirectory 添加一个子目录并运行其中的 CMakeLists.txt ,子目录必须是一个 CMake 项目喵# =============================================================================
# 使用 include 加载并运行 CMake 文件喵
# include(<file|module> # 要加载的 CMake 文件喵
# [OPTIONAL] # 如指定,则找不到文件时不报错喵
# [RESULT_VARIABLE <var>] # 保存完整的文件名,找不到文件为 NOTFOUND
# [NO_POLICY_SCOPE]) # 不创建新的策略喵喵
include(Resources/test_for_inc.cmake)
message("\n")# 可使用 include_guard([DIRECTORY|GLOBAL]) 防止重复包含文件喵
#
# 在子文件使用下面的结构也可以防止重复包含喵:
# if(__CURRENT_FILE_VAR__)
# return() # 因重复包含退出了喵
# endif()
# set(__CURRENT_FILE_VAR__ TRUE)
include(Resources/test_for_inc.cmake)
message("\n")# =============================================================================
# 使用 cmake_language 可执行 CMake 指令或代码喵# 执行一条 CMake 命令喵
# cmake_language(CALL <command> [<arg>...]) # 约等于 command([args...])
cmake_language(CALL "message" "执行一条 CMake 命令测试喵: Hello World! \n")# 执行多条 CMake 命令喵
# cmake_language(EVAL CODE <code>...) # 实际上是调用 CODE 后的内容喵
cmake_language(EVAL CODE "message(执行多条 CMake 命令测试喵: 第一条 Hello World CmdA)message(执行多条 CMake 命令测试喵: 第二条 Hello World CmdB \n)")# 在文件处理最后调用 CMake 命令喵
# cmake_language(DEFER <options>... CALL <command> [<arg>...])
# options 可包含以下内容
# DIRECTORY <dir> # 指定该级文件夹处理结束后调用本命令喵,默认为本级,只可指定为祖先级,如 ".."
# ID id # 设置 ID ,需以下划线开头
# ID_VAR id # 设置保存 ID 的变量喵
cmake_language(DEFER DIRECTORY ".." CALL message "延后命令调用测试喵: 本条消息将在父级文件处理最后显示喵 \n") # 会在最后调用喵
cmake_language(DEFER ID "_DeferedMessage" ID_VAR cm_lg_id CALL message "本条消息稍后会被取消喵") # 会在最后调用,并获取 ID
message("延后命令调用的 ID 测试喵: 某一条消息的 Id : " ${cm_lg_id} "\n")
cmake_language(DEFER CANCEL_CALL ${cm_lg_id}) # 取消一个回调喵message(" -- 执行外部指令喵 \n")# =============================================================================
# 使用 execute_process 执行外部程序或脚本,每个命令的输出将通过管道传输到下一个命令
# execute_process(COMMAND <cmd1> [<arguments>] # 指令和参数
# [COMMAND <cmd2> [<arguments>]]... # 指令和参数
# [WORKING_DIRECTORY <directory>] # 执行命令的目录
# [TIMEOUT <seconds>] # 超时,单位为秒
# [RESULT_VARIABLE <variable>] # 运行的最终结果。成功时为整数,失败时为错误信息
# [RESULTS_VARIABLE <variable>] # 保存每条命令的结果。成功时为整数,失败时为错误信息
# [OUTPUT_VARIABLE <variable>] [ERROR_VARIABLE <variable>] # 保存 stdout 或 stderr 到变量
# [INPUT_FILE <file>] # 重定向 标准输入
# [OUTPUT_FILE <file>] [ERROR_FILE <file>] # 重定向 stdout 或 stderr
# [OUTPUT_QUIET] [ERROR_QUIET] # 忽略 stdout 或 stderr
# [COMMAND_ECHO <where>] # 正在运行的命令将被回送到 <where> ,<where> 可为 STDERR STDOUT NONE
# [OUTPUT_STRIP_TRAILING_WHITESPACE] [ERROR_STRIP_TRAILING_WHITESPACE] # 删除 stdout 或 stderr 的尾部空格
# [ENCODING <name>] # 编码
# [ECHO_OUTPUT_VARIABLE] [ECHO_ERROR_VARIABLE] # 标准输出或标准错误不会专门重定向到指定的变量
# [COMMAND_ERROR_IS_FATAL <ANY|LAST>]) # ANY 则任何命令错误都会停止, LAST 则只有最后一条命令错误时停止
execute_process(COMMAND echo "执行外部指令测试喵: 准备执行 shell 指令 echo !" COMMAND echo "执行外部指令测试喵: Hello World!" OUTPUT_VARIABLE exe_pro_output COMMAND_ECHO STDOUT) # 执行 shell 命令 echo
message("执行外部指令测试喵: 最终结果: " ${exe_pro_output} "\n")# =============================================================================
# 使用 separate_arguments 将命令行参数解析为以分号分隔的列表
# separate_arguments(<variable> <mode> [PROGRAM [SEPARATE_ARGS]] <args>)
# mode 可为: UNIX_COMMAND WINDOWS_COMMAND NATIVE_COMMAND
# 指定 PROGRAM 时, arg[0] 将被认为是可执行文件,后续为参数
# 指定 SEPARATE_ARGS 时,参数被拆分在结果中,否则参数为一个字符串整体
separate_arguments(out_test_cmd_args UNIX_COMMAND PROGRAM SEPARATE_ARGS "cc -c tst.c")
foreach(X IN LISTS out_test_cmd_args)message("解析命令行参数测试喵: the arg is : " ${X})
endforeach()
message("\n")message(" -- 文件和路径喵 \n")# =============================================================================
# 路径喵# 简要的说明喵:
# <path-var> 一个路径变量喵
# <input> 一个字符串文字表示一个或多个路径喵
# <input>... 零个或多个字符串文字参数喵
# <out-var> 保存结果的变量喵# Decomposition 检索
# cmake_path(GET <path-var> type <out-var>)
# type ROOT_NAME ROOT_DIRECTORY ROOT_PATH FILENAME RELATIVE_PART PARENT_PATH
# cmake_path(GET <path-var> EXTENSION|STEM [LAST_ONLY] <out-var>)# Query 查询路径是否存在
# cmake_path(HAS_type <path-var> <out-var>)
# type 可为 ROOT_NAME ROOT_DIRECTORY ROOT_PATH FILENAME EXTENSION STEM RELATIVE_PART PARENT_PATH# cmake_path(IS_ABSOLUTE <path-var> <out-var>) # 是否是绝对路径
# cmake_path(IS_RELATIVE <path-var> <out-var>) # 是否是相对路径
# cmake_path(IS_PREFIX <path-var> <input> [NORMALIZE] <out-var>)
# cmake_path(COMPARE <input1> <OP> <input2> <out-var>) # 比较路径# Modification 修改
# cmake_path(SET <path-var> [NORMALIZE] <input>) # 创建一个路径变量,令 path-var = input ,会按需自动转换形式
# cmake_path(APPEND <path-var> [<input>...] [OUTPUT_VARIABLE <out-var>]) # 连接路径,令 path-var += input ,会按需自动转换形式
# cmake_path(APPEND_STRING <path-var> [<input>...] [OUTPUT_VARIABLE <out-var>]) # 连接路径,令 path-var += input ,会按需自动转换形式
# cmake_path(REMOVE_FILENAME <path-var> [OUTPUT_VARIABLE <out-var>]) # 删除文件名,文件变为目录
# cmake_path(REPLACE_FILENAME <path-var> <input> [OUTPUT_VARIABLE <out-var>]) # 替换文件名
# cmake_path(REMOVE_EXTENSION <path-var> [LAST_ONLY] [OUTPUT_VARIABLE <out-var>]) # 略
# cmake_path(REPLACE_EXTENSION <path-var> [LAST_ONLY] <input> [OUTPUT_VARIABLE <out-var>]) # 略# Generation 生成
# cmake_path(NORMAL_PATH <path-var> [OUTPUT_VARIABLE <out-var>]) # 规范化路径
# cmake_path(RELATIVE_PATH <path-var> [BASE_DIRECTORY <input>] [OUTPUT_VARIABLE <out-var>]) # 将 path-var 修改为相对目录
# cmake_path(ABSOLUTE_PATH <path-var> [BASE_DIRECTORY <input>] [NORMALIZE] [OUTPUT_VARIABLE <out-var>]) # 将 path-var 修改为绝对目录# Native Conversion 本地转换, CMake 路径和特定操作系统的路径转换
# cmake_path(NATIVE_PATH <path-var> [NORMALIZE] <out-var>) # CMake -> 系统
# cmake_path(CONVERT <input> TO_CMAKE_PATH_LIST <out-var> [NORMALIZE]) # 系统 -> CMake
# cmake_path(CONVERT <input> TO_NATIVE_PATH_LIST <out-var> [NORMALIZE]) # CMake -> 系统# Hashing 哈希
# cmake_path(HASH <path-var> <out-var>) # 计算路径的哈希值# =============================================================================
# 文件喵# Reading 读
# file(READ <filename> <out-var> [...]) # 从文件读取内容
# file(STRINGS <filename> <out-var> [...]) # 从文件读取 ANSCII 字符串
# file(<HASH> <filename> <out-var>) # 计算文件的哈希值
# file(TIMESTAMP <filename> <out-var> [...]) # 计算文件的修改时间
# file(GET_RUNTIME_DEPENDENCIES [...]) # 递归获取给定文件所依赖的库列表,不适用于项目模式# Writing 写
# file({WRITE | APPEND} <filename> <content>...) # 写入文件
# file({TOUCH | TOUCH_NOCREATE} [<file>...]) # 创建文件
# file(GENERATE OUTPUT <output-file> [...]) # 为当前 CMake Generator 支持的每个 build configuration 生成一个输出文件
# file(CONFIGURE OUTPUT <output-file> CONTENT <content> [...]) # 类似于 configure_file 命令# Filesystem 文件系统
# file({GLOB | GLOB_RECURSE} <out-var> [...] [<globbing-expr>...]) # 遍历子目录,使用类似 "*.txt" 的 globbing expressions 搜索文件
# file(MAKE_DIRECTORY [<dir>...]) # 创建一个目录
# file({REMOVE | REMOVE_RECURSE } [<files>...]) # 删除
# file(RENAME <oldname> <newname> [...]) # 重命名
# file(COPY_FILE <oldname> <newname> [...]) # 复制文件
# file({COPY | INSTALL} <file>... DESTINATION <dir> [...]) # COPY 进阶的文件复制; INSTALL 类似于 install 命令
# file(SIZE <filename> <out-var>) # 获取文件大小
# file(READ_SYMLINK <linkname> <out-var>) # 查询符号链接并获取指向的路径
# file(CREATE_LINK <original> <linkname> [...]) # 创建一个符号链接
# file(CHMOD <files>... <directories>... PERMISSIONS <permissions>... [...]) # 更改文件权限
# file(CHMOD_RECURSE <files>... <directories>... PERMISSIONS <permissions>... [...]) # 更改文件夹权限# Path Conversion 路径转换
# file(REAL_PATH <path> <out-var> [BASE_DIRECTORY <dir>] [EXPAND_TILDE]) # 转为绝对路径
# file(RELATIVE_PATH <out-var> <directory> <file>) # 计算相对路径
# file({TO_CMAKE_PATH | TO_NATIVE_PATH} <path> <out-var>) # 转换路径为 CMake 格式或操作系统格式# Transfer 传输
# file(DOWNLOAD <url> [<file>] [...]) # 下载
# file(UPLOAD <file> <url> [...]) # 上传# Locking 加锁
# file(LOCK <path> [...])# Archiving 归档,支持 7zip gnutar pax paxr raw zip 格式
# file(ARCHIVE_CREATE OUTPUT <archive> PATHS <paths>... [...])
# file(ARCHIVE_EXTRACT INPUT <archive> [...])message(" -- 列表操作喵 \n")# Reading 读
# list(LENGTH <list> <out-var>) # 获取列表元素数量
# list(GET <list> <element index> [<index> ...] <out-var>) # 获取第 index 个元素
# list(JOIN <list> <glue> <out-var>) # 连接为字符串, glue 为分隔符
# list(SUBLIST <list> <begin> <length> <out-var>) # 截取# Search 查
# list(FIND <list> <value> <out-var>) # 查找,返回索引# Modification 写
# list(APPEND <list> [<element>...]) # 追加元素,尾插
# list(FILTER <list> {INCLUDE | EXCLUDE} REGEX <regex>) # 过滤
# list(INSERT <list> <index> [<element>...]) # 插入元素
# list(POP_BACK <list> [<out-var>...]) # 弹出最后一个
# list(POP_FRONT <list> [<out-var>...]) # 弹出第一个
# list(PREPEND <list> [<element>...]) # 头插
# list(REMOVE_ITEM <list> <value>...) # 移除值为 value 的元素
# list(REMOVE_AT <list> <index>...) # 移除 index 位置的元素
# list(REMOVE_DUPLICATES <list>) # 去重
# list(TRANSFORM <list> <ACTION> [...]) # 操作列表, ACTION 可为: APPEND, PREPEND, TOUPPER, TOLOWER, STRIP, GENEX_STRIP, REPLACE; SELECTOR 可为 AT FOR REGEX# Ordering 排序
# list(REVERSE <list>) # 反转
# list(SORT <list> [COMPARE <compare>] [CASE <case>] [ORDER <order>]) # 排序, COMPARE 可为 STRING, FILE_BASENAME, NATURAL ; CASE 可为 SENSITIVE, INSENSITIVE; ORDER 可为 ASCENDING, DESCENDINGmessage(" -- 字符串操作喵 \n")# Search and Replace 查找替换
# string(FIND <string> <substr> <out-var> [...]) # 在 string 查找 substr 的位置
# string(REPLACE <match-string> <replace-string> <out-var> <input>...) # 替换
# string(REGEX MATCH <match-regex> <out-var> <input>...) # 查找匹配正则表达式的位置
# string(REGEX MATCHALL <match-regex> <out-var> <input>...) # 检查整个字符串是否符合正则表达式
# string(REGEX REPLACE <match-regex> <replace-expr> <out-var> <input>...) # 正则替换# Manipulation 字符串操作
# string(APPEND <string-var> [<input>...]) # 尾插
# string(PREPEND <string-var> [<input>...]) # 头插
# string(CONCAT <out-var> [<input>...]) # 连接
# string(JOIN <glue> <out-var> [<input>...]) # 连接
# string(TOLOWER <string> <out-var>) # 转小写
# string(TOUPPER <string> <out-var>) # 转大写
# string(LENGTH <string> <out-var>) # 获取长度
# string(SUBSTRING <string> <begin> <length> <out-var>) # 截取
# string(STRIP <string> <out-var>) # 删除前导和尾随空格
# string(_STRIP <string> <out-var>) # 删除 GENEX 生成表达式
# string(REPEAT <string> <count> <out-var>) # 重复 count 次# Comparison 比较
# string(COMPARE <op> <string1> <string2> <out-var>) # 比较, op 可为 LESS GREATER EQUAL NOTEQUAL LESS_EQUAL GREATER_EQUAL# Hashing 哈希
# string(<HASH> <out-var> <input>) # 计算哈希值# Generation 生成
# string(ASCII <number>... <out-var>) # 数字转字符串
# string(HEX <string> <out-var>) # 转十六进制
# string(CONFIGURE <string> <out-var> [...]) # 类似 configure_file 命令
# string(MAKE_C_IDENTIFIER <string> <out-var>) # 非字母数字字符转换为下划线
# string(RANDOM [<option>...] <out-var>) # 生成随机字符串
# string(TIMESTAMP <out-var> [<format string>] [UTC]) # 时间字符串
# string(UUID <out-var> ...) # 获取 UUID# JSON
# string(JSON <out-var> [ERROR_VARIABLE <error-var>]
# {GET | TYPE | LENGTH} <json-string> <member|index> [<member|index> ...]) # 获取元素的值、类型、长度
# string(JSON <out-var> [ERROR_VARIABLE <error-var>]
# REMOVE <json-string> <member|index> [<member|index> ...]) # 删除一个元素
# string(JSON <out-var> [ERROR_VARIABLE <error-var>]
# MEMBER <json-string> [<member|index> ...] <index>) # 获取第 <index> 个成员的名称,需要对象类型的元素
# string(JSON <out-var> [ERROR_VARIABLE <error-var>]
# SET <json-string> <member|index> [<member|index> ...] <value>) # 设置值
# string(JSON <out-var> [ERROR_VARIABLE <error-var>]
# EQUAL <json-string1> <json-string2>) # 比较两个 JSON 对象是否相等message(" -- 属性喵 \n")# 使用 define_property 定义一个属性喵
# define_property(<GLOBAL | DIRECTORY | TARGET | SOURCE | TEST | VARIABLE | CACHED_VARIABLE> # 设置属性的范围
# PROPERTY <name> # 属性的名称
# [INHERITED] # 继承自高级作用域的属性。指定之后,获取属性在本级作用域未查到时,会从更高的作用域查找
# [BRIEF_DOCS <brief-doc> [docs...]] # 属性的简介文档
# [FULL_DOCS <full-doc> [docs...]] # 属性的完整文档
# [INITIALIZE_FROM_VARIABLE <variable>]) # 从变量初始化,只用于 TARGET 的属性# 使用 set_property 设置属性的值喵
# set_property(<
# GLOBAL |
# DIRECTORY [<dir>] |
# TARGET [<target1> ...] |
# SOURCE [<src1> ...]
# [DIRECTORY <dirs> ...]
# [TARGET_DIRECTORY <targets> ...] |
# INSTALL [<file1> ...] |
# TEST [<test1> ...]
# [DIRECTORY <dir>] |
# CACHE [<entry1> ...]
# > # 前面都是属性的作用域喵
# [APPEND] [APPEND_STRING] # APPEND 按列表追加, APPEND_STRING 按字符串追加
# ROPERTY <name> [<value1> ...]) # 属性名称和值喵# 使用 get_property 获取属性的值喵,查找属性没找到均为 NOTFOUND
# get_property(<variable> # 保存结果的变量
# <
# GLOBAL |
# DIRECTORY [<dir>] |
# TARGET <target> |
# SOURCE <source>
# [DIRECTORY <dir> | TARGET_DIRECTORY <target>] |
# INSTALL <file> |
# TEST <test>
# [DIRECTORY <dir>] |
# CACHE <entry> |
# VARIABLE
# > # 前面都是属性的作用域喵
# PROPERTY <name> # 属性名喵
# [SET | DEFINED | BRIEF_DOCS | FULL_DOCS]) # 依次为 是否置值 是否定义 简要文档 完整文档# 其他属性操作函数喵
# 全局属性喵,只读喵
# get_cmake_property(<variable> <property>) # 查找属性
# 文件夹属性喵
# set_directory_properties(PROPERTIES <prop1> <value1> [<prop2> <value2>] ...) # 设置属性
# get_directory_property(<variable> [DIRECTORY <dir>] <prop-name>) # 查找属性
# get_directory_property(<variable> [DIRECTORY <dir>] DEFINITION <var-name>) # 从目录 dir 查找变量 var-name
# 目标属性
# set_target_properties(<targets> ... PROPERTIES <prop1> <value1> [<prop2> <value2>] ...) # 设置属性
# get_target_property(<variable> target property) # 查找属性
# 源文件属性
# set_source_files_properties(<files> ... [DIRECTORY <dirs> ...] [TARGET_DIRECTORY <targets> ...] PROPERTIES <prop1> <value1> [<prop2> <value2>] ...) # 设置属性
# get_source_file_property(<variable> <file> [DIRECTORY <dir> | TARGET_DIRECTORY <target>] <property>) # 查找属性add_subdirectory(Proj_TestForDirProp) # 需用 add_subdirectory 加载文件夹喵
get_directory_property(dir_res_prop DIRECTORY Proj_TestForDirProp FOR_TEST_PROP)
message("文件夹属性 FOR_TEST_PROP 是 : " ${dir_res_prop})
get_directory_property(dir_res_def DIRECTORY Proj_TestForDirProp DEFINITION Var_For_Test_Prop)
message("文件夹变量 Var_For_Test_Prop 是 : " ${dir_res_def})
get_property(dir_res_prop_doc DIRECTORY Proj_TestForDirProp PROPERTY FOR_TEST_PROP BRIEF_DOCS)
message("文件夹属性 FOR_TEST_PROP 的文档是 : " ${dir_res_prop_doc} "\n")message(" -- 其他命令喵 \n")message("其他命令: ")
# 获取系统信息喵
# cmake_host_system_information(RESULT <variable> QUERY <key> ...) # 查询系统信息
# cmake_host_system_information(RESULT <variable> QUERY WINDOWS_REGISTRY <key> ...) # 查询 Windows 注册表
cmake_host_system_information(RESULT sys_pretty_name QUERY DISTRIB_PRETTY_NAME)
message("sys_pretty_name: ${sys_pretty_name}")
cmake_host_system_information(RESULT sys_distro QUERY DISTRIB_INFO)
foreach(VAR IN LISTS sys_distro)message("${VAR} = `${${VAR}}`")
endforeach()# 获取本机名喵
site_name(var_site_name)
message("the site name : " ${var_site_name})# 获取日志级别喵
cmake_language(GET_MESSAGE_LOG_LEVEL log_level)
message("日志级别: " ${log_level} "\n")
项目命令
cmake_minimum_required(VERSION 3.30)# CMake 项目命令喵message("\n======================================================================")
message(" -- 项目命令喵,文档喵")
message("======================================================================\n")add_subdirectory(Sample) # 示例项目喵# █████████████████████████████████████████████████████████████████████████████
# -- 作用范围喵
# █████████████████████████████████████████████████████████████████████████████# <INTERFACE|PUBLIC|PRIVATE> 用于指定作用范围喵
# INTERFACE 表示用于指定项目的使用方
# PUBLIC 表示用于指定项目及其使用方
# PRIVATE 表示仅用于指定的项目# █████████████████████████████████████████████████████████████████████████████
# -- 目标喵
# █████████████████████████████████████████████████████████████████████████████# =============================================================================
# 可执行文件喵# 普通可执行文件喵
# add_executable(<name> [WIN32] [MACOSX_BUNDLE] [EXCLUDE_FROM_ALL] [source1] [source2 ...])# 导入的可执行文件喵
# add_executable(<name> IMPORTED [GLOBAL])# 可执行文件的别名喵
# add_executable(<name> ALIAS <target>)# =============================================================================
# 库喵# 普通库喵
# add_library(<name> [STATIC|SHARED|MODULE] [EXCLUDE_FROM_ALL] [<source>...])
# STATIC 为静态库, SHARED 为动态库, MODULE 为运行时库,指定 EXCLUDE_FROM_ALL 则排除在生成过程中# 导入库,从外部导入库喵
# add_library(<name> <STATIC|SHARED|MODULE|UNKNOWN|OBJECT> IMPORTED [GLOBAL])
# 指定 GLOBAL 则全局可见# 接口库喵,不会编译和生成,可用以安装和导出,比如纯头文件库
# add_library(<name> INTERFACE) # 对象库喵,编译但不链接
# add_library(<name> OBJECT [<source>...]) # 库的别名喵
# add_library(<name> ALIAS <target>)# =============================================================================
# 链接喵# 将库链接到以后添加的所有目标喵
# link_libraries([item1 [item2 [...]]] [[debug|optimized|general] <item>] ...)# 链接目标 target 和 item
# target_link_libraries(<target> ... <item>... ...)# =============================================================================
# 源文件喵# 查找目录中的所有源文件喵
# aux_source_directory(<dir> <variable>)# 向目标添加源文件喵
# target_sources(<target> <INTERFACE|PUBLIC|PRIVATE> [items1...] [...])# █████████████████████████████████████████████████████████████████████████████
# -- 预处理宏定义喵
# █████████████████████████████████████████████████████████████████████████████# 添加预处理宏定义喵,前导的 -D 将被删除
# add_compile_definitions(<definition> ...)# 为一个目标添加宏定义喵,前导的 -D 将被删除,目标必须由 add_executable 或 add_library 创建,不能是 ALIAS target
# target_compile_definitions(<target> <INTERFACE|PUBLIC|PRIVATE> [items1...] [...])# █████████████████████████████████████████████████████████████████████████████
# -- 目录喵
# █████████████████████████████████████████████████████████████████████████████# 添加到全局的包含目录列表 INCLUDE_DIRECTORIES ,指定 SYSTEM 则目录在某些平台为系统包含目录
# include_directories([AFTER|BEFORE] [SYSTEM] dir1 [dir2 ...])# 添加到全局的库目录列表 LINK_DIRECTORIES
# link_directories([AFTER|BEFORE] dir1 [dir2 ...])# 指定目标的包含目录,指定 SYSTEM 则目录在某些平台为系统包含目录
# target_include_directories(<target> [SYSTEM] [AFTER|BEFORE] <INTERFACE|PUBLIC|PRIVATE> [items1...] [...])# 指定目标库目录喵
# target_link_directories(<target> [BEFORE] <INTERFACE|PUBLIC|PRIVATE> [items1...] [...])# AFTER 和 BEFORE 指定添加位置(末尾和头部)# █████████████████████████████████████████████████████████████████████████████
# -- 依赖喵
# █████████████████████████████████████████████████████████████████████████████# 添加依赖项可以保证被依赖项总是先生成喵
# add_dependencies(<target> [<target-dependency>]...)# █████████████████████████████████████████████████████████████████████████████
# -- 安装喵
# █████████████████████████████████████████████████████████████████████████████# 通用选项喵
# [DESTINATION <dir>] # 安装文件的目标目录喵
# [PERMISSIONS permissions...] # 安装文件的权限喵,可为 OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_WRITE GROUP_EXECUTE WORLD_READ WORLD_WRITE WORLD_EXECUTE SETUID SETGID
# [CONFIGURATIONS [Debug|Release|...]] # 为之后出现的项指定配置喵
# [COMPONENT <component>] # 指定组件名称喵
# [OPTIONAL] # 要安装的文件不存在则不报错喵
# [EXCLUDE_FROM_ALL] # 从完整安装中排除,仅作为组件特定安装的一部分安装
# [RUNTIME_DEPENDENCY_SET <set-name>] # 将依赖项添加到指定的运行时依赖集中。可使用 install(RUNTIME_DEPENDENCY_SET) 命令安装依赖集# 安装目标喵
# install(TARGETS targets... # 安装的目标喵
# [EXPORT <export-name>] # 将目标导出为 export-name
# [RUNTIME_DEPENDENCIES args...| # 同时安装目标的所有运行时依赖项
# RUNTIME_DEPENDENCY_SET <set-name>]
# [[ARCHIVE|LIBRARY|RUNTIME|OBJECTS|FRAMEWORK|BUNDLE|PRIVATE_HEADER|PUBLIC_HEADER|RESOURCE|FILE_SET <set-name>|CXX_MODULES_BMI] # 安装项的类型
# [DESTINATION <dir>] [PERMISSIONS permissions...] [CONFIGURATIONS [Debug|Release|...]] [COMPONENT <component>] [OPTIONAL] [EXCLUDE_FROM_ALL]
# [NAMELINK_COMPONENT <component>] # 指定组件的符号链接名称
# [NAMELINK_ONLY|NAMELINK_SKIP] # 符号链接
# ] [...]
# [INCLUDES DESTINATION [<dir> ...]]) # 同时将指定目录添加到项目的 INTERFACE_INCLUDE_DIRECTORIES 中# 安装导入的运行时组件喵
# install(IMPORTED_RUNTIME_ARTIFACTS targets... # 安装的组件喵
# [RUNTIME_DEPENDENCY_SET <set-name>]
# [[LIBRARY|RUNTIME|FRAMEWORK|BUNDLE] # 安装项的类型喵
# [DESTINATION <dir>] [PERMISSIONS permissions...] [CONFIGURATIONS [Debug|Release|...]] [COMPONENT <component>] [OPTIONAL] [EXCLUDE_FROM_ALL]
# ] [...])# 安装文件喵
# install(<FILES|PROGRAMS> files... # 安装的文件喵
# TYPE <type> | DESTINATION <dir> # 文件类型或安装位置喵,提供类型时将根据类型自行选择位置
# [PERMISSIONS permissions...] [CONFIGURATIONS [Debug|Release|...]] [COMPONENT <component>] [OPTIONAL] [EXCLUDE_FROM_ALL]
# [RENAME <name>]) # 将文件重命名# 安装目录喵
# install(DIRECTORY dirs...
# TYPE <type> | DESTINATION <dir> # 文件类型或安装位置喵,提供类型时将根据类型自行选择位置
# [FILE_PERMISSIONS permissions...] # 文件权限
# [DIRECTORY_PERMISSIONS permissions...] # 文件夹权限
# [USE_SOURCE_PERMISSIONS] # 使用源文件的权限
# [MESSAGE_NEVER] # 安装时不输出消息
# [CONFIGURATIONS [Debug|Release|...]] [COMPONENT <component>] [OPTIONAL] [EXCLUDE_FROM_ALL]
# [FILES_MATCHING] # 仅安装通过过滤的文件
# [[PATTERN <pattern> | REGEX <regex>] # 文件过滤选择
# [EXCLUDE] # 跳过匹配的文件
# [PERMISSIONS permissions...] # 文件的权限
# ] [...])# 自定义安装逻辑喵
# install([[SCRIPT <file>] # 调用给定的 CMake 脚本文件
# [CODE <code>]] # 调用给定的 CMake 代码
# [ALL_COMPONENTS | COMPONENT <component>] # 为哪些组件执行此逻辑
# [EXCLUDE_FROM_ALL] [...])# 安装导出喵
# install(EXPORT <export-name> # 安装的导出
# DESTINATION <dir> [PERMISSIONS permissions...]
# [NAMESPACE <namespace>] # 命名空间
# [FILE <name>.cmake] # 文件名
# [CONFIGURATIONS [Debug|Release|...] [COMPONENT <component>] [EXCLUDE_FROM_ALL]
# [CXX_MODULES_DIRECTORY <directory>] # 保存 C++ 模块的目录
# [EXPORT_LINK_INTERFACE_LIBRARIES]) # 导出 (IMPORTED_)?LINK_INTERFACE_LIBRARIES(_<CONFIG>)? 命名的属性的内容# 安装运行时依赖喵
# install(RUNTIME_DEPENDENCY_SET <set-name> # 安装的依赖集合
# [[LIBRARY|RUNTIME|FRAMEWORK] # 依赖类型
# [DESTINATION <dir>] [PERMISSIONS permissions...] [CONFIGURATIONS [Debug|Release|...]] [COMPONENT <component>] [OPTIONAL] [EXCLUDE_FROM_ALL]
# [NAMELINK_COMPONENT <component>] # 指定组件的符号链接名称
# ] [...]
# [PRE_INCLUDE_REGEXES regexes...] [PRE_EXCLUDE_REGEXES regexes...] [POST_INCLUDE_REGEXES regexes...] [POST_EXCLUDE_REGEXES regexes...] [POST_INCLUDE_FILES files...] [POST_EXCLUDE_FILES files...] [DIRECTORIES directories...]) # 由 file(GET_RUNTIME_DEPENDENCIES) 使用# █████████████████████████████████████████████████████████████████████████████
# -- 导出喵
# █████████████████████████████████████████████████████████████████████████████# 导出目标喵
# export(TARGETS <target>... [NAMESPACE <namespace>] # 目标名和命名空间喵
# [APPEND] # 指定则为追加,否则为覆盖喵
# FILE <filename> # 导出的文件名喵
# [EXPORT_LINK_INTERFACE_LIBRARIES] # 在导出中包含以模式 (IMPORTED_)?LINK_INTERFACE_LIBRARIES(_<CONFIG>)? 命名的属性的内容
# [CXX_MODULES_DIRECTORY <directory>]) # 将 C++ 模块属性导出到给定目录下的文件中# 导出导出喵,创建一个文件 <filename> ,外部项目可以通过包含该文件,从当前项目中导入目标
# export(EXPORT <export-name> [NAMESPACE <namespace>] # 导出名和命名空间喵
# [FILE <filename>] # 导出的文件名喵
# [CXX_MODULES_DIRECTORY <directory>] # 将 C++ 模块属性导出到给定目录下的文件中
# [EXPORT_PACKAGE_DEPENDENCIES]) # 由 find_dependency() 使用喵# 导出包喵,但是默认不操作喵喵
# export(PACKAGE <PackageName>)# 配置导出喵,配置导出的参数
# export(SETUP <export-name> # 要配置的导出名称
# [PACKAGE_DEPENDENCY <dep> # 依赖
# [ENABLED (<bool-true>|<bool-false>|AUTO)] # 控制是否导出依赖关系
# [EXTRA_ARGS <args>...] # 传递给 find_dependency 的附加参数
# ] [...]
# [TARGET <target> # 导出的目标
# [XCFRAMEWORK_LOCATION <location>] # 疑似 XCode 使用
# ] [...])# █████████████████████████████████████████████████████████████████████████████
# -- 编译链接选项喵
# █████████████████████████████████████████████████████████████████████████████# 向目标添加预编译头文件喵
# target_precompile_headers(<target> <INTERFACE|PUBLIC|PRIVATE> [header1...] [...])# 添加全局编译选项喵,如 W4 : warning level 4
# add_compile_options(<option> ...)# 为目标添加编译选项喵
# target_compile_options(<target> [BEFORE] <INTERFACE|PUBLIC|PRIVATE> [items1...] [...])# 向目标添加链接选项喵
# target_link_options(<target> [BEFORE] <INTERFACE|PUBLIC|PRIVATE> [items1...] [...])# 向目标添加编译特性喵,如 -std=gnu++11 等
# target_compile_features(<target> <PRIVATE|PUBLIC|INTERFACE> <feature> [...])# █████████████████████████████████████████████████████████████████████████████
# -- 自定义编译链接步骤喵
# █████████████████████████████████████████████████████████████████████████████# =============================================================================
# 自定义命令喵# 用于生成输出文件喵
# add_custom_command(OUTPUT output1 [output2 ...] # 输出文件喵
# COMMAND command1 [ARGS] [args1...] # 命令和参数喵
# [COMMAND command2 [ARGS] [args2...] ...] # 命令和参数喵
# [MAIN_DEPENDENCY depend] # 指定命令的主要输入源文件喵
# [DEPENDS [depends...]] # 依赖文件喵
# [BYPRODUCTS [files...]] # 指定命令预期生成的文件喵
# [IMPLICIT_DEPENDS <lang1> depend1 [<lang2> depend2] ...] # 隐式依赖喵
# [WORKING_DIRECTORY dir] # 执行目录喵
# [COMMENT comment] # 执行命令前输出的提示信息喵
# [DEPFILE depfile] # 依赖文件喵
# [JOB_POOL job_pool] # Ninja 生成器相关
# [JOB_SERVER_AWARE <bool>] # 命令是 GNU Make job server aware
# [VERBATIM] [APPEND] [USES_TERMINAL] # VERBATIM 保证了命令参数的字面意义喵; APPEND 将 COMMAND 和 DEPENDS 选项值附加到指定第一个输出的自定义命令喵; USES_TERMINAL 授予直接访问终端的权限喵
# [CODEGEN] # 添加到代码生成器全局目标喵
# [COMMAND_EXPAND_LISTS] # 命令参数中的列表将被扩展喵
# [DEPENDS_EXPLICIT_ONLY]) # 指示命令的 DEPENDS 参数表示命令所需的所有文件,并且不需要隐式依赖关系# 用于建立事件喵
# 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] # 保证了命令参数的字面意义喵
# [COMMAND_EXPAND_LISTS] # 命令参数中的列表将被扩展喵
# [USES_TERMINAL]) # 授予直接访问终端的权限喵# =============================================================================
# 自定义目标喵# 添加一个自定义的目标,每次都会重新构建喵
# 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] # Ninja 生成器相关
# [JOB_SERVER_AWARE <bool>] # 命令是 GNU Make job server aware
# [VERBATIM] [USES_TERMINAL] # VERBATIM 保证了命令参数的字面意义喵; USES_TERMINAL 授予直接访问终端的权限喵
# [COMMAND_EXPAND_LISTS] # 命令参数中的列表将被扩展喵
# [SOURCES src1 [src2...]]) # 源文件喵
示例项目
cmake_minimum_required(VERSION 3.30)message("\n======================================================================")
message(" -- 示例项目喵")
message("======================================================================\n")# 设置 C++ 特性,使用 C++11 喵
set(CMAKE_CXX_STANDARD 11) # 默认为空
set(CMAKE_CXX_STANDARD_REQUIRED True) # 默认为空# 创建项目喵
project(HeadEnlargerSample VERSION 1.2.3.4)# 使用 configure_package_config_file 和 write_basic_package_version_file 需 包含 CMakePackageConfigHelpers 喵
include(CMakePackageConfigHelpers)# 安装目录常量喵:
# lib 目录在 linux 下为 /usr/local/lib 喵
# include 命令在 linux 下为 /usr/local/include 喵# █████████████████████████████████████████████████████████████████████████████
# █████████████████████████████████████████████████████████████████████████████# =============================================================================
# 静态库喵# 添加一个静态库喵
add_library(s_lib STATIC third_party/static_lib/src/s_lib.cpp)
# 添加配置文件喵
configure_file("third_party/static_lib/config/lib_config.h.in" "s_lib/config.h")
# 添加包含目录喵
target_include_directories(s_lib PRIVATE third_party/static_lib/include "${PROJECT_BINARY_DIR}/s_lib")
target_include_directories(s_lib INTERFACE$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/third_party/static_lib/include> # 本库的包含目录喵$<INSTALL_INTERFACE:include/cmake/s_lib>) # 使用方的包含目录喵# 生成包含导出内容的配置文件,供 find_package 使用喵
configure_package_config_file("third_party/static_lib/config/lib_config.cmake.in" # 母版文件喵"s_libConfig.cmake" # 生成的目标,名称格式特定喵INSTALL_DESTINATION "lib/cmake/s_lib" # 安装位置喵NO_SET_AND_CHECK_MACRO NO_CHECK_REQUIRED_COMPONENTS_MACRO)
# 为配置文件生成版本文件喵
write_basic_package_version_file("s_libConfigVersion.cmake" # 生成的目标,名称格式特定喵VERSION ${HeadEnlargerSample_VERSION} # 版本号喵COMPATIBILITY AnyNewerVersion) # 向后兼容喵# 安装库喵
install(TARGETS s_lib # 库喵DESTINATION lib/cmake/s_lib # 安装位置喵EXPORT s_lib_ex) # 导出名称喵
# 安装头文件喵
install(FILES third_party/static_lib/include/s_lib.h # 头文件喵DESTINATION include/cmake/s_lib) # 安装位置喵# 导出库喵
export(EXPORT s_lib_ex # 导出喵FILE s_lib_ex.cmake) # 导出文件喵
# 安装导出喵
install(EXPORT s_lib_ex # 导出喵FILE s_lib_ex.cmake # 导出文件喵DESTINATION lib/cmake/s_lib) # 安装位置喵# 安装配置文件,供 find_package 使用喵
install(FILES"${CMAKE_CURRENT_BINARY_DIR}/s_libConfig.cmake""${CMAKE_CURRENT_BINARY_DIR}/s_libConfigVersion.cmake"DESTINATION lib/cmake/s_lib) # 安装位置喵# █████████████████████████████████████████████████████████████████████████████
# █████████████████████████████████████████████████████████████████████████████# =============================================================================
# 动态库喵# 添加一个动态库喵
add_library(d_dll SHARED third_party/shared_dll/src/d_dll.cpp)
# 添加配置文件喵
configure_file("third_party/shared_dll/config/dll_config.h.in" "d_dll/config.h")
# 添加包含目录喵
target_include_directories(d_dll PRIVATE third_party/shared_dll/include "${PROJECT_BINARY_DIR}/d_dll")
target_include_directories(d_dll INTERFACE$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/third_party/shared_dll/include> # 本库的包含目录喵$<INSTALL_INTERFACE:include/cmake/d_dll>) # 使用方的包含目录喵# 生成包含导出内容的配置文件,供 find_package 使用喵
configure_package_config_file("third_party/shared_dll/config/dll_config.cmake.in" # 母版文件喵"d_dllConfig.cmake" # 生成的目标喵INSTALL_DESTINATION "lib/cmake/d_dll" # 安装位置喵NO_SET_AND_CHECK_MACRO NO_CHECK_REQUIRED_COMPONENTS_MACRO)
# 为配置文件生成版本文件喵
write_basic_package_version_file("d_dllConfigVersion.cmake" # 生成的目标喵VERSION ${HeadEnlargerSample_VERSION} # 版本号喵COMPATIBILITY AnyNewerVersion) # 向后兼容喵# 安装库喵
install(TARGETS d_dll # 库喵DESTINATION lib/cmake/d_dll # 安装位置喵EXPORT d_dll_ex) # 导出名称喵
# 安装头文件喵
install(FILES third_party/shared_dll/include/d_dll.h # 头文件喵DESTINATION include/cmake/d_dll) # 安装位置喵# 导出喵
export(EXPORT d_dll_ex # 导出喵FILE d_dll_ex.cmake) # 导出文件喵
# 安装导出喵
install(EXPORT d_dll_ex # 导出喵FILE d_dll_ex.cmake # 导出文件喵DESTINATION lib/cmake/d_dll) # 安装位置喵# 安装配置文件,供 find_package 使用喵
install(FILES"${CMAKE_CURRENT_BINARY_DIR}/d_dllConfig.cmake""${CMAKE_CURRENT_BINARY_DIR}/d_dllConfigVersion.cmake"DESTINATION lib/cmake/d_dll) # 安装位置喵# █████████████████████████████████████████████████████████████████████████████
# █████████████████████████████████████████████████████████████████████████████# =============================================================================
# 可执行文件喵# 添加一个可执行文件喵
add_executable(main src/main.cpp)
# 添加配置文件喵
configure_file("config/sampleConfig.h.in" "hes_config.h")
# 添加包含目录喵
target_include_directories(main PUBLIC include "${PROJECT_BINARY_DIR}")
# 链接喵
target_link_libraries(main s_lib d_dll)# =============================================================================
# 配置依赖关系喵add_dependencies(main s_lib d_dll)
项目文件
CMakeFinal.zip
``