Mastering CMake 第四章 CMakeList编写(2)

第四章 CMakeList编写(2)

Table of Contents

第四章 CMakeList编写(2)

4.4 正则表达式

4.5 检测CMake版本 

4.6 模块的使用

在SWIG中使用CMake

在Qt中使用CMake

在FLTK中使用CMake

相关链接:


4.4 正则表达式

一些CMake命令(例如if和string)需要利用正则表达式,或者可以将正则表达式用作参数。 最简单的形式是,正则表达式是一串用于搜索精确字符匹配的字符序列。 但是,很多时候,确切的字符序列都不是很明确,或者只希望在字符串的开头或结尾进行匹配。 由于用于指定正则表达式的约定有多种,因此下面将介绍CMake的标准。 该说明基于Texas Instruments的开源正则表达式类,CMake使用该类来解析正则表达式。

可以通过使用标准字母数字字符和以下正则表达式元字符的组合来指定正则表达式:

^ 匹配行或字符串的开头。
$ 匹配行或字符串的末尾。
.  匹配换行符以外的任何单个字符。
[xy]  匹配方括号内的任何字符。
[^xy] 匹配不在方括号内的任何字符。
[a-b] 匹配破折号两侧任意范围内的字符。
*  匹配先前的子表达式零次或多次。
+ 匹配先前的子表达式一次或多次。
?匹配先前的子表达式零或仅匹配一次。
() 保存匹配的表达式,并在以后的替换中使用它。
(|) 匹配条形图的左侧或右侧。

请注意,可以在单个正则表达式中使用多个元字符,用来实现更复杂的搜索模式。 例如,模式[^ ab1-9]表示要匹配任何不以字符“ a”或“ b”或1到9之间的数字开头的字符序列。 以下示例可以帮助阐明正则表达式的用法:

  • 正则表达"^hello"只有在搜索字符串的开头和"hello"匹配。它可以与"hello there"匹配,但是"hi,\nhello"则不行。
  • 正则表达"long$"只有在搜索字符串的结尾和"long"匹配。它可以与"so long"匹配,但是"long ago"则不行。
  • 正则表达"t..t..g"会匹配的任意字符串,其中包含一个"t", 接着是两个任意字符、另一个字符"t"和两个任意字符,最后一个字符"g"。它可以与"testing"或者"test again"匹配,但是"toasting"则不行。
  • 正则表达"[1-9ab]"可以匹配任何1~9之间的字符和字符"a","b"。它可以与"hello  1"或"begin"匹配,但是"no-match"则不行。
  • 正则表达"[^1-9ab]"可以匹配任何不是1~9之间的字符或字符"a","b"。它不可以与"1ab2"或"b2345a"匹配,但是可以和"no-match"匹配。
  • 正则表达"br* "可以匹配的字符串,需要以"b"开头,后面没有字符或者紧跟着多个"r", 最后以空格结束。它可以与"brrrr "和"b "匹配,但是"brrh "则不行。
  • 正则表达"br+ "可以匹配的字符串,需要以"b"开头,后面紧跟着一个或多个"r", 最后以空格结束。它可以与"brrrr "和"br "匹配,但是"b "和"brrh "则不行。
  • 正则表达"br? "可以匹配的字符串,需要以"b"开头,后面没有字符或者紧跟着一个"r", 最后以空格结束。它可以与"br "和"b "匹配,但是"brrrr "和"brrh "则不行。
  • 正则表达 "(..p)b"可以匹配的字符串,需要以"pb"结束,同时在该行中的第一个p之前以任意两个字符开头。它可以在”rep drepaqrepb"中匹配到"repb"。正则表达 "(..p)a"可以在"rep drepa qrepb"中匹配到 "repa qrepb"。
  •  正则表达 "d(..p)"可以匹配的字符串,需要以"p"结束,以字符"d"开头,同时中间的两个字符和该行中的第一个p之前的两个字符相同。它可以在”rep drepaqrepb"中匹配到"repb"。可以在"rep drepa qrepb"中匹配到 ”drepa qrepb"。

a{2,4} 匹配2~4个a。
\w+     匹配多个字母。
\d+     匹配多个数字。
\s       匹配一个空格。
\+       匹配一个+。
\[        匹配一个[。
good (morning|evening|afternoon)    匹配多种模式。
^\s*$  匹配空白行。

辅助工具:https://regex101.com/

4.5 检测CMake版本 

CMake是一个不断更新的程序,随着新版本的发布,可能会引入新的功能或命令。 因此,在某些情况下,您可能想使用CMake的当前版本中的命令,而不是先前版本中的命令。 有两种方法可以解决此问题。 一种选择是使用if命令检查是否有新
命令存在。 例如:

# test if the command exists
if (COMMAND some_new_command)
    # use the command
    some_new_command (ARGS...)
endif (COMMAND some_new_command)

上面的方法在大多数情况下应该可行,但是如果您需要更多信息,则可以通过评估CMAKE_VERSION变量来对照正在运行的CMake的实际版本,如以下示例所示:

# look for newer version of CMake
# https://blog.csdn.net/k_shmily
if (${CMAKE_VERSION} VERSION_GRATER 1.6.1)
    # do something special here
endif ()

编写CMakeLists文件时,您可能会决定不再支持CMake的旧版本。 为此,您可以将以下命令放在CMakeLists文件的顶部:

cmake_minmum_required(VERISON 2.2)

这表明在您的项目上运行CMake的人必须具有版本至少为2.2的CMake。 如果他们运行的是较旧版本的CMake,则将显示一条错误消息,告诉他们该项目至少需要指定版本的CMake。

最后,在某些情况下,可能会发布新版本的CMake,该版本不再支持您正在使用的某些命令(尽管我们尝试避免这种情况)。 在这些情况下,您可以使用CMake策略,如第4.7节中所述。

4.6 模块的使用

代码重用是软件开发中的一种有价值的技术,而CMake的设计也很好地支持这一特征。允许CMakeLists文件使用可重用模块,使得整个CMake社区可以共享代码的可重用部分。对于CMake这些代码段称为模块,可以在CMake安装的Modules子目录中找到。
模块只是放在文件中的CMake命令的一部分。然后可以使用include命令将它们包含在其他CMakeLists文件中。例如,以下命令将包括来自CMake的FindTCL模块,然后将Tcl库添加到目标FOO。

include(FindTCL)
target_link_libraries(FOO ${TCL_LIBRARY})

可以使用模块文件的完整路径或让CMake自己查找模块来指定模块的位置。 CMake将在CMAKE_MODULE_PATH指定的目录中查找模块,如果找不到,则将在CMake的Modules子目录中查找。https://blog.csdn.net/k_shmily 这样,项目可以覆盖CMake提供的模块,以根据需要对其进行自定义。模块可以分为如下几个主要类别:

查找模块

这些模块确定诸如头文件或库之类的软件元素的位置。

系统自检模块

这些模块测试系统的属性,例如浮点数的大小,对ANSI C++流的支持等。

实用程序模块

这些模块还提供了附加功能,例如一个CMake项目依赖于另一个项目以及其他便利例程的情况。

现在让我们更详细地考虑这三种类型的模块。 CMake包含大量的查找模块。 查找模块的目的是查找诸如头文件或库文件之类的软件元素。 如果找不到它们,那么它们将提供一个缓存条目,以便用户可以设置所需的属性。 考虑以下查找PNG库的模块。

模块顶部清楚地记录了模块将执行的操作以及它将设置的变量。接下来它包括另一个模块即FindZLIB模块,判断是否安装了ZLib库。接下来,如果找到ZLib,则使用find_path命令查找PNG包含文件。第一个参数是存储结果的变量的名称,第二个参数是要查找的头文件的名称,其余参数是搜索头文件的路径。如果在系统路径中找不到,则将该变量设置为PNG_PNG_INCLUDE_DIR-NOTFOUND,使用户可以对其进行设置。

请注意,搜索PNG库的路径可以包括硬编码目录,注册表项以及由其他CMake变量组成的目录。下一条命令使用find_library命令查找实际的PNG库。此命令执行其他检查以找到适当的库名称,例如在Linux系统上会在名称的前面添加“ lib”,并在名称末尾添加“ .so”。

在find调用之后,设置了一些CMake变量,利用FindPNG开发人员可以在他们的项目中使用这些变量(例如include路径和库名)。 最后PNG_FOUND正确设置,这使得开发人员知道正确地找到了PNG库。

对于CMake中所有查找模块,这种结构都是相当普遍的。 通常它们很短,但是在某些情况下,例如FindopenGL,它们可能有几页长。 它们通常独立于其他模块,但是对其他模块的使用没有限制。

系统自检模块提供有关目标平台或编译器的信息。 其中许多模块的名称以Test或Check开头,例如TestBigEndian和CheckTypesize。 实际上,许多系统自省模块都会尝试编译代码以确定正确的结果。 在这些情况下,源代码通常与模块命名相同,但扩展名为.c或.cxx。 第5章将更详细地介绍系统自检模块。

CMake包括一些实用程序模块,可帮助用户更加轻松地使用CMake。 CMakeExportBuildSettings和CMakeImportBuildSettings提供工具来帮助验证两个C++项目是否使用相同的编译器和键标志而进行编译的。 CMakePrintsystemInformation模块可打印出许多关键的CMake设置,以帮助调试。

在SWIG中使用CMake

一个关于如何使用模块的示例是,使用SWIG在另一种语言中包装C / C ++代码。 SWIG(Simplified Wrapper and Interface Generater 简化包和接口生成器)www.swig.org是一种工具,可读取带注释的C / C ++头文件,并创建包装器代码(胶水代码),使得相应的C / C ++库可用于其他编程语言,例如 Tcl,Python或Java。 CMake通过find_ package命令支持SWIG的使用。 尽管可以使用自定义命令从CMake中调用SWIG,但SWIG包提供了一些宏,这些宏使得在CMake构造SWIG项目时更加简单。 要使用SWIG宏,首先必须使用名称SWIG调用find_package命令。 然后,您需要包含变量SWIG_USE_FILE引用的文件。 这将定义若干个宏并设置CMake,轻松地构建出基于SWIG的项目。

两个非常有用的宏是SWIG_ADD_MODULE和SWIG_LINK_LIBRARIES。 SWIG_ADD_MODULE的工作方式与CMake中的add_library命令非常相似。 该命令是这样调用的:

SWIG_ADD_MODULE(module_name language source1 source2 ... sourceN)

第一个参数是要创建的模块名称。下一个参数是SWIG正在为其生成包装的目标语言。其余参数由用于创建共享模块的源文件列表组成。最大的不同是SWIG .i接口文件可以直接用作源。该宏将创建正确的自定义命令来运行SWIG,并从SWIG接口文件生成C或C ++包装器代码。源也可以是常规C或C ++文件,这些文件需要使用包装程序进行编译。

SWIG_LINK_LIBRARIES宏用于将支持库链接到模块。使用此宏是因为根据SWIG包装的语言,模块的名称可能不同。模块的实际名称存储在名为SWIG_MODULE_$ {name} _REAL_NAME的变量中,其中$ {name}是传递给SWIG_ADD_MODULE宏的名称。例如,SWIG_ADD_MODULE(foo tcl foo.i)将创建一个名为SWIG_MODULE_foo_REAL_NAME的变量,其中将包含创建的实际模块的名称。

现在考虑以下示例,该示例使用在SWIG中的Examples / python / class下的SWIG示例。

此示例首先使用find_package查找SWIG。 接下来是包含定义了SWIG CMake宏SWIG_USE_FILE。 然后,它找到Python库并设置CMake,利用Python库进行构建。 注意,SWIG输入文件example.i的用法与CMake中的任何其他源文件一样,并且在文件上设置了属性,告诉SWIG该文件为C ++,并且在该源文件上运行SWIG时SWIG标志——includeall将会被使用 。 通过告诉SWIG模块名称,目标语言和源文件列表来创建模块。 最后,Python库将被链接到该模块。

在Qt中使用CMake

可以使用CMake来构建使用来自诺基亚(qt.nokia.com)的流行小工具Qt的项目。 CMake支持Qt的多个版本,包括版本3和4。第一步是告诉CMake寻找Qt的版本。 许多Qt应用程序旨在与Qt3或Qt4一起使用,但不能同时与这两者一起使用。 如果您的应用程序是为Qt4设计的,则可以将FindQt4模块用于,Qt3则应使用FindQt3模块。 如果您的项目可以使用任一版本的Qt,则可以使用通用的FindQt模块。 所有模块都为构建Qt项目提供了有用的工具。 以下是构建使用Qt4的项目的简单示例。

在FLTK中使用CMake

利用带有特殊的FLTK CMake命令, CMake还支持的Fast Light Toolkit(FLTK)。 FLTK_WRAP_UI命令用于在.fl文件上运行fltk流体程序并生成C ++源文件作为构建的一部分。 以下示例显示了如何将FLTK与CMake一起使用。

find_package(FLTK)
if (FLTK_FOUND)
    set(FLTK_SRCS
        fltk1.fl)
    FLTK_WRAP_UI(wraplibFLTK ${FLTK_SRCS})
    add_library(wraplibFLTK ${wraplibFLTK_UI_SRCS})
endif (FLTK_FOUND)

 

相关链接:

Matering CMake 第四章 CMakeList编写(1)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值