Cmake实例分析

Cmake与autotools一样都是生成makefile的工具,但其步骤更清晰明了,这里做一下解析。

CMake主要是编写CMakeLists.txt文件,然后用cmake命令将CMakeLists.txt文件转化为make所需要的makefile文件,最后用make命令编译源码。因此CMake的编译基本就两个步骤:

  1. cmake
  2. make

CMakeLists.txt是以目录为执行单位的,CMakeLists.txt中可以添加子目录,子目录下也存在一个该目录的CMakeLists.txt文件。

以mbedtls的CMakeLists.txt为例:

调试方法:

在buildroot环境中,调试CMakeLists.txt的方法如下:

  1. 修改CMakeLists.txt,在其中加入调试语句

message( [STATUS|WARNING|AUTHOR_WARNING|FATAL_ERROR|SEND_ERROR]
  "message to display" ...)
打印变量的示例如下:

message(STATUS ${CMAKE_COMPILER_IS_MSVC})

        2. 执行如下命令,就会输出加入的调试信息。

$ make mbedtls-reconfigure > m1.txt 2>&1

实例分析:

cmake_minimum_required(VERSION 2.6)

cmake_minimum_required(VERSION <min>[...<policy_max>] [FATAL_ERROR])
该命令指定了编译该工程对cmake的最高、最低版本要求,如果 CMake 的运行版本低于所需版本,它将停止处理项目并报告错误。

project("mbed TLS" C)   

project(<PROJECT-NAME> [<language-name>...])

指定工程名称以及语言

option(USE_PKCS11_HELPER_LIBRARY "Build mbed TLS with the pkcs11-helper library." OFF)

option(<variable> "<help_text>" [value])

  • variable:定义选项名称
  • help_text:说明选项的含义
  • value:定义选项默认状态,一般是OFF或者ON,除去ON之外,其他所有值都为认为是OFF

string(REGEX MATCH "IAR" CMAKE_COMPILER_IS_IAR "${CMAKE_C_COMPILER_ID}")

string(REGEX MATCH <regular_expression> <output_variable> <input> [<input>...])
从所有<input> ...中查找<regular_expression>匹配到的字符串,并存放于<output_variable>,查不到输出为空字符串。多个输入时先连接再做操作。只匹配第一次。

以上语句是查找Cmake的编译器是否是IAR规范。

set(WARNING_BORDER "*******************************************************\n")
set(NULL_ENTROPY_WARN_L1 "****  WARNING!  MBEDTLS_TEST_NULL_ENTROPY defined!\n")
set(NULL_ENTROPY_WARN_L2 "****  THIS BUILD HAS NO DEFINED ENTROPY SOURCES\n")
set(NULL_ENTROPY_WARN_L3 "****  AND IS *NOT* SUITABLE FOR PRODUCTION USE\n")

set(NULL_ENTROPY_WARNING "${WARNING_BORDER}"
                         "${NULL_ENTROPY_WARN_L1}"
                         "${NULL_ENTROPY_WARN_L2}"
                         "${NULL_ENTROPY_WARN_L3}"
                         "${WARNING_BORDER}")

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

  • variable:要被赋值的变量
  • value:要赋给变量的值

设置NULL_ENTROPY_WARNING 字符串变量的值;

message(STATUS "NULL_ENTROPY_WARNING is:\n${NULL_ENTROPY_WARNING}")

打印出该值为:

NULL_ENTROPY_WARNING is:

*******************************************************
;****  WARNING!  MBEDTLS_TEST_NULL_ENTROPY defined!
;****  THIS BUILD HAS NO DEFINED ENTROPY SOURCES
;****  AND IS *NOT* SUITABLE FOR PRODUCTION USE
;*******************************************************

 find_package(Perl)

 find_package(<package> [version] [EXACT] [QUIET] [MODULE]
             [REQUIRED] [[COMPONENTS] [components...]]
             [OPTIONAL_COMPONENTS components...]
             [NO_POLICY_SCOPE])

package:必填参数。需要查找的包名,注意大小写。

version和EXACT:可选参数,version指定的是版本,如果指定就必须检查找到的包的版本是否和version兼容。如果指定EXACT则表示必须完全匹配的版本而不是兼容版本就可以。

QUIET:可选参数,表示如果查找失败,不会在屏幕进行输出(但是如果指定了REQUIRED字段,则QUIET无效,仍然会输出查找失败提示语)。

MODULE:可选字段。前面提到说“如果Module模式查找失败则回退到Config模式进行查找”,但是假如加入了MODULE选项,那么就只在Module模式查找,如果Module模式下查找失败并不切换到Config模式查找。

REQUIRED:可选字段。表示一定要找到包,找不到的话就立即停掉整个CMake。而如果不指定REQUIRED则CMake会继续执行。

COMPONENTS,components:可选字段,表示查找的包中必须要找到的组件(components),如果有任何一个找不到就算失败,类似于REQUIRED,导致CMake停止执行。
查找是否已经有Perl依赖包

if(PERL_FOUND),如果Perl已经有安装,PERL_FOUND为true

从cmake的官方文档查到

Find perl

this module looks for Perl

PERL_EXECUTABLE     - the full path to perl
PERL_FOUND          - If false, don't attempt to use perl.
PERL_VERSION_STRING - version of perl found (since CMake 2.8.8)

execute_process(COMMAND ${PERL_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/scripts/config.pl -f ${CMAKE_CURRENT_SOURCE_DIR}/include/mbedtls/config.h get MBEDTLS_TEST_NULL_ENTROPY
                        RESULT_VARIABLE result)

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>]
                [INPUT_FILE <file>]
                [OUTPUT_FILE <file>]
                [ERROR_FILE <file>]
                [OUTPUT_QUIET]
                [ERROR_QUIET]
                [COMMAND_ECHO <where>]
                [OUTPUT_STRIP_TRAILING_WHITESPACE]
                [ERROR_STRIP_TRAILING_WHITESPACE]
                [ENCODING <name>]
                [ECHO_OUTPUT_VARIABLE]
                [ECHO_ERROR_VARIABLE]
                [COMMAND_ERROR_IS_FATAL <ANY|LAST>])

 execute_process 命令将从当前正在执行的CMake进程中派生一个或多个子进程,从而提供了在配置项目时运行任意命令的方法。可以在一次调用 execute_process 时执行多个命令。但请注意,每个命令的输出将通过管道传输到下一个命令中。该命令接受多个参数:

COMMAND:子进程命令行。
WORKING_DIRECTORY:指定应该在哪个目录中执行命令。
TIMEOUT:如果在指定的时间内(以秒为单位计算,允许有小数位)子进程执行仍未完成,则将会被中断。
RESULT_VARIABLE:包含进程运行的结果。这要么是一个整数表示执行成功,要么是一个带有错误条件的字符串。
RESULTS_VARIABLE:变量将被设置为以分号分隔的列表形式包含所有进程的结果,按给定命令参数的顺序排列。每个条目都是对应子项的整数返回码或描述错误条件的字符串。
OUTPUT_VARIABLE和ERROR_VARIABLE将包含执行命令的标准输出和标准错误。由于命令的输出是通过管道传输的,因此只有最后一个命令的标准输出才会保存到OUTPUT_VARIABLE中。
INPUT_FILE指定标准输入重定向的文件名。
OUTPUT_FILE指定标准输出重定向的文件名。
ERROR_FILE指定标准错误输出重定向的文件名。
设置OUTPUT_QUIET和ERROR_QUIET后,CMake将静默地忽略标准输出和标准错误。
COMMAND_ECHO <where>:正在运行的命令将被回送到<where>,而<where>将被设置为STDERR、STDOUT或NONE中的一个。
设置OUTPUT_STRIP_TRAILING_WHITESPACE,可以删除运行命令的标准输出中的任何尾随空 格。
设置ERROR_STRIP_TRAILING_WHITESPACE,可以删除运行命令的错误输出中的任何尾随空格。
ENCODING <name>:适用于windows平台,编码名称有NONE、AUTO、ANSI、OEM、UTF8或UTF-8。
ECHO_OUTPUT_VARIABLE, ECHO_ERROR_VARIABLE:标准输出或标准错误不会被专门重定向到配置的变量。
COMMAND_ERROR_IS_FATAL <ANY|LAST>:
1.ANY:如果命令列表中的任何命令失败,execute_process()命令将因错误而停止。2.LAST:如果命令列表中的最后一个命令失败,则execute_process()命令会因错误而停止。列表中前面的命令不会导致致命错误。
        如果在同一管道中同时指定了多个OUTPUT_*或ERROR_*选项,则优先级顺序是未知的(应避免这种情况)。

        如果未指定任何OUTPUT_*或ERROR_*选项,则命令CMake所在进程共享输出管道。
 执行命令并设定返回值为result

function(link_to_source base_name)
    # Get OS dependent path to use in `execute_process`
    file(TO_NATIVE_PATH "${CMAKE_CURRENT_BINARY_DIR}/${base_name}" link)
    file(TO_NATIVE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/${base_name}" target)

    if (NOT EXISTS ${link})
        if (CMAKE_HOST_UNIX)
            set(command ln -s ${target} ${link})
        else()
            if (IS_DIRECTORY ${target})
                set(command cmd.exe /c mklink /j ${link} ${target})
            else()
                set(command cmd.exe /c mklink /h ${link} ${target})
            endif()
        endif()

        execute_process(COMMAND ${command}
            RESULT_VARIABLE result
            ERROR_VARIABLE output)

        if (NOT ${result} EQUAL 0)
            message(FATAL_ERROR "Could not create symbolic link for: ${target} --> ${output}")
        endif()
    endif()
endfunction(link_to_source)

function(<name> [<arg1> ...])
  <commands>
endfunction([<name>])
 CMake中的function类似编程语言的函数,允许我们将一系列复杂的命令封装起来,方便调用与重复使用。

<name>:表示定义的函数名,通过这个名字来调用整个函数,
[<arg1>…]表示函数的参数,可以省略
<commands>就是函数中的具体命令组合,这些命令组合可以使用传进来的参数。
endfunction()表示整个函数以及定义完成,其中括号里可填,可不填,如果要填的话,其名字必须与function中定义的函数名一致。

add_subdirectory(library)
add_subdirectory(include)

添加子目录。

add_subdirectory (source_dir [binary_dir] [EXCLUDE_FROM_ALL])

  • source_dir
    必选参数。该参数指定一个子目录,子目录下应该包含CMakeLists.txt文件和代码文件。子目录可以是相对路径也可以是绝对路径,如果是相对路径,则是相对当前目录的一个相对路径。
  • binary_dir
    可选参数。该参数指定一个目录,用于存放输出文件。可以是相对路径也可以是绝对路径,如果是相对路径,则是相对当前输出目录的一个相对路径。如果该参数没有指定,则默认的输出目录使用source_dir
  • EXCLUDE_FROM_ALL
    可选参数。当指定了该参数,则子目录下的目标不会被父目录下的目标文件包含进去,父目录的CMakeLists.txt不会构建子目录的目标文件,必须在子目录下显式去构建。例外情况:当父目录的目标依赖于子目录的目标,则子目录的目标仍然会被构建出来以满足依赖关系(例如使用了target_link_libraries)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值