cmake基本用法

2023-05-16

一、cmake命令

1、基本用法

cmake [选项] <源码路径>

CMake可执行程序是CMake的命令行界面。它可以用脚本对工程进行配置。工程配置设置可以在命令行中使用-D选项指定。使用-i选项,cmake将通过提示交互式地完成该设置。
CMake是一个跨平台的构建系统生成工具。它使用平台无关的CMake清单文件CMakeLists.txt,指定工程的构建过程;源码树的每个路径下都有这个文件。CMake产生一个适用于具体平台的构建系统,用户使用这个系统构建自己的工程。
-D:创建一个CMake的缓存条目
当cmake第一次运行于一个空的构建数时,它会创建一个CMakeCache.txt文件,并且使用可定制的工程设置来填充这个文件。这个选项可以用来指定优先级高于工程的默认值的工程设置值。这个参数可以被重复多次,用来填充所需要数量的缓存条目(cache entries)。
-E: CMake命令行模式
为了真正做到与平台无关,CMake提供了一系列可以用于所有系统上的的命令。以-E参数运行CMake会帮助你获得这些命令的用法。可以使用的命令有:chdir, copy, copy_if_different copy_directory, compare_files, echo, echo_append, environment, make_directory, md5sum, remove_directory, remove, tar, time, touch, touch_nocreate, write_regv, delete_regv, comspec, create_symlink。
例如:

#改变当前的目录,然后执行命令
chdir <dir> <cmd> [<arg>...]

-P : 处理脚本模式
将给定的cmake文件按照CMake语言编写的脚本进行处理。如果要使用-D选项定义变量,-D选项必须在-P选项之前。
参考:
https://www.cnblogs.com/lsgxeva/p/9454443.html
https://cmake.org/cmake/help/v3.6/manual/cmake.1.html?highlight=chdir

2、install

install用于指定在安装时运行的规则。它可以用来安装很多内容,可以包括目标二进制、动态库、静态库以及文件、目录、脚本等:

install(TARGETS <target>... [...])
install({FILES | PROGRAMS} <file>... [...])
install(DIRECTORY <dir>... [...])
install(SCRIPT <file> [...])
install(CODE <code> [...])
install(EXPORT <export-name> [...])

3、include

作用:从文件或模块加载并运行CMake代码。
可以指定载入一个文件,如果定义的是一个模块,那么将在 CMAKE_MODULE_PATH 中搜 索这个模块并载入,如果没有指定CMAKE_MODULE_PATH,那么从当前的CMakeLists.txt所在的目录查找。 载入的内容将在处理到 INCLUDE 语句是直接执行。
用法:

include(<file|module> [OPTIONAL] [RESULT_VARIABLE ]
[NO_POLICY_SCOPE])
    
#例如,加载预定义的cmake模块
include (tools.cmake)

说明:

  • 变量读写范围为调用此指令的调用者的范围,因此,具有动态范围即取决于调用者;
  • 如果“OPTIONAL”被指定,则指定的文件不存在时,不会产生任何错误;
  • 如果“RESULT_VARIABLE”被给予了变量,则会赋值给变量完整的文件名(即<file|module>)或者在失败时赋值为“NOTFOUND ”。

参考:
https://blog.csdn.net/RobotLife/article/details/85416226

4、config_file

指令说明:

configure_file(<input> <output>
               [COPYONLY] [ESCAPE_QUOTES] [@ONLY]
               [NEWLINE_STYLE [UNIX|DOS|WIN32|LF|CRLF] ])

configure_file 主要实现如下两个功能:

  • 将 文件里面的内容全部复制到 文件中;
  • 根据参数规则,替换 @VAR@ 或 ${VAR} 变量;

参数解析:
(1) COPYONLY
仅拷贝 文件里面的内容到 文件, 不进行变量的替换;
(2) ESCAPE_QUOTES
使用反斜杠(C语言风格)来进行转义;
(3) @ONLY
限制替换, 仅仅替换 @VAR@ 变量, 不替换 ${VAR} 变量
(4) NEWLINE_STYLE
指定输入文件的新行格式, 例如:Unix 中使用的是 \n, windows 中使用的 \r\n
注意: COPYONLY 和 NEWLINE_STYLE 是冲突的,不能同时使用;

参考:https://www.cnblogs.com/gaox97329498/p/10952732.html

5、set_property和get_property

set_property: 在指定域中设置一个命名属性

set_property(<GLOBAL |
                DIRECTORY [dir] |
                TARGET [target1 [target2 ...]] |
                SOURCE [src1 [src2 ...]] |
                TEST [test1 [test2 ...]] |
                CACHE [entry1 [entry2 ...]]>
               [APPEND][APPEND_STRING]
               PROPERTY <name>[value1 [value2 ...]])

在某个域中对零个或多个对象设置一个属性。第一个参数决定该属性设置所在的域。它必须为下面中的其中之一:

  • GLOBAL域是唯一的,并且不接特殊的任何名字。
  • DIRECTORY域默认为当前目录,但也可以用全路径或相对路径指定其他的目录(前提是该目录已经被CMake处理)。
  • TARGET域可命名零或多个已经存在的目标。
  • SOURCE域可命名零或多个源文件。注意:源文件属性只对在相同目录下的目标是可见的(CMakeLists.txt)。
  • TEST域可命名零或多个已存在的测试。
  • CACHE域必须命名零或多个已存在条目的cache。

必选项PROPERTY后面紧跟着要设置的属性的名字。其他的参数用于构建以分号隔开的列表形式的属性值。如果指定了APPEND选项,则指定的列表将会追加到任何已存在的属性值当中。如果指定了APPEND_STRING选项,则会将值作为字符串追加到任何已存在的属性值。
get_property: 获取一个属性值

get_property(<variable>
               <GLOBAL |
                DIRECTORY [dir] |
                TARGET <target> |
                SOURCE <source> |
                TEST <test> |
                CACHE <entry> |
                VARIABLE>
               PROPERTY <name>
               [SET | DEFINED |BRIEF_DOCS | FULL_DOCS])

相关域的说明与set_property意义相同。
必选项PROPERTY后面紧跟着要获取的属性的名字。如果指定了SET选项,则变量会被设置为一个布尔值,表明该属性是否已设置。如果指定了DEFINED选项,则变量也会被设置为一个布尔值,表明该属性是否已定义(如通过define_property)。如果定义了BRIEF_DOCS或FULL_DOCS选项,则该变量被设置为一个字符串,包含了对请求的属性的文档。如果该属性没有相关文件,则会返回NOTFOUND。
参考:
https://blog.csdn.net/fuyajun01/article/details/9036485

5、set

CMake 变量包含 常规变量Normal Variables和全局变量Cache Variables。通过 set 指令可以设置两种不同的变量。也可以在 CMake 脚本中使用和设置环境变量。set(ENV{} …),本文重点讲述 CMake 脚本语言特有的两种变量。
(1)两种变量的定义参考
Normal Variables

set(<variable> <value>... [PARENT_SCOPE])

这个命令来设置的变量就是 Normal Variables。例如 set(MY_VAL “666”) ,此时 MY_VAL 变量的值就是 666。
Cache Variables

set(<variable> <value>... CACHE <type> <docstring> [FORCE])

这个命令来设置的变量就是 Cache Variables。例如 set(MY_CACHE_VAL “666” CACHE STRING INTERNAL),此时 MY_CACHE_VAL 就是一个 CACHE 变量。
CMake 规定,有一个与 Cache 变量同名的 Normal 变量出现时,后面使用这个变量的值都是以 Normal 为准,如果没有同名的 Normal 变量,CMake 才会自动使用 Cache 变量。

set(TAF_WEB_HOST "" CACHE STRING "set web host")
IF (TAF_WEB_HOST STREQUAL "")
	set(TAF_WEB_HOST "http://taf.test.com")
ENDIF ()

缓存变量由如下特点:

  • 缓存变量是全局作用域, 变量的值会从CMakeCache.txt中获取,缓存变量在写入CMakeCache.txt以后, 每次都从这个缓存文件中读取该值, 而不会重新调用set(… CACHE …)!!!(Cache变量只会初始化一次,在CMakeCache.txt中存储以后, 多次调用set(… CACHE …)不起作用!!!)。
  • 缓存变量的常规初始化的方式是set(abc “789” CACHE STRING “”)。
  • 当常规变量和缓存变量重名时, 如果缓存变量声明在后面, 会覆盖常规变量。
  • 除了使用set(… CACHE …)可以声明缓存, 也可以在命令行使用-Dxxx=xxx修改缓存变量的值!!!
  • 如果某个Cache变量已经存在于CMakeCache.txt中, 代码中的set(… CACHE …)将不会对这个值有影响, 如果我们在代码中需要强制修改Cache变量的值, 需要使用FORCE字段 — set(abc “123” CACHE STRING “” FORCE)。
    参考:
    https://www.jianshu.com/p/72b07f886820
    https://www.cnblogs.com/ncuneugcj/p/9756324.html

二、常用变量

1、CMAKE_BINARY_DIR和CMAKE_SOURCE_DIR

好多网上的文章,都说CMAKE_BINARY_DIR和CMAKE_SOURCE_DIR是等价的。实际不然。一般来说,都是这样用

cmake ./

上面的方式一般称之为内部编译,这样CMAKE_BINARY_DIR和CMAKE_SOURCE_DIR是等价的。也就是当前源码的目录。如果执行cmake的时候,并不在源码的路径的话,比如:

cmake ../src

这样编译一般称之为外部编译,外部编译的好处是cmake生成的文件和编译出来的东西,就不放在源码路径下了,保证了源码路径的干净整洁。比如可以在src的同级目录下建立build目录。然后在build目录下执行cmake …/src。这样编译出来的东西和cmake生成的东西,都放到了build目录下了。

CMAKE_BINARY_DIR=全路径/build
CMAKE_SOURCE_DIR=全路径/src

2、PROJECT_BINARY_DIR和PROJECT_SOURCE_DIR

CMAKE_BINARY_DIR和PROJECT_BINARY_DIR是不等价的,CMAKE_SOURCE_DIR和PROJECT_SOURCE_DIR也是不等价的。CMAKE_BINARY_DIR和CMAKE_SOURCE_DIR永远都是工程的顶层目录,而PROJECT_BINARY_DIR和PROJECT_SOURCE_DIR则是CMakeList.txt编译发生的目录。
在此之前,有必要介绍一个最基本的命令:

project(projectname [CXX] [C] [Java])

指定工程名称,并可指定工程支持的语言。支持语言列表可忽略,默认支持所有语言。执行project命令后立即会常见两个cmake变量_BINARY_DIR和_SOURCE_DIR,同时也重新赋值了PROJECT_BINARY_DIR和PROJECT_SOURCE_DIR这两个变量。具体为当前CMakeList.txt所在的源目录和编译目录(build)。

3、CMAKE_CURRENT_SOURCE_DIR和CMAKE_CURRENT_BINARY_DIR

路径指向当前正在处理的源目录(CMakeLists.txt所在目录),这是一个指向源目录的完全路径,当前正在被cmake处理。
CMAKE_CURRENT_SOURCE_DIR和CMAKE_CURRENT_BINARY_DIR不同于PROJECT_BINARY_DIR和PROJECT_SOURCE_DIR,PROJECT_BINARY_DIR和PROJECT_SOURCE_DIR是编译发生的目录,只有在执行project命令后才会重置为CMakeList.txt所在的目录,而 CMAKE_CURRENT_SOURCE_DIR和CMAKE_CURRENT_BINARY_DIR是当前处理的源目录,无论是否执行project命令,都是当前CMakeList.txt所在的目录。

4、CMAKE_CURRENT

cmake可执行程序程序的完整路径,例如:

/usr/local/bin/cmake

5、CMAKE_ARCHIVE_OUTPUT_DIRECTORY,CMAKE_LIBRARY_OUTPUT_DIRECTORY和CMAKE_RUNTIME_OUTPUT_DIRECTORY

CMAKE_ARCHIVE_OUTPUT_DIRECTORY:编译后.a文件存储位置。
CMAKE_LIBRARY_OUTPUT_DIRECTORY:动态链接文件.so存储位置。
CMAKE_RUNTIME_OUTPUT_DIRECTORY:可执行文件存储位置。
例如:

#编译的可执行程序输出目录
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)

以上三行命令最好写在根(root)CmakeLists.txt的里面。
参考:
https://www.cnblogs.com/gatsby123/p/10885555.html
https://cmake.org/cmake/help/v3.0/prop_tgt/RUNTIME_OUTPUT_DIRECTORY.html
https://blog.csdn.net/weixin_34043301/article/details/92424326
https://blog.csdn.net/u012487272/article/details/12882283

6、CMAKE_VERBOSE_MAKEFILE

为了在cmake生成Makefile后执行make的时候输出详细的编译命令,可以在CMakeList.txt内加入:

SET( CMAKE_VERBOSE_MAKEFILE on )

或者执行make时

$ make VERBOSE=1

7、系统信息

系统信息相关的变量(内置变量):
(1)在不同的平台编译的时候,会用到一些系统内置的变量,比如操作系统名称,版本号之类

CMAKE_MAJOR_VERSION,CMAKE 主版本号,比如 2.4.6 中的 2
CMAKE_MINOR_VERSION,CMAKE 次版本号,比如 2.4.6 中的 4
CMAKE_PATCH_VERSION,CMAKE 补丁等级,比如 2.4.6 中的 6
CMAKE_SYSTEM,系统名称,比如 Linux-2.6.22
CMAKE_SYSTEM_NAME,不包含版本的系统名,比如 Linux
CMAKE_SYSTEM_VERSION,系统版本,比如 2.6.22
CMAKE_SYSTEM_PROCESSOR,处理器名称,比如 i686.

(2)系统标志,下面的变量都是BOOL类型的,如果与当前系统或编译器相符,值为true,反之为false

UNIX
WIN32 for MINGW,CYGWIN,MSYS
APPLE
BORLAND
WATCOM
MSVC,MSVC_IDE,CMAKE_COMPILER_2005,MSVC60/70/71/80/90/10,针对不同的Visual C++
CMAKE_COMPILER_IS_GUNCXX/CMAKE_COMPILER_IS_GUNCC
UNIX,在所有的类 UNIX 平台为 TRUE,包括 OS X 和 cygwin
WIN32,在所有的 win32 平台为 TRUE,包括 cygwin

(3)编译时选项

BUIlD_SHARED_LIBS:将所有程序库的target设置成共享库
CMAKE_BUIlD_TYPE:控制构建类型,以下为可选参数
None:default;Debug:生成调试信息;Release:发布版本,进行最佳化,需要注意这个值不会在configure的时候自动初始化,需要手动指定
CMAKE_C_FLAGS
CMAKE_C_FLAGS_DEBUG
CMAKE_C_FLAGS_RELEASE

CMAKE_CXX_FLAGS
CMAKE_CXX_FLAGS_DEBUG
CMAKE_CXX_FLAGS_RELEASE

8、编译选项相关的变量

CMAKE_C_FLAGS:内置的 C 编译选项,也可以通过指令 ADD_DEFINITIONS()添加。
CMAKE_CXX_FLAGS:内置的 C++编译选项,也可以通过指令 ADD_DEFINITIONS()添加。
例如:

set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -std=c++11  -Wno-deprecated -fno-strict-aliasing -Wno-overloaded-virtual")

CMake 中有一个变量 CMAKE_BUILD_TYPE ,可以的取值是 Debug,Release,Rel,WithDebInfo 和 MinSizeRel。当这个变量值为 Debug 的时候,CMake 会使用变量 CMAKE_CXX_FLAGS_DEBUG 和 CMAKE_C_FLAGS_DEBUG 中的字符串作为编译选项生成 Makefile ,当这个变量值为 Release 的时候,工程会使用变量 CMAKE_CXX_FLAGS_RELEASE 和 CMAKE_C_FLAGS_RELEASE 选项生成 Makefile。
CMAKE_CXX_FLAGS和CMAKE_C_FLAGS是公共的编译选项,即不管CMAKE_BUILD_TYPE是什么值,也不管是CMAKE_CXX_FLAGS_DEBUG还是CMAKE_CXX_FLAGS_RELEASE,那么最终的编译中都包括CMAKE_CXX_FLAGS和CMAKE_C_FLAGS定义的编译选项。
例如:

set(CMAKE_BUILD_TYPE "Release" CACHE STRING "set build type to release default")
IF (CMAKE_BUILD_TYPE STREQUAL "")
    set(CMAKE_BUILD_TYPE "Release")
ENDIF ()
#公共编译选项
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -std=c++11  -Wno-deprecated -fno-strict-aliasing -Wno-overloaded-virtual")

#__FILE__宏不带路径名
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-builtin-macro-redefined -D__FILE__='\"$(notdir $(abspath $<))\"'")
set(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -Wall -g")
set(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O2 -Wall -fno-strict-aliasing")

9、CMAKE_INSTALL_PREFIX

CMAKE_INSTALL_PREFIX 变量类似于 configure 脚本的 –prefix,常见的使用方法看 起来是这个样子:

#命令行设置
cmake -DCMAKE_INSTALL_PREFIX=/usr .
#设置变量
set(CMAKE_INSTALL_PREFIX "${PROJECT_SOURCE_DIR}/release" CACHE PATH "Installation Directory"  FORCE)

install安装命令

INSTALL(TARGETS targets...
[[ARCHIVE|LIBRARY|RUNTIME]
[DESTINATION <dir>]
[PERMISSIONS permissions...]
[CONFIGURATIONS
[Debug|Release|...]]
[COMPONENT <component>]
[OPTIONAL]
] [...])

DESTINATION 定义了安装的路径,如果路径以/开头,那么指的是绝对路径,这时候CMAKE_INSTALL_PREFIX 其实就无效了。如果你希望使用 CMAKE_INSTALL_PREFIX 来 定义安装路径,就要写成相对路径,即不要以/开头,那么安装后的路径就是:

${CMAKE_INSTALL_PREFIX}/<DESTINATION 定义的路径>

三、常用命令

1、set

#编译选项 Release 还是 Debug
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "set build type to release default")
set(Ext "")
IF (CMAKE_BUILD_TYPE STREQUAL "" OR CMAKE_BUILD_TYPE STREQUAL "Release")
    set(CMAKE_BUILD_TYPE "Release")
    set(Ext ".O2")
ENDIF()
message("CMAKE_BUILD_TYPE TYPE = " ${CMAKE_BUILD_TYPE})
message("Ext = " ${Ext})

其中:

set(CMAKE_BUILD_TYPE "Release" CACHE STRING "set build type to release default")

执行命令:

cmake ../project/ -DCMAKE_BUILD_TYPE=Debug

只设置CMAKE_BUILD_TYPE的缓存值,如果后续没有set这个值,那么这个值取cache中的值,否则为新set的值。如果CMake 中默认有这个CMAKE_BUILD_TYPE变量,那么此时就是赋值,没有的话,CMake 就会默认创建了一个全局 Cache 变量然后赋值。
参考:
https://www.cnblogs.com/ncuneugcj/p/9756324.html

2、aux_source_directory

查找源文件并保存到相应的变量中:

#查找当前目录下所有源文件并保存至SRC_LIST变量中
aux_source_directory(. SRC_LIST)

3、file

file(WRITE filename "message towrite"... )

WRITE 将一则信息写入文件’filename’中,如果该文件存在,它会覆盖它,如果不存在,它会创建该文件。

file(APPEND filename "message to write"... )

APPEND 如同WRITE,区别在于它将信息内容追加到文件末尾。

file(READ filename variable [LIMIT numBytes] [OFFSEToffset] [HEX])

READ 会读取文件的内容并将其存入到变量中。它会在给定的偏移量处开始读取最多numBytes个字节。如果指定了HEX参数,二进制数据将会被转换成十进制表示形式并存储到变量中。

file(<MD5|SHA1|SHA224|SHA256|SHA384|SHA512> filenamevariable)

MD5, SHA1, SHA224, SHA256, SHA384, 和SHA512 会计算出文件内容对应的加密散列。

file(STRINGS filename variable [LIMIT_COUNT num]
     [LIMIT_INPUT numBytes] [LIMIT_OUTPUTnumBytes]
     [LENGTH_MINIMUM numBytes] [LENGTH_MAXIMUMnumBytes]
     [NEWLINE_CONSUME] [REGEX regex]
     [NO_HEX_CONVERSION])

STRINGS 从文件中解析出ASCII字符串列表并存储在变量中。文件中的二进制数据将被忽略。回车符(CR)也会被忽略。也能解析Intel Hex和Motorola S-record文件,这两种文件在读取是会自动转换为二进制格式,可以使用参数NO_HEX_CONVERSION 禁用这种自动转换。LIMIT_COUNT设置可返回的最大数量的字符串。LIMIT_INPUT 设置从输入文件中可读取的最大字节数。LIMIT_OUTPUT设置了存储在输出变量中最大的字节数。 LENGTH_MINIMUM设置了返回的字符串的最小长度。小于这个长度的字符串将被忽略。 LENGTH_MAXIMUM 设置返回的字符串的最大长度。大于这个长度的字符串将被切分为长度不大于于最大长度值的子字符串。NEWLINE_CONSUME 允许换行符包含进字符串中而不是截断它们。REGEX 指定了返回的字符串必须匹配的正则表达式的模式。典型用法:

file(STRINGS myfile.txt myfile)

将输入文件的每行内容存储在变量"myfile"中。

file(GLOB variable [RELATIVE path] [globbingexpressions]...)

GLOB 会产生一个由所有匹配globbing表达式的文件组成的列表,并将其保存到变量中(注意返回的是文件列表而不是文件内容)。Globbing 表达式与正则表达式类似,但更简单。如果指定了RELATIVE 标记,返回的结果将是与指定的路径相对的路径构成的列表。 (通常不推荐使用GLOB命令来从源码树中收集源文件列表。原因是:如果CMakeLists.txt文件没有改变,即便在该源码树中添加或删除文件,产生的构建系统也不会知道何时该要求CMake重新产生构建文件。globbing 表达式包括:

file(GLOB_RECURSE variable [RELATIVE path] [FOLLOW_SYMLINKS] [globbingexpressions]...)
#例如:遍历当前子目录
file(GLOB children RELATIVE ${curdir} ${curdir}/*)

GLOB_RECURSE 与GLOB类似,区别在于它会遍历匹配目录的所有文件以及子目录下面的文件。对于属于符号链接的子目录,只有FOLLOW_SYMLINKS指定一或者cmake策略CMP0009没有设置为NEW时,才会遍历这些目录。

4、get_filename_component

get_filename_component(<VAR> FileName
                         PATH|ABSOLUTE|NAME|EXT|NAME_WE|REALPATH
                         [CACHE])

将变量设置为路径(PATH),文件名(NAME),文件扩展名(EXT),去掉扩展名的文件名(NAME_WE),完整路径(ABSOLUTE),或者所有符号链接被解析出的完整路径(REALPATH)。注意,路径会被转换为Unix的反斜杠(/),并且没有结尾的反斜杠。该命令已经考虑了最长的文件扩展名。如果指定了CACHE选项,得到的变量会被加到cache中。

5、add_library

生成动态库或者静态库,默认情况下会在build的相应目录下面生成库。
语法:

add_library(<name> [STATIC | SHARED | MODULE]
            [EXCLUDE_FROM_ALL]
            source1 [source2 ...])

:库的名字,直接写名字即可,不要写lib,会自动加上前缀的哈。
[STATIC | SHARED | MODULE] :类型有三种。

  • SHARED,动态库
  • STATIC,静态库
  • MODULE,在使用 dyld 的系统有效,如果不支持 dyld,则被当作 SHARED 对待。
    EXCLUDE_FROM_ALL:这个库不会被默认构建,除非有其他的组件依赖或者手工构建。
    使用:
SET(LIBHELLO_SRC hello.c)
ADD_LIBRARY(hello SHARED ${LIBHELLO_SRC})
ADD_LIBRARY(hello_static STATIC ${LIBHELLO_SRC})  

注意,一般我们使用的静态库/动态库只是后缀名不同而已,上面构建的libhello.so与libhello_static.a,显然名字不同哦。这时你会有一个想法,那我把hello_static改成hello,结果是不可行的,静态库无法构建。重名会忽略第二条指令。
解决方法:改libhello_static.a的属性–输出名字

SET_TARGET_PROPERTIES(hello_static PROPERTIES OUTPUT_NAME "hello")

这样就可以生成libhello.so与libhello.a了。关于动态库的版本号:

#VERSION 指代动态库版本,SOVERSION 指代 API 版本。
SET_TARGET_PROPERTIES(hello PROPERTIES VERSION 1.2 SOVERSION 1)    

在这里插入图片描述
参考:
https://blog.csdn.net/weixin_39956356/article/details/100504979

6、add_dependenices

对于编译时遇到的依赖问题,很多时候我们只需要一句target_link_libraries就可以搞定。但是CMake还有另外一个command,add_dependencies。这个什么时候用呢?
一般来说用不到。用到的情况就是两个targets有依赖关系(通过target_link_libraries解决)并且依赖库也是通过编译源码产生的。这时候一句add_dependencies可以在直接编译上层target时,自动检查下层依赖库是否已经生成。没有的话先编译下层依赖库,然后再编译上层target,最后link depend target。
命令语法:

add_dependencies(target-name depend-target1 depend-target2 …)

命令简述:用于指定某个目标(可执行文件或者库文件)依赖于其他的目标。这里的target-name目标必须是 add_executable、add_library、add_custom_target 命令创建的目标。

7、add_custom_comand

增加自定义的构建规则到生成的构建系统中。对于add_custom_command,有两种使用形式。第一种形式是增加一个自定义的命令用来产生一个输出。

add_custom_command(OUTPUT output1 [output2 ...]
                     COMMAND command1[ARGS] [args1...]
                     [COMMAND command2 [ARGS] [args2...] ...]
                     [MAIN_DEPENDENCY depend]
                     [DEPENDS[depends...]]
                     [IMPLICIT_DEPENDS<lang1> depend1 ...]
                     [WORKING_DIRECTORY dir]
                     [COMMENT comment] [VERBATIM] [APPEND])

不要同时在多个相互独立的目标中执行上述命令产生相同的文件,主要是为了防止冲突产生。如果有多条命令,它们将会按顺序执行。ARGS是为了向后兼容,使用过程中可以忽略。MAIN_DEPENDENCY完全是可选的,它主要是针对Visual Studio给出的一个建议。在Makefile中,它会产生一个这样的新目标:

OUTPUT: MAIN_DEPENDENCY DEPENDS
          COMMAND

第二种形式是为某个目标如库或可执行程序添加一个自定义命令。这对于要在构建一个目标之前或之后执行一些操作非常有用。该命令本身会成为目标的一部分,仅在目标本身被构建时才会执行。如果该目标已经构建,命令将不会执行。

add_custom_command(TARGET target
                     PRE_BUILD | PRE_LINK| POST_BUILD
                     COMMAND command1[ARGS] [args1...]
                     [COMMAND command2[ARGS] [args2...] ...]
                     [WORKING_DIRECTORY dir]
                     [COMMENT comment][VERBATIM])

命令执行的时机由如下参数决定:

  • PRE_BUILD - 命令将会在其他依赖项执行前执行
  • PRE_LINK - 命令将会在其他依赖项执行完后执行
    +POST_BUILD - 命令将会在目标构建完后执行。
    其中,PRE_BUILD只被Visual Studio 7及之后的版本支持,其他所有的构建文件产生器将视PRE_BUILD为PRE_LINK。如果指定了WORKING_DIRECTORY,那么命令将会在指定的目录下执行。如果是相对路径,那么该路径将被解释为与当前源码目录对应的构建目录相对的路径。 如果设置了COMMENT,那么在编译时,命令执行前会将COMMENT的内容当做信息输出。如果指定了APPEND ,那么COMMAND 和 DEPENDS 选项的值将会被追加到第一个指定的输出对应的自定义命令中。目前,如果指定了APPEND选项,那么COMMENT, WORKING_DIRECTORY, 和 MAIN_DEPENDENCY选项将会忽略。但是将来可能会使用。如果指定了VERBATIM选项,那么,所有传递到命令的参数将会被适当地转义,这样命令接受到的参数将不会改变。建议使用VERBATIM选项,如果客制命令的输出不是创建一个存储在磁盘上的文件,需要使用命令SET_SOURCE_FILES_PROPERTIES把它标记为SYMBOLIC。
    IMPLICIT_DEPENDS选项请求扫描一个输入文件的隐含依赖项。特定的语言会指明对应编程语言,它会使用相应的依赖项扫描器。目前仅支持C和CXX语言依赖项扫描器。目前IMPLICIT_DEPENDS 选项仅被Makefile产生器支持,其它构建文件的产生器将会忽略该选项。
    如果COMMAND指定了一个可执行的目标(由ADD_EXECUTABLE创建),那么它会自动地被在构建时创建的可执行文件路径替换。另外,也会添加一个目标级的依赖,使得可执行目标总会在使用了该客制命令的任何目标之前构建。然而,它不会增加一个文件级的依赖,这种依赖会使得只要该可执行程序被重新编译,该客制命令也会重新运行。
    DEPENDS选项指定了该命令所依赖的文件。如果任何依赖项是同一目录中其他另一个客制命令 OUTPUT(CMakeLists.txt)。那么CMake会自动地将其引入到执行该客制命令的目标中来。如果没有指定DEPENDS,那么只要OUTPUT不见了,该命令就会运行。如果该命令并没有实际去创建OUTPUT,那么该规则总是执行。如果DEPENDS指定了任何一个目标 (由ADD_* 系列命令创建) ,那么就会创建一个目标级的依赖以确保该目标比任何使用该客制命令的目标要先构建。另外,如果该目标是一个可执行文件或是一个库,那么就会创建一个文件级的依赖,这样会使得只要该目标重新编译,该客制命令就会重新运行。
    **注:**add_custom_command命令生成输出文件并不会立即执行,只会在make的时候才会执行。
    参考:
    https://cmake.org/cmake/help/v3.0/command/add_custom_command.html
    https://blog.csdn.net/fuyajun01/article/details/8907207

8、add_custom_target

增加一个没有输出的目标,使得它总是被构建。

add_custom_target(Name [ALL] [command1 [args1...]]
                    [COMMAND command2 [args2...] ...]
                    [DEPENDS depend depend depend ... ]
                    [WORKING_DIRECTORY dir]
                    [COMMENT comment] [VERBATIM]
                    [SOURCES src1 [src2...]])

增加一个指定名字的目标,并执行指定的命令。该目标没有输出文件,总是被认为是过期的,即使是在试图用目标的名字创建一个文件。使用ADD_CUSTOM_COMMAND命令来创建一个具有依赖项的文件。默认情况下,没有任何目标会依赖该自定义目标。使用ADD_DEPENDENCIES 来添加依赖项或成为别的目标的依赖项。如果指定了ALL选项,那就表明该目标会被添加到默认的构建目标,使得它每次都被运行。(该命令的名称不能命名为 ALL). 命令和参数都是可选的,如果没有指定,将会创建一个空目标。如果设置了WORKING_DIRECTORY ,那么该命令将会在指定的目录中运行。如果它是个相对路径,那它会被解析为相对于当前源码目录对应的构建目录。如果设置了 COMMENT,在构建的时候,该值会被当成信息在执行该命令之前显示。DEPENDS参数可以是文件和同一目录中的其他客制命令的输出。
如果指定了VERBATIM, 所有传递给命令的参数将会被适当地转义。建议使用该选项。
SOURCES选项指定了包含进该客制目标的额外的源文件。即使这些源文件没有构建规则,但是它们会被增加到IDE的工程文件中以方便编辑。
下面以生成jce文件的实际例子来说明:

#JCE2CPP: "/usr/local/taf/cpp/tools/jce2cpp"
#JCE_FILE:"${CMAKE_CURRENT_SOURCE_DIR}/CommonData.jce"
#JCE_GEN_DIR: "${CMAKE_CURRENT_SOURCE_DIR}"
#CUR_JCE_GEN:"${CMAKE_CURRENT_SOURCE_DIR}/CommonData.h"
#set(JCE_GEN ${JCE_GEN} ${CUR_JCE_GEN})
#JCE2CPP_INCULDE: "/home/tafjce/HQSys/LIBS/hqtools"
#JCE2CPP_FLAG: ""
#TARGET: "jce_all"
add_custom_command(
    OUTPUT ${CUR_JCE_GEN}       
    WORKING_DIRECTORY ${JCE_GEN_DIR}
    COMMAND ${JCE2CPP} ${JCE_FILE} ${JCE2CPP_FLAG}  ${JCE2CPP_INCULDE}
    DEPENDS ${JCE2CPP} ${JCE_FILE}
)

add_custom_target(${TARGET} ALL DEPENDS ${JCE_GEN})

DEPENDS ${JCE2CPP} ${JCE_FILE}:这里之所以有 ${JCE2CPP},JCE2CPP虽然是可执行程序,单也是一个文件,故也是一个依赖项。

 add_custom_command(OUTPUT output1 [output2 ...]
                     COMMAND command1[ARGS] [args1...]
                     [COMMAND command2 [ARGS] [args2...] ...]
                     [MAIN_DEPENDENCYdepend]
                     [DEPENDS[depends...]]
                     [IMPLICIT_DEPENDS<lang1> depend1 ...]
                     [WORKING_DIRECTORYdir]
                     [COMMENT comment] [VERBATIM] [APPEND])

add_custom_target(Name [ALL] [command1 [args1...]]
                    [COMMAND command2 [args2...] ...]
                    [DEPENDS depend depend depend ... ]
                    [WORKING_DIRECTORY dir]
                    [COMMENT comment] [VERBATIM]
                    [SOURCES src1 [src2...]])

这里add_custom_command没有指定TARGET,故需要add_custom_target配合才能立即执行。
参考:
https://cmake.org/cmake/help/v3.0/command/add_custom_target.html
https://blog.csdn.net/fuyajun01/article/details/8907207

9、list

用途:提供一些列表操作

list(LENGTH <list><output variable>)
list(GET <list> <elementindex> [<element index> ...] <output variable>)
list(APPEND <list><element> [<element> ...])
list(FIND <list> <value><output variable>)
list(INSERT <list><element_index> <element> [<element> ...])
list(REMOVE_ITEM <list> <value>[<value> ...])
list(REMOVE_AT <list><index> [<index> ...])
list(REMOVE_DUPLICATES <list>)
list(REVERSE <list>)
list(SORT <list>)

选项说明:

  • LENGTH返回列表的长度
  • GET返回列表中指定下标的元素
  • APPEND添加新元素到列表中
  • INSERT 将新元素插入到列表中指定的位置
  • REMOVE_ITEM从列表中删除某个元素
  • REMOVE_AT从列表中删除指定下标的元素
  • REMOVE_DUPLICATES从列表中删除重复的元素
  • REVERSE 将列表的内容实地反转,改变的是列表本身,而不是其副本
  • SORT 将列表按字母顺序实地排序,改变的是列表本身,而不是其副本
    列表的子命令APPEND, INSERT, REMOVE_AT, REMOVE_ITEM,REMOVE_DUPLICATES, REVERSE以及SORT在当前的CMake变量域创建一些新值。与SET命令类似,即使列表本身是在父域中定义的,LIST命令也只会在当前域创建新的变量值,为了将这些操作的结果向上传递,需要通过SET PARENT_SCOPE, SET CACHE INTERNAL或其他值域扩展的方法。
    注意:cmake中的列表是以分号隔开的一组字符串。可以使用set命令创建一个列表。例如:set(var a b c d e)创建了一个这样的列表:a;b;c;d;e。 set(var “a b c d e”)创建了一个字符串或只有一个元素的列表。
    当指定索引值时,为大于或等于0的值。它从列表的开始处索引,0代表列表的第一个元素。如果为小于或等于-1的值,它从列表的结尾处索引,-1代表列表的最后一个元素。

10、set_directory_properties

设置某个路径的一种属性。

set_directory_properties(PROPERTIES prop1 value1 prop2 value2)

为当前的路径及其子路径设置一种属性。如果该属性不存在,CMake将会报告一个错误。属性包括:INCLUDE_DIRECTORIES, LINK_DIRECTORIES, INCLUDE_REGULAR_EXPRESSION, 以及ADDITIONAL_MAKE_CLEAN_FILES共四种。ADDITIONAL_MAKE_CLEAN_FILES是一个文件名的list,其中包含有"make clean"阶段会被清除掉的文件。

11、include_directories,link_directories, link_libraries和target_link_libraries

INCLUDE_DIRECTORIES作用是添加头文件目录,它相当于g++选项中的-I参数的作用,也相当于环境变量中增加路径到CPLUS_INCLUDE_PATH变量的作用(这里特指c++。c和Java中用法类似)。
比如:

include_directories("/opt/MATLAB/R2012a/extern/include")

LINK_DIRECTORIES作用是添加需要链接的库文件目录
语法:

link_directories(directory1 directory2 ...)

它相当于g++命令的-L选项的作用,也相当于环境变量中增加LD_LIBRARY_PATH的路径的作用。比如:

LINK_LIBRARIES("/opt/MATLAB/R2012a/bin/glnxa64/libeng.so")
LINK_LIBRARIES("/opt/MATLAB/R2012a/bin/glnxa64/libmx.so")

也可以写成:

LINK_LIBRARIES("/opt/MATLAB/R2012a/bin/glnxa64/libeng.so" "/opt/MATLAB/R2012a/bin/glnxa64/libmx.so")

TARGET_LINK_LIBRARIES 作用是设置要链接的库文件的名称,语法:

TARGET_LINK_LIBRARIES(targetlibrary1 <debug | optimized> library2 ..)

比如(以下写法,包括备注中的都可以):

#连接libhello.so库
TARGET_LINK_LIBRARIES(myProject hello)
TARGET_LINK_LIBRARIES(myProject libhello.a)
TARGET_LINK_LIBRARIES(myProject libhello.so)

再如:

TARGET_LINK_LIBRARIES(myProject libeng.so)
TARGET_LINK_LIBRARIES(myProject eng)
TARGET_LINK_LIBRARIES(myProject -leng)

一个简单的示例(以下CMakeLists.txt效果相当,在ubuntu 12.04 + g++4.6下测试编译通过):
方式一:

cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
include_directories("/opt/MATLAB/R2012a/extern/include")
#directly link to the libraries.
LINK_LIBRARIES("/opt/MATLAB/R2012a/bin/glnxa64/libeng.so")
LINK_LIBRARIES("/opt/MATLAB/R2012a/bin/glnxa64/libmx.so")
#equals to below
#LINK_LIBRARIES("/opt/MATLAB/R2012a/bin/glnxa64/libeng.so" "/opt/MATLAB/R2012a/bin/glnxa64/libmx.so")
add_executable(myProject main.cpp)

方式二:

cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
include_directories("/opt/MATLAB/R2012a/extern/include")
LINK_DIRECTORIES("/opt/MATLAB/R2012a/bin/glnxa64")
add_executable(myProject main.cpp)
target_link_libraries(myProject eng mx)
#equals to below
#target_link_libraries(myProject -leng -lmx)
#target_link_libraries(myProject libeng.so libmx.so)

参考:
https://blog.csdn.net/Tommy_wxie/article/details/77698627?utm_source=blogxgwz4

12、execute_process

CMake可以通过execute_process调用shell命令或者脚本,其原型如下:

execute_process(COMMAND <cmd1> [args1...]]
                [COMMAND <cmd2> [args2...] [...]]
                [WORKING_DIRECTORY <directory>]
                [TIMEOUT <seconds>]
                [RESULT_VARIABLE <variable>]
                [OUTPUT_VARIABLE <variable>]
                [ERROR_VARIABLE <variable>]
                [INPUT_FILE <file>]
                [OUTPUT_FILE <file>]
                [ERROR_FILE <file>]
                [OUTPUT_QUIET]
                [ERROR_QUIET]
                [OUTPUT_STRIP_TRAILING_WHITESPACE]

按指定的先后顺序运行一个或多个命令,每个进程的输出通过管道连接作为下一个进程的输入。所有的进程使用单个的标准错误输出管道。如果指定了WORKING_DIRECTORY,则指定的目录将作为子进程当前的工作目录。如果指定了TIMEOUT值,则如果在指定的时间内(以秒为单位计算,允许有小数位)子进程执行仍未完成,则将会被中断。如果指定了RESULT_VARIABLE变量,则最后命令执行的结果将保存在该变量中,它是最后一个子进程执行完后的返回值或描述某种错误信息的字符串。如果指定了OUTPUT_VARIABLE或ERROR_VARIABLE变量,则该变量会分别保存标准输出和标准错误输出的内容。如果指定的变量是同一个,则输出会按产生的先后顺序保存在该变量中。如果指定了INPUT_FILE,UTPUT_FILE或ERROR_FILE等文件名,则它们会分别与第一个子进程的标准输入,最后一个子进程的标准输出以及所有子进程的标准错误输出相关联。如果指定了OUTPUT_QUIET或ERROR_QUIET,则会忽略标准输出和错误输出。如果在同一管道中同时指定了多个OUTPUT_*或ERROR_*选项,则优先级顺序是未知的(应避免这种情况)。如果未指定任何OUTPUT_*或ERROR_*选项,则命令CMake所在进程共享输出管道。
例如,执行shell命令:

execute_process(COMMAND <一句shell命令> WORKING_DIRECTORY <这句shell命令执行的工作目录>)

执行shell脚本:

execute_process(COMMAND sh test.sh WORKING_DIRECTORY <test.sh所在目录>)

参考:
https://blog.csdn.net/qq_28584889/article/details/97758450

13、add_subdirectory

add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL])

这个指令用于向当前的工程添加存放源文件的目录,并可以指定中间二进制和目标二进制存放的位置。 EXCLUDE_FROM_ALL参数的含义是将这个目录从编译的过程中排除,比如,工程中的example,可以就需要工程构建完成后,再进入example目录单独进行构建。
有这样一种情况。自己写了一个库,需要写测试程序。类似如下结构:

hello-world/
├── CMakeLists.txt
├── main.c
├── test
│   ├── CMakeLists.txt
│   └── main.c
├── hello
│   ├── CMakeLists.txt
│   ├── hello.c
│   └── hello.h
└── world
    ├── CMakeLists.txt
    ├── world.c
    └── world.h

hello/ 目录生成 libhello.so,world/ 目录生成 libworld.so,test/ 目录存储测试程序,测试上述两个库功能是否正常。请注意 test/ 与 hello/ 和 world/ 的目录层级关系。我们只关注 test/CMakeLists.txt 文件。第一反应,是这么写:

cmake_minimum_required(VERSION 3.5)
​
project(test C) 
​
#库目录
set(TOP_DIR ${CMAKE_CURRENT_LIST_DIR}/../)
​
add_subdirectory(${TOP_DIR}/hello)
add_subdirectory(${TOP_DIR}/world)
​
add_executable(${PROJECT_NAME} main.c)
​
target_link_libraries(${PROJECT_NAME} PRIVATE hello)
target_link_libraries(${PROJECT_NAME} PRIVATE world)
​
target_include_directories(${PROJECT_NAME} PRIVATE ${TOP_DIR}/hello)
target_include_directories(${PROJECT_NAME} PRIVATE ${TOP_DIR}/world)

编译结果:

-- The C compiler identification is GNU 5.3.1
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
CMake Error at CMakeLists.txt:10 (add_subdirectory):
  add_subdirectory not given a binary directory but the given source
  directory "/home/sdc/pro/hello-world/hello" is not a subdirectory of
  "/home/sdc/pro/hello-world/test".  When specifying an out-of-tree source a
  binary directory must be explicitly specified.
​
CMake Error at CMakeLists.txt:11 (add_subdirectory):
  add_subdirectory not given a binary directory but the given source
  directory "/home/sdc/pro/hello-world/world" is not a subdirectory of
  "/home/sdc/pro/hello-world/test".  When specifying an out-of-tree source a
  binary directory must be explicitly specified.
​
-- Configuring incomplete, errors occurred!
See also "/home/sdc/pro/hello-world/test/build/CMakeFiles/CMakeOutput.log".

add_subdirectory 发生错误。
错误原因: hello/ 目录不是 test/ 的子目录。
解决方法: 显式指定 binary directory。
在使用 add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL])命令时,如果 source_dir 不是当前目录(CMakeLists.txt 所在目录,例子中的 test/ 目录)的子目录,那么就需要显式指定 [binary_dir] 参数,用于存储 source_dir 相关文件。
修改CMakeLists.txt 文件中的 add_subdirectory()命令为如下方式即可:

#指定 [binary_dir] 参数
add_subdirectory(${TOP_DIR}/hello hello_binary_dir)
add_subdirectory(${TOP_DIR}/world world_binary_dir)

**说明:**例子中的 hello/ 和world/ 目录与 test/ 目录是平级关系。实际上,只要不是上下级关系(比如,hello/ 和 world/ 目录在其他目录下或者是 test/ 目录的上级),在使用 add_subdirectory() 时都需要指定 [binary_dir] 参数。

14、set_target_properties

set_target_properties 设置目标的一些属性来改变它们构建的方式。

set_target_properties(target1 target2 ...
                        PROPERTIES prop1 value1
                        prop2 value2 ...)

为一个目标设置属性。该命令的语法是列出所有你想要变更的文件,然后提供你想要设置的值。你能够使用任何你想要的属性/值对,并且在随后的代码中调用GET_TARGET_PROPERTY命令取出属性的值。
影响一个目标输出文件的名字的属性详述如下。PREFIX和SUFFIX属性覆盖了默认的目标名前缀(比如lib)和后缀(比如.so)。IMPORT_PREFIX和IMPORT_SUFFIX是与之等价的属性,不过针对的是DLL(共享库目标)的导入库。在构建目标时,OUTPUT_NAME属性设置目标的真实名字,并且可以用来辅助创建两个具有相同名字的目标,即使CMake需要唯一的逻辑目标名。例如:

SET_TARGET_PROPERTIES(hello_static PROPERTIES OUTPUT_NAME "hello")

LINK_FLAGS属性可以用来为一个目标的链接阶段添加额外的标志。LINK_FLAGS_将为配置添加链接标志,例如DEBUG,RELEASE,MINSIZEREL,RELWITHDEBINFO。COMPILE_FLAGS属性可以设置附加的编译器标志,它们会在构建目标内的源文件时被用到。它也可以用来传递附加的预处理器定义。
参考:
http://www.wendangku.net/doc/73ab3fcad5bbfd0a79567372-15.html
https://www.cnblogs.com/coderfenghc/archive/2012/10/20/2712806.html

15、option

提供一个用户可以任选的选项。语法如下:

option(<option_variable> "help string describing option"
            [initial value])

提供选项让用户选择是 ON 或者 OFF ,如果没有提供初始化值,使用OFF,也就是说默认的值是OFF。
注意:这个option命令和你本地是否存在编译缓存的关系很大。所以,如果你有关于 option 的改变,那么请你务必清理 CMakeCache.txt 和 CMakeFiles 文件夹。还有,请使用标准的 [initial value] 值 ON 或者 OFF。
参考:
https://www.cnblogs.com/the-capricornus/p/4717566.html
https://www.jianshu.com/p/035bc18f8f62

四、编译过程

1、cmake会立即执行的操作

(1)set命令
set命令在cmake的时候会立即执行,例如:

set(CLEAR_INCLUDE "clear-install.cmake")

(2)file命令
file命令在cmake的时候会立即执行,例如:

set(CLEAR_INCLUDE "clear-install.cmake")
FILE(WRITE ${CLEAR_INCLUDE} "EXECUTE_PROCESS(COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_INSTALL_PREFIX}/include)\n")

注:如果没有指定路径,那么文件默认就是当前CMakeLists.txt所在的目录。
(3)config_file命令
复制文件操作

configure_file(${CMAKE_SOURCE_DIR}/tc_version.h.in
        ${CMAKE_SOURCE_DIR}/taf-cpp-util/include/util/tc_version.h
        )
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

cmake基本用法 的相关文章

  • CUDA程序编写具体参数设置

    介绍了GPU的结构以及资源的控制要素 xff08 GPU硬件结构和程序具体参数设置 yu132563的专栏 CSDN博客 xff09 以及编程过程中的一些需要注意的问题 xff08 CUDA程序性能调优 yu132563的专栏 CSDN博客
  • CUDA Stream流并发性

    目录 1 CUDA 中的异步命令 2 默认流 3 Multistream多流示例 异构计算是指高效地使用系统中的所有处理器 xff0c 包括 CPU 和 GPU 为此 xff0c 应用程序必须在多个处理器上并发执行函数 CUDA 应用程序通
  • Madagascar环境下编程

    引用 原创 Madagascar环境下编程 2013 07 17 04 50 34 转载 标签 xff1a 教育 分类 xff1a madagascar 本文转载自seismig 原创 Madagascar环境下编程 Madagascar是
  • mySQL(关系型数据库管理系统)编辑

    收藏 2906 1034 mySQL xff08 关系型数据库管理系统 xff09 编辑 MySQL 1 是一个 关系型数据库管理系统 xff0c 由瑞典 MySQL AB公司开发 xff0c 目前属于 Oracle公司 MySQL是最流行
  • CPU的核心数、线程数的关系和区别

    我们在选购电脑的时候 xff0c CPU是一个需要考虑到核心因素 xff0c 因为它决定了电脑的性能等级 CPU从早期的单核 xff0c 发展到现在的双核 xff0c 多核 CPU除了核心数之外 xff0c 还有线程数之说 xff0c 下面
  • STM32单片机,下载器下载完程序能正常跑起来,断电再上电程序不运行

    晶振坏了 转载于 https www cnblogs com god of death p 7050281 html
  • CUDA性能优化----warp深度解析

    CUDA性能优化 warp深度解析 2017 01 12 16 41 07 分类 xff1a HPC amp CUDA优化 标签 xff1a gpu cuda hpc 举报 字号 订阅 下载LOFTER 我的照片书 1 引言 CUDA性能优
  • 螺旋桨转矩

    xfeff xfeff 在螺旋桨气动力分析时 xff0c 首先应用翼型理论进行螺旋桨叶素分析 利用翼型升阻特性数据 xff0c 回避了有限机翼的展弦比问题 xff0c 诱导流动由涡流模型确定 xff0c 取决于桨叶数目 间距以及作用于每片桨
  • 给初学者们讲解人工神经网络(ANN)

    1 介绍 这份教学包是针对那些对人工神经网络 xff08 ANN xff09 没有接触过 基本上完全不懂的一批人做的一个简短入门级的介绍 我们首先简要的引入网络模型 xff0c 然后才开始讲解ANN的相关术语 作为一个应用的案例 xff0c
  • OpenMP基本概念

    OpenMP是一种用于共享内存并行系统的多线程程序设计方案 xff0c 支持的编程语言包括C C 43 43 和Fortran OpenMP提供了对并行算法的高层抽象描述 xff0c 特别适合在多核CPU机器上的并行程序设计 编译器根据程序
  • 散度和旋度的物理意义是什么?

    高等数学学的时间有点久远了 xff0c 最近需要推倒一些公式 xff0c 以前高数学的时候这公式那定理的都没说什么物理意义 xff0c 现在接触的问题都是具有一定物理意义的 xff0c 感觉对不上 xff0c 回来找找资料好好理解一下 xf
  • 格林公式、高斯公式及斯托克斯公式的理解及相互关系

    最近要推倒波动方程积分解 xff0c 要对散度 旋度以及他们之间的相互关系有一个理解 看了两天 xff0c 自己认为理解的差不多了 xff0c 现在写在这个地方 xff0c 作为笔记 xff0c 以后忘记了拿过来看一下 xff0c 加深一下
  • Radon变换理论介绍

    本人最近在研究Radon变换 xff0c 在查阅了各种资料之后在此写下个人的理解 xff0c 希望与各位牛牛进行交流共同进步 xff0c 也使得理解更加深刻些 Radon变换的本质是将原来的函数做了一个空间转换 xff0c 即 xff0c
  • test

    lt DOCTYPE html gt lt html lang 61 34 en 34 gt lt head gt lt meta charset 61 34 utf 8 34 gt lt meta http equiv 61 34 X U
  • BIT内存顺序

    机器的最小寻址单位是字节 xff0c bit无法寻址 xff0c 也就没有高低地址和起始地址的概念 xff0c 我们需要定义一下bit的 地址 以一个字节为例 xff0c 我们把从左到右的8个bit的位置 position 命名按顺序命名如
  • 无人驾驶感知篇之融合(五)

    今天早上看到上海新增一万七千左右 xff0c 看的真的很揪心 xff01 希望白衣战士能早点战胜这场疫情 xff0c 期待明天能有好消息 xff01 今天具体讲讲多贝叶斯估计算法的原理 xff0c 多贝叶斯估计法的主要思想是将传感器信息依据
  • MAC地址的介绍(单播、广播、组播、数据收发)

    MAC地址组成 网络设备的MAC地址是全球唯一的 MAC地址长度为48比特 xff0c 通常用十六进制表示 MAC地址包含两部分 xff1a 前24比特是组织唯一标识符 xff08 OUI xff0c OrganizationallyUni
  • stm32通用定时器输出PWM控制舵机

    stm32的通用定时器有TIM2 TIM3 TIM4 TIM5 xff0c 每个定时器都有独立的四个通道可以作为 xff1a 输入捕获 输出比较 PWM输出 单脉冲模式输出等 stm32除了基本定时器 xff0c 其他定时器都能输出PWM
  • Linux内核Socket CAN中文文档

    自己在年假中空闲之余翻译的内核中Socket CAN的文档 xff0c 原文地址在 xff1a http lxr linux no linux 43 v2 6 34 Documentation networking can txt 但是这篇
  • c/c++自定义通讯协议(TCP/UDP)

    前言 xff1a TCP与UDP是大家耳熟能详的两种传输层通信协议 xff0c 本质区别在于传输控制策略不相同 xff1a 使用TCP协议 xff0c 可以保证传输层数据包能够有序地被接受方接收到 xff0c 依赖其内部一系列复杂的机制 x

随机推荐

  • ubuntu 使用虚拟can 与 socketCAN使用

    原文链接 xff1a https blog csdn net xiandang8023 article details 127990159 创建虚拟CAN接口 在Linux上能使用虚拟CAN接口之前 xff0c 需要在终端执行以下三个步骤
  • cmake引入第三方库

    cmake引入第三方库 第三方库包含 lib文件和 h hpp文件动态库还包含 dll文件 小例程 3rdparty bin test dll include test hpp lib Debug test lib Release test
  • AHB-APB总线协议

    AHB APB总线协议 文章目录 AHB APB总线协议一 AHB APB总线介绍二 AHB总线设备1 AHB主设备 xff08 master xff09 2 AHB从设备 xff08 slave xff09 3 AHB仲裁器 xff08
  • Modelsim缺失库快速添加

    Modelsim缺失库快速添加 文章目录 Modelsim缺失库快速添加前言一 ini文件二 器件库配置1 将器件库放在modelsim文件夹下2 ini配置文件修改 前言 在单独使用modelsim时 xff0c 假如要编译复杂的工程文件
  • AHB-APB_Lite总线协议及Verilog实现

    AHB APB Lite总线协议及Verilog实现 文章目录 AHB APB Lite总线协议及Verilog实现一 AHB Lite协议介绍二 系统框架介绍三 代码设计四 仿真测试 一 AHB Lite协议介绍 AHB xff08 Ad
  • 通信协议详解(二):IIC总线协议(传输时序+数据格式+设计实现)

    文章目录 一 IIC xff08 Inter Integrated Circuit xff09 介绍二 传输协议1 时序传输时序写操作时序数据有效性开始 amp 结束信号从机应答信号 2 数据格式 三 设计实现1 时钟2 传输过程3 三态门
  • Qt error ------ 'XXX' has not been declared

    1 头文件没加 2 调用函数者的头文件在XXX头文件的下方 转载于 https www cnblogs com god of death p 8572306 html
  • Command Expert安装

    一 安装准备 需先下载两个安装包 1 Commmand Expert安装包 https www keysight com cn zh lib software detail computer software command expert
  • Vitis开发(一):Vivado启动vitis

    Vitis是Xilinx SDK的继承开发工具 xff0c 从Vivado 2019 2版本开始启用 在Vivado 2019 1及更早版本中 xff0c 导出的硬件描述文件为 hdf文件 xff0c 给xilinx sdk使用 在Viva
  • 数字IC刷题(一)

    一 选择 1 To achieve better leakage cells are placed A HVT B LVT C RVT 解 LVT Low V threshold xff1a 低阈值 这种库的漏电流较大 xff0c 但是延迟
  • CPU设计-分支预测

    目录 CPU分支指令类型分类 1 xff09 无条件跳转 xff0f 分支 xff08 Unconditional Jump Branch xff09 指令 无条件直接跳转 xff0f 分支 xff1a 无条件间接跳转 xff0f 分支 x
  • 数字世界的积木-从MOS管搭反相器,与非门,锁存器,触发器

    文章目录 一 MOS管MOS管搭建反相器MOS管搭建传输门MOS管搭建与非门 二 与非门R S锁存器三 电平触发器电平触发RS锁存器带异步复位 xff0c 异步置位的电平触发RS锁存器电平触发D触发器 四 边沿触发器 一 MOS管 NMOS
  • 内存对齐规则

    每个特定平台上的编译器都有自己的默认 对齐系数 也叫对齐模数 程序员可以通过预编译命令 pragma pack n xff0c n 61 1 2 4 8 16来改变这一系数 xff0c 其中的n就是你要指定的 对齐系数 规则 xff1a 1
  • EGO-Planner: An ESDF-free Gradient-based Local Planner for Quadrotors(论文笔记)

    EGO Planner An ESDF free Gradient based Local Planner for Quadrotors xff08 论文笔记 xff09 ESDF欧式符号距离场避碰力估算基于梯度的轨迹优化平滑惩罚障碍惩罚可
  • 计算机组成原理系列(三):计算机存储器结构体系详解

    x1f525 Hi xff0c 我是小余 本文已收录到 GitHub Androider Planet 中 这里有 Android 进阶成长知识体系 xff0c 关注公众号 小余的自习室 xff0c 在成功的路上不迷路 xff01 前言 生
  • linux下怎么使用C语言编写接收和发送udp组播数据?

    一 xff0c 发送端 代码如下 xff1a 先调用initUdpMultiCastSender初始化 xff0c int initUdpMultiCastSender uint32 t localip uint16 t localport
  • MQTT 及其 测试工具

    协议说明书 xff1a https mcxiaoke gitbooks io mqtt cn content mqtt 04 OperationalBehavior html 官网提供了很多的broker模拟器 xff0c 地址 xff1a
  • OpenCV安装教程:Windows 安装 Visual Studio + OpenCV + OpenCV contrib

    目录 0 写作背景 1 安装visual studio 2 下载OpenCV相关的源码 下载OpenCV原始的源码 下载OpenCV contrib的源码 下载安装cmake 3 cmake编译OpenCV 初始编译 CmakeDownlo
  • 图像分类、目标检测、图像分割----简介

    1 图像分类 xff1a 单任务算法 1 1 公开数据集 xff1a xff08 1 xff09 MNIST xff1a 10个类别 xff0c 手写数字体数据集 xff0c 6万条训练数据和1万条测试数据 xff0c 28 28的灰度图
  • cmake基本用法

    一 cmake命令 1 基本用法 cmake 选项 lt 源码路径 gt CMake可执行程序是CMake的命令行界面 它可以用脚本对工程进行配置 工程配置设置可以在命令行中使用 D选项指定 使用 i选项 xff0c cmake将通过提示交