一文读懂CMake

这篇文章是站在VS角度描述CMake基本语法的。具体语法对应关系,参照下表。

CMake函数对应VS相关设置

VS相关设置CMake函数
指定包含头文件目录target_include_directories
指定链接库目录target_link_directories
指定链接库target_link_libraries
指定C++标准set(CMAKE_CXX_STANDARD 11)
指定编译器版本cmake -G “Visual Studio 12 2013”
指定平台集cmake -G “Visual Studio 12 2013 Win64”
指定编译类型set(CMAKE_BUILD_TYPE “Debug”)等价于g++ -g
指定预编译宏add_definitions(-Dxxx -Dyyy ) 必须-D开头
指定解决方案名称project(xxxx)
文件分类source_group(“folder_name” file_list)

CMake常见内置变量

CMake内置变量说明(路径都是全路径)
PROJECT_NAMECMakeList.txt里设置的project_name
CMAKE_BUILD_TYPE设置当前工程编译类型(Debug,Release),默认debug
BUILD_TYPE当前工程的编译类型(Debug,Release)
PROJECT_SOURCE_DIR根CMakeLists.txt所在的路径
PROJECT_BINARY_DIR工程的构建目录(build目录)
CMAKE_CURRENT_SOURCE_DIR当前’CMakeLists.txt’ 所在的路径
CMAKE_CURRENT_BINARY_DIR当前正在处理的’构建目录’
CMAKE_CURRENT_LIST_DIR当前处理的’cmake文件’所在的目录
CMAKE_CURRENT_LIST_FILE当前处理的’CMakeLists.txt或cmake’文件的全路径
CMAKE_CURRENT_LIST_LINE当前处理的’CMakeLists.txt或cmake’文件的’行号’
CMAKE_PROJECT_NAME整个项目’配置的project_name
LIBRARY_OUTPUT_DIRECTORY库的存放目录(需要用户设置)
CMAKE_RUNTIME_OUTPUT_DIRECTORY可执行文件的存放目录(需要用户设置,必须在设置可执行文件之前设置)

变量作用域

当调用add_subdirectory的时候CMake会为处理该目录的CMakeLists.txt文件创建了一个子作用域。作用域规则如下
1.父作用域中的所有变量对子作用域均可见,但传递的仅是父作用域变量的副本,子作用域对变量的修改不会传递到父作用域
2.子作用域中的任何新变量对父作用域不可见
3.如果想修改父作用域的变量需要指定PARENT_SCOPE

#PARENT_SCOPE关键字表示修改父作用域的变量,不修改当前作用域
eg://如果父作用域myvar=top,
set(myvar bar PARENT_SCOPE)
#调用PARENT_SCOPE之后父作用域${myvar}=bar,当前左右域${myvar}=top

CMake 配置和编译

mkdir build
cd build
#Config vs2019 win32,如果不指定win32则默认为x64
cmake -G "Visual Studio 16 2019" -A Win32 ..\
#编译项目
cmake --build .

CXX 标准设置

#require c++11 and disable c++ extension
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

设置预编译头

#增加预编译头
PRIVATE:预编译头文件仅用于定义它们的目标。
PUBLIC:预编译头文件用于定义它们的目标,且自动传播给依赖这个目标的其他目标。
INTERFACE:预编译头文件仅用于那些依赖这个目标的其他目标。

target_precompile_headers(target PRIVATE <header1> <header2>)

# 示例:在项目中配置预编译头文件
target_precompile_headers(demo PRIVATE
    "common/pch.h"
    "utils/UtilityHeaders.h"
)

MD、MT设置

#CMAKE 2.8有效,CMAKE 3.X可能无效,经测试3.20无效
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd")

#均有效
target_compile_options(${TARGET_NAME} PRIVATE "$<$<C_COMPILER_ID:MSVC>:$<IF:$<CONFIG:Debug>,/MTd,/MT>>")
or
add_compile_options("$<$<C_COMPILER_ID:MSVC>:$<IF:$<CONFIG:Debug>,/MTd,/MT>>")

添加exe[win32]程序

CMake默认生成的vs工程为console程序。如果想生成windows窗口程序需要指定链接属性。

#win32 程序
#方法一
add_executable(hello WIN32 hello.cpp)
#方法二
add_executable(hello hello.cpp)


set_target_properties(hello PROPERTIES LINK_FLAGS "/SUBSYSTEM:WINDOWS")
  
  
 #控制台程序
 add_executable(hello hello.cpp)

查找并引入库

#指定库的安装目录
list(APPEND CMAKE_PREFIX_PATH "d://123//xhttp")
#查找XHTTP
find_package(XHTTP REQUIRED)
message("XHTTP_FOUND=${XHTTP_FOUND}")

#如果查找库成功,则查找对应的头文件所在位置
if(XHTTP_FOUND)
   target_link_libraries(hello XHttp::XHTTP)
   #find header path
   find_path(XHTTP_INCLUDES NAMES "xhttpapi.h")
   message("XHTTP_INCLUDES=${XHTTP_INCLUDES}")
   #引入头文件
   include_directories(${XHTTP_INCLUDES})
endif(XHTTP_FOUND)

生成器表达式

生成器表达式是在生成构建系统的时候展开的,所以不能通过配置CMakeLists.txt阶段通过message命令打印信息

#表达式格式形态
1. $<condition:true_string>:如果条件为真,则结果为true_string,否则为空
2. $<IF:condition,str1,str2>:如果条件为真,则结果为str1,否则为str2

#CONFIG
1.获取所有变量值:$<CONFIG>
2.判断值是否存在于变量中:$<CONFIG:cfgs> eg:$<CONFIG:Debug>

#编译目标查询(add_executable,add_library) eg:add_executable(demo )
1. $<TARGET_FILE:traget>:获取target的绝对文件路径,eg:$<TARGET_FILE:demo>
2. $<TARGET_FILE_DIR:traget>:获取target的绝对文件目录,eg:$<TARGET_FILE_DIR:demo>
3. $<TARGET_FILE_NAME:traget>:获取target的文件名(含后缀),eg:$<TARGET_FILE_NAME:demo>
4. $<TARGET_FILE_BASE_NAME:traget>:获取target的文件名(不含后缀),eg:$<TARGET_FILE_BASE_NAME:demo>

调试(在cmake build之后检查是否符合预期)

#build完成之后打印信息
add_custom_command(TARGET hello POST_BUILD COMMAND ${CMAKE_COMMAND} -E echo "\"$<$<CONFIG:Debug>:debug mode>,$<PLATFORM_ID>\"")

是否64位

#根据不同的模式连接不同位置的库
if(CMAKE_CL_64)
    target_link_directories(${TARGET_NAME} PRIVATE $<IF:$<CONFIG:Debug>,${PROJECT_SOURCE_DIR}/lib/x64/Debug,${PROJECT_SOURCE_DIR}/lib/x64/Release>)
else()
    target_link_directories(${TARGET_NAME} PRIVATE $<IF:$<CONFIG:Debug>,${PROJECT_SOURCE_DIR}/lib/x86/Debug,${PROJECT_SOURCE_DIR}/lib/x86/Release>)
endif()

当前运行平台判断

# 在 Linux 平台
CMAKE_HOST_SYSTEM_NAME = "Linux"
CMAKE_HOST_UNIX = 1
CMAKE_HOST_WIN32 = 空
UNIX = 1
WIN32 = 空
 
# 在 Windows 平台
CMAKE_HOST_SYSTEM_NAME = "Windows"
CMAKE_HOST_UNIX = 空
CMAKE_HOST_WIN32 = 1
UNIX = 空
WIN32 = 1

#判断方法一:通过SYSTEM_NAME
if(CMAKE_HOST_SYSTEM_NAME MATCHES "Linux")
	message(STATUS "current platform: Linux ")
elseif(CMAKE_HOST_SYSTEM_NAME MATCHES "Windows")
	message(STATUS "current platform: Windows ")
else()
	message(STATUS "current platform: unkonw ")
endif()

#判断方法二:通过BOOL值
if(CMAKE_HOST_UNIX)
	message(STATUS "current platform: Linux ")
elseif(CMAKE_HOST_WIN32)
	message(STATUS "current platform: Windows ")
else()
	message(STATUS "current platform: unkonw ")
endif()

指定编译模式

#方法一:Cmake文件中设置变量CMAKE_BUILD_TYPE 
set(CMAKE_BUILD_TYPE "Debug")

#方法二:cmake 执行命令的时候设置变量CMAKE_BUILD_TYPE 
cmake ./ -DCMAKE_BUILD_TYPE:STRING=Debug 
#如果在windows平台
#release版本
cmake --build . --config Release
#debug版本
cmake --build . --config Debug

#如果在linux平台
#release版本
cmake ../ -DCMAKE_BUILD_TYPE=Release
cmake --build .
#Debug版本
cmake ../ -DCMAKE_BUILD_TYPE=Debug
cmake --build .

链接第三方库和头文件包含

#eg:hellow 链接libmymath.a,libtest.a等库,每个库之间以空格分开
target_link_libraries(hellow PUBLIC mymath test)
#指定库位置
target_link_directories(hellow PUBLIC 
						"/home/jef/work/mymath "
						"/home/jef/work/test"
						)
#指定lib头文件位置
target_include_directories(hellow PUBLIC 
                        "/home/jef/work/test/include"
                        "${PROJECT_SOURCE_DIR}/mymath"
                        )

增加预定义宏

#增加预定义宏,eg:增加宏HELLOW
add_definitions(-DHELLO)

#删除预定义宏,eg:删除宏HELLOW
remove_definitions(-DHELLO)

#针对特定目标增加预定义宏 HELLOW2
target_compile_definitions(target PRIVATE HELLOW2)

#define MY_MACRO 233
target_compile_definitions(main PUBLIC MY_MACRO=233)
target_compile_definitions(main PUBLIC MY_NAME="jefcats")

#代码中使用
#ifdef HELLO
#else
#endif

开关选项控制option

通过option的ON和off来控制编译流程

#variable:定义选项名称
#help_text:说明选项的含义
#value:定义选项默认状态,一般是OFF或者ON,除去ON之外,其他所有值都为认为是OFF。
option(<variable> "<help_text>" [value])

eg:如果定义USE_OPEN_SLL=ON,则定义宏USE_OPEN_SLL否则不定义

option(USE_OPEN_SLL "USE_OPEN_SLL" ON)

if (USE_OPEN_SLL)
	add_definitions(-DUSE_OPEN_SLL)
	message(STATUS "USE_OPEN_SLL on")
else ()
	message(STATUS "USE_OPEN_SLL off")
endif()
cmake -G "Visual Studio 12 2013 Win64" ../ -DUSE_OPEN_SLL=ON

添加动态库、静态库

#全局设置,默认值由BUILD_SHARED_LIBS决定
#如果设置BUILD_SHARED_LIBS为YES,则add_library默认为动态库
set(BUILD_SHARED_LIBS YES)
add_library(hello hellow.cpp)

#明确指定动态库
add_library(hello SHARED hellow.cpp)
#明确指定静态库
add_library(hello STATIC hellow.cpp)

指定项目依赖项(指定项目生成顺序)

#例如当前项目hellow依赖mymath.lib
add_dependencies(hellow mymath)

执行生成事件

add_custom_command

参数含义
PRE_BUILD在目标中执行任何其他规则之前运行
PRE_LINK在编译源代码之后,链接二进制文件或库文件之前运行
POST_BUILD在目标内所有其他规则均已执行后运行
#PRE_BUILD 生成前执行command
#POST_BUILD 生成后执行command
#PRE_LINK 源代码编译之后链接之前执行command
#均为构建阶段命令
add_custom_command() 
add_custom_target()

#配置阶段执行命令
execute_process()

#查看支持的完整命令集
cmake -E help

#使用系统内置命令
COMMAND rmdir /S /Q "d:\\123"

#使用CMake内置命令,平台无关性
COMMAND  "${CMAKE_COMMAND}" -E rm -R "d:\\123"


#demo
  #to avoid copy demo.dll error
  add_custom_command(TARGET demo PRE_BUILD
  COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_BINARY_DIR}/lib/Debug
  COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_BINARY_DIR}/lib/Release
  COMMAND ${CMAKE_COMMAND} -E touch ${PROJECT_BINARY_DIR}/lib/Debug/demo.dll
  COMMAND ${CMAKE_COMMAND} -E touch ${PROJECT_BINARY_DIR}/lib/Release/demo.dll)

  #copy demo dll to bin dir
  add_custom_command(TARGET demo POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E copy_if_different
    ${PROJECT_BINARY_DIR}/lib/Debug/demo.dll ${PROJECT_BINARY_DIR}/bin/Debug/demo.dll
    COMMAND ${CMAKE_COMMAND} -E copy_if_different
    ${PROJECT_BINARY_DIR}/lib/Release/demo.dll ${PROJECT_BINARY_DIR}/bin/Release/demo.dll)

执行custom_target

#定义custom target
add_custom_target(cleancache
    COMMAND ${CMAKE_COMMAND} -E remove -rf ${CMAKE_BINARY_DIR}/CMakeCache.txt
    COMMENT "Cleaning cache files"
)

#执行custom target
 cmake --build . --target cleancache

指定二进制文件或者库文件生成位置

#将输出目录保存在统一变量中
if(CMAKE_CL_64)
    set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib/x64/$<IF:$<CONFIG:Debug>,Debug,Release>)
    set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin/x64/$<IF:$<CONFIG:Debug>,Debug,Release>)
else()
    set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib/x86/$<IF:$<CONFIG:Debug>,Debug,Release>)
    set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin/x86/$<IF:$<CONFIG:Debug>,Debug,Release>)
endif()

#开始设置输出目录set_target_properties、get_target_properties
set_target_properties(hello PROPERTIES
    ARCHIVE_OUTPUT_DIRECTORY ${LIBRARY_OUTPUT_DIRECTORY}
    LIBRARY_OUTPUT_DIRECTORY ${LIBRARY_OUTPUT_DIRECTORY}
    RUNTIME_OUTPUT_DIRECTORY ${EXECUTABLE_OUTPUT_PATH}
)

设置Target的生成目标名称

#设置目标输出名称(不包括后缀)
set_target_properties(demo PROPERTIES OUTPUT_NAME "demox")

路径函数

  1. cmake 3.20 及以后支持cmake_path
  2. cmake 3.20 之前get_filename_componet和file

cmake_path
cmake_path不访问文件系统,仅仅对路径的语法操作。所以对文件信息和状态是无感知的。
eg:C:/one/two/start/middle.end
在这里插入图片描述

cmake_path(GET pathVar <COMP> [LAST_ONLY] outVar)
cmake_path(SET pathVar [NORMALIZE] input])

#LAST_ONLY 只能在<COMP>是EXTENSION或STEM使用。EXTNESION默认从最左边的第一个点(.)开始。如果指定LAST_ONLY则使用最右边的点开始。
#pathVar必须是一个变量


#demo1
set(tpath "d://123//123.txt")
cmake_path(GET tpath PARENT_PATH PARENT_DIR)
message("PARENT_DIR=${PARENT_DIR}")

#demo2
cmake_path(SET tpath NORMALIZE "d://123//123.txt")
cmake_path(GET tpath PARENT_PATH PARENT_DIR)
message("PARENT_DIR=${PARENT_DIR}")

get_filname_component

get_filename_component(outVar input component [CACHE]])
component说明
DIRECTORY获取文件目录
NAME获取文件名,包括后缀
NAME_WE获取文件名,不包括后缀(左边第一个点)
NAME_WLE获取文件名,不包括后缀(右边最后一个点)
EXT后缀名,左边第一个点开始
LAST_EXT后缀名,右边最后一个点开始
set(tpath "d://123//123.txt")
#获取目录 d://123
get_filename_component(dir ${tpath} DIRECTORY))

file函数

#file(<command> <args>)
#常用命令
GLOB: 查找与模式匹配的文件。
GLOB_RECURSE: 递归查找与模式匹配的文件
COPY:复制文件
READ: 读取文件内容。
WRITE: 写入文件内容。
APPEND: 追加内容到文件。
MAKE_DIRECTORY: 创建目录。
REMOVE: 删除文件。
REMOVE_RECURSE: 递归删除目录及其内容。
DOWNLOAD 下载
UPLOAD 上传
GENERATE 生成器表达式

文件匹配:支持通配符

示例说明
*.txt表示以txt结尾的文件
foo?.txt问号通配符可以匹配任意字符[0个字符或者1个字符]
bar[0-9].txt正则表达式[0-9],表示barX.txt的文件,X代表0-9中的任意一个数字
//.png/*/支持任意目录
#获取当前所有c,cpp文件
file(GLOB SRC_FILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} 
${CMAKE_CURRENT_SOURCE_DIR}/*.c ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
foreach(SRC_FILE ${SRC_FILES})
    message("SRC_FILE=${SRC_FILE}")
endforeach(SRC_FILE)

#file GLOB 默认获取的是绝对路径如果指定了RELATIVE则会取相对于RELATIVE的路径。

在这里插入图片描述

文件分类source_group

通过上述生成的工程文件没有分类,并且没有包含头文件。下面我们将按照目录结构进行分类(不使用lib)。

在这里插入图片描述
注意涉及函数filesource_group

#获取当前目录下所有的头文件并进行分类
#GLOB-只索引当前目录,不包括子目录
#GLOB_RECURSE-索引当前目录以及包括子目录 
file(GLOB project_header_files ${CMAKE_CURRENT_SOURCE_DIR}/*.h)

#进行头文件,只能是相同类型的文件,否则会失败
source_group("Header Files" ${project_header_files})

#获取mymath目录下的头文件和源文件并且进行分类
#获取mymath目录下所有的文件这里并没有使用aux_source_directory("${CMAKE_CURRENT_SOURCE_DIR}/mymath" maths_file)
file(GLOB math_header_files ${CMAKE_CURRENT_SOURCE_DIR}/mymath/*.h)
file(GLOB math_src_files ${CMAKE_CURRENT_SOURCE_DIR}/mymath/*.cpp)

#source_group有两种写法
#自己定义folder,名称
#source_group("mymath" FILES ${math_header_files} ${math_src_files})
#根据目录结构截取生成目录名称 files的绝对路径去掉${CMAKE_CURRENT_SOURCE_DIR},即拼成目录名称
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${math_src_files} ${math_header_files})

#最后一步也是最重要的一步,一定要添加到target里面,否则也不会展示
add_executable(hellow ${all_file} ${project_header_files} ${math_header_files} ${math_src_files})
cmake -G "Visual Studio 12 2013 Win64" ../ 

此时可以看到文件已经分类,层级分明了。
在这里插入图片描述

配置项目版本号和信息

#设置项目名称和版本
project(Tutorial VERSION 1.0)

#配置头文件传递版本号给源代码
#配置宏定义,配置默认值为ON,如果想关闭 cmake -DUSE_MYMATH=OFF
#option 除了ON之外其他的都默认为OFF
option(USE_MYMATH "user mymath.lib" ON)

#传递字符串给配置文件
set(var_Key "hellow word")
#传递INT给配置文件
set(INT_Key 1)

#输入文件 输出文件
configure_file(hellow_ver.h.in hellow_ver.h)

#由于配置好的文件hellow_ver.h将被写入二进制目录
#所以我们必须将该目录添加到 include 文件的搜索路径中
target_include_directories(hellow PUBLIC 
						"d:/test/include"
                        "${PROJECT_SOURCE_DIR}/mymath"
                        "${PROJECT_BINARY_DIR}"
                        )

hellow_ver.h.in

//配置的项目版本号
#define hellow_VERSION_MAJOR @hellow_VERSION_MAJOR@
#define hellow_VERSION_MINOR @hellow_VERSION_MINOR@

//宏定义
#cmakedefine USE_MYMATH
//注意:${}之间的名称要与cmakedefine后的变量名一样
//变量名称和cmakeLists.txt设置的变量名称相同
#cmakedefine var_Key "@var_Key@”
#cmakedefine INT_Key @INT_Key@

运行之后生成的hellow_ver.h
在这里插入图片描述
如果想取消USE_MYMATH 可以使用 -DUSE_MYMATH=OFF

cmake -G "Visual Studio 12 2013 Win64" ../ -DUSE_MYMATH=OFF

CMake Demo

下面将建立一个简单的Demo,展示一下CMake的简单应用。该工程名称叫cmakedemo,依赖一个mymath库。文件目录结构如下:
在这里插入图片描述

project/CMakeLists.txt

cmake_minimum_required(VERSION 3.10)

project(cmakedemo VERSION 1.0)

option(USE_MYMATH "my math as a lib to use" OFF)
#指定C++执行标准
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED true)
set(CMAKE_BUILD_TYPE "Debug")

#设置输出目录
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)
#so库文件位置
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)
#lib文件位置,windows上有效,linux上无效
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)



#所有源文件
aux_source_directory("${CMAKE_CURRENT_SOURCE_DIR}" src_files)

if(NOT USE_MYMATH)
    aux_source_directory("${CMAKE_CURRENT_SOURCE_DIR}/mymath" math_src_files)
else()
    set(math_src_files "")
    add_subdirectory(mymath)
endif()



#所有头文件
#GLOB-只索引当前目录,不包括子目录
#GLOB_RECURSE-索引当前目录以及包括子目录 
file(GLOB_RECURSE header_files ${CMAKE_CURRENT_SOURCE_DIR}/*.h)

#文件分类,必须加入到executable,否则不会分类
#source_group("Source Files" ${src_files} ${math_src_files})
#source_group("Header Files" ${header_files})
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${src_files} ${math_src_files} ${header_files})

#打印文件
message(STATUS "src_files= ${src_files} ${math_src_files}")
message(STATUS "header_files= ${header_files}")

#添加生成文件
add_executable(main ${src_files} ${math_src_files} ${header_files})

#增加头文件目录
target_include_directories(main PUBLIC 
                        "${CMAKE_CURRENT_SOURCE_DIR}/mymath"
                        )

message(STATUS "include_directories ${CMAKE_CURRENT_SOURCE_DIR}/mymath")

if(USE_MYMATH)
    #添加连接库    
    target_link_libraries(main PUBLIC mymath)
    #添加库目录,这个可以省略,默认会包含进去
    #target_link_directories(main PUBLIC ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}/${BUILD_TYPE})
endif()

project/mymath/CMakeLists.txt(注意子CMake不要和根CMake变量名称重复)


#如果是win则需要定义export接口
if(CMAKE_HOST_WIN32)
	add_definitions(-DMYPATH_EXPORT)
endif()
#所有源文件
aux_source_directory("${CMAKE_CURRENT_SOURCE_DIR}" math_src_files)

#所有头文件
#GLOB-只索引当前目录,不包括子目录
#GLOB_RECURSE-索引当前目录以及包括子目录 
#注意变量名不要和其他CMake文件重复
file(GLOB_RECURSE math_header_files ${CMAKE_CURRENT_SOURCE_DIR}/*.h)

message(STATUS "mymath CMAKE_CURRENT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}")
message(STATUS "mymath math_src_files ${math_src_files}")
message(STATUS "mymath math_header_files ${math_header_files}")
add_library(mymath SHARED ${math_src_files} ${math_header_files})

由于linux下的库不需要像windows那样export所以作为动态库的时候,需要进行环境处理。
project/mymath/mymath.h

#pragma once

#ifdef _WIN32
	#ifdef MYPATH_EXPORT
		#define MYPATH_EXPORT_API extern "C" __declspec(dllexport)
	#else
		#define MYPATH_EXPORT_API extern "C" __declspec(dllimport)
	#endif
#else
	#define MYPATH_EXPORT_API 
#endif // _WIN32


MYPATH_EXPORT_API int add(int a,int b);
cmake ../ -DUSE_MYMATH=ON
cmake --build ./

本文参考:
CMake 教程,至于CMake的安装和测试将在下一章讲解。
CMake判断Release还是Debug环境

函数简单说明

对于CMake,可能存在两种函数:xxxxx和target_xxxx。下面以link_librariestarget_link_libraries来做讲解。
link_libraries:针对全局的,即:CMake的所有模块都会添加该库。
target_link_libraries:针对指定目标的,只有指定目标包含该库。
例如CMake包含连个目标AB,此时如果通过link_libraries(ws2_32 test)包含ws2_32.libtest.lib那么AB都将包含这两个库。但是如果通过target_link_libraries(A PUBLIC ws2_32 test)那么此时仅仅目标A包含这两个库。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值