CMake入门实践之语法(2)

续文章 CMake入门实践之语法(1)

8. 变量 EXECUTABLE_OUTPUT_PATH, LIBRARY_OUTPUT_PATH

EXECUTABLE_OUTPUT_PATH 为生成可执行文件路径, LIBRARY_OUTPUT_PATH为生成库文件路径。我们可以通过 SET 指令对其进行设置最终目标二进制的位置,即最终生成的工程可执行文件与最终的共享库,而不会包含生成的中间文件。

命令如下:

SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)

9. LINK_DIRECTORIES

格式:

LINK_DIRECTORIES(directory1 directory2 ...)
# 该指令用于添加外部库的搜索路径

10. TARGET_LINK_LIBARRIES

格式:

TARGET_LINK_LIBRARIES(target library1 <debug | optimized> library2 ..)

# target:目标文件
# library1, ... , library N :链接外部库文件
# 指定链接目标文件时需要 链接的外部库,效果类似 gcc 编译参数 -L ,解决外部库依赖的问题。

11. MESSAGE

向终端输出用户定义的信息和变量值,格式:

MESSAGE([SEND_ERROR | STATUS | FATAL_ERROR] “message to display” …)

# SEND_ERROR : 产生错误,生成过程被跳过
# STATUS : 输出前缀为 - 的信息
# FATAL_ERROR : 立即终止所有 cmake 过程

12. SET_TARGET_PROPERTIES

设置目标的某些属性,改变它们的构建方式。格式:

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

该指令为一个目标设置属性,语法是列出所有用户想要变更的文件,然后提供想要设置的值。用户可以使用任何想用的属性与对应的值,并在随后的代码中调用 GET_TARGET_PROPERTY 命令取出属性的值。

影响目标输出文件按的属性 PROPERTY 详述如下:

-- PREFIX, SUFFIX :PREFIX 覆盖了默认的目标名前缀(如lib); SUFFIX 覆盖了默认的目标名后缀(如 .so)。

-- IMPORT_PREFIX,IMPORT_SUFFIX:与 PREFIX, SUFFIX是等价的属性,但针对的是 DLL 导入库(即共享库目标)。

-- OUTPUT_NAME :构建目标时, OUTPUT_NAME 用来设置目标的真实名称。

-- LINK_FLAGS : 为一个目标的链接阶段添加额外标志。LINK_FLAGS_<CONFIG> 将为配置 <CONFIG> 添加链接标志,如DEBUG/RELEASE/MINSIZEREL/RELWITHDEBINFO。

-- COMPILE_FLAGS : 设置附加的编译器标志,在构建目标内的源文件时被用到。

-- LINKER_LANGUAGE :改变链接可执行文件或共享库的工具。默认是设置与库中文件相匹配的语言。 CXX和C是该属性的公共值。

-- VERSION, SOVERSION : VERSION 指定构建的版本号, SOVERSION 指定构建的 API 版本号。构建或安装时,如果平台支持符号链接,且链接器支持 so 名称,那么恰当的符号链接将会被创建。如果只指定两者中的一个,缺失的另一个假定为具有相同的版本号。

示例1:

SET_TARGET_PROPERTIES(hello_static PROPERTIES OUTPUT_NAME "hello")

 示例2:

SET_TARGET_PROPERTIES(hello PROPERTEIES VERSION 1.2 SOVERSION 1)

13. AUX_SOURCE_DIRECTORY

查找某个路径下的所有源文件,并将源文件列表存储到一个变量中。

格式:

AUX_SOURCE_DIRECTORY(< dir > < variable >)

示例:

AUX_SOURCE_DIRECTORY(. SRC_LIST)
# 该指令将当前目录下的文件列表全部存入变量 SRC_LIST

14. INSTALL 

INSTALL 命令可以按照对象的不同分为三种类型:目标文件、非目标文件、目录。

-- 目标文件

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

# TARGETS targets :targets 即为我们通过 ADD_EXECUTABLE 或 ADD_LIBRARY 定义的目标文件,可能
# 是可执行的二进制、动态库、静态库;

# DESTINATION <dir> : dir 即为定义的安装路径。安装路径可以是 绝对/相对路径。
# 如果路径以 / 开头,则是绝对路径,且绝对路径的情况下, CMAKE_INATLL_PREFIX 就失效了。

# 注:如果希望使用 CMAKE_INSTALL_PREFIX 定义安装路径,就需要使用相对路径,这时候安装后的路径就是
# ${CMAKE_INSTALL_PREFIX}/<dir>

# 略去其他参数详解,待续

-- 非目标文件

.sh 脚本文件,即为典型的非目标文件的额可执行程序。

格式:

INSTALL(PROGRAMS files... DESTINATION < dir >
    [PERMISSIONS permissions...]
    [CONFIGURATIONS [Debug|Release|...]]
    [COMPONENT < component >]
    [RENAME < name >] [OPTIONAL])

# 使用方法基本和上述目标文件指令的 INSTALL 相同,
# 唯一不同的是,安装非目标文件之后的权限为 OWNER_EXECTE, GROUP_EXECUTE, WORLD_EXECUTE, 
# 即755权限目录的安装

-- 目录

格式:

INSTALL(DIRECTORY dirs... DESTINATION < dir >
    [FILE_PERMISSIONS permissions...]
    [DIRECTORY_PERMISSIONS permissions...]
    [USE_SOURCE_PERMISSIONS]
    [CONFIGURATIONS [Debug|Release|...]]
    [COMPONENT < component >]
    [[PATTERN < pattern > | REGEX < regex >]
    [EXCLUDE] [PERMISSIONS permissions...]] [...])

# DIRECTORY dirs :  dirs 是所在源文件目录的相对路径。
# 但需要注意的是: abc 与 abc/ 有很大的区别:
# 若是 abc, 则该目录将被安装为目标路径 abc;
# 若是 abc/,则代表将该目录内容安装到目标路径,但不包括该目录本身

示例:

INSTALL(DIRECTORY icons scripts/ DESTINATION share/myproj
    PATTERN "CVS" EXCLUDE
    PATTERN "scripts/*" PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ)

# 该指令的执行结果是:
# -- 将 icons 目录安装到 <prefix>/share/myproj
# -- 将scripts/ 中的内容安装到 <prefix>/share/myproj
# -- 不包含目录名 CVS 的目录
# -- 对于 scripts/* 文件指定权限为 OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ

三、基本控制语法

1. IF

IF...ELSE... 语法格式基本类似于 C语言,大致如下:

IF (expression)
    COMMAND1(ARGS ...)
    COMMAND2(ARGS ...)
    ...
ELSE (expression)
    COMMAND1(ARGS ...)
    COMMAND2(ARGS ...)
    ...
ENDIF (expression)

# 其中,一定要有 ENDIF 与 IF 对应。

(1)IF 基本用法

-- IF(expression), expression 不为:空,0, N, NO, FALSE, NOTFOUND 或 <var>_NOTFOUND时,为真

-- IF(not exp),与上面相反;

-- IF(var1 AND var2)

-- IF(var1 OR var2)

-- IF(COMMAND cmd) 如果cmd确实是命令并可调用,为真

--IF(EXISTS dir) 如果目录存在,为真

--IF(EXISTS file) 如果文件存在,为真

--IF(file1 IS_NEWER_THAN file2) 当file1 比file2新,或file1/file2 中有一个不存在时为真,文件名需使用全路径

--IF(IS_DIRECTORY dir) 当 dir 是目录时,为真

--IF(DEFINE var) 如果变量被定义,为真

--IF(var MATCHES regex) 此处 var 可以用 var名,也可以用 ${var}

--IF(string MATCHES regex) 当给定变量或字符串能匹配正则表达式 regex 时,为真

示例:

IF ("hello" MATCHES "ell")
MESSAGE("true")
ENDIF("hello" MATCHES "ell")

(2) 数字比较表达式

-- IF(var LESS number)

-- IF(var GREATER number)

-- IF(var EQUAL number)

(3) 字母表顺序比较

-- IF(var1 STRLESS var2)

-- IF(var1 STRGREATER var2)

-- IF (var1 STREQUAL var2)

示例1.1:

IF(WIN32)
    MESSAGE(STATUS "This is windows.")
ELSE(WIN32)
    MESSAGE(STATUS "This is not windows.")
ENDIF(WIN32)

# 上述代码可以控制不同平台进行不同的控制

注:也许 ELSE(WIN32) 之类的语句阅读起来不舒服,这时候可以加上语句:

SET(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON)

示例1.2:

SET(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON)

IF(WIN32)
    MESSAGE(STATUS "This is windows.")
ELSE()
    MESSAGE(STATUS "This is not windows.")
ENDIF()

示例2:配合 ELSEIF使用,不同平台上的控制

IF(WIN32)
    #do something related to WIN32
ELSEIF(UNIX)
    #do something related to UNIX
ELSEIF(APPLE)
    #do something related to APPLE
ENDIF (WIN32)

2. WHILE

语法结构:

WHILE(condition)
    COMMAND1(ARGS ...)
    COMMAND2(ARGS ...)
    ...
ENDWHILE(condition)

#真假判断条件参考 IF 指令

3. FOREACH

FOREACH 有三种使用形式的语法,且每个 FOREACH 都需要一个 ENDFOREACH() 与之匹配。

(1) 列表语法

FOREACH(loop_var arg1 arg2 ...)
     COMMAND1(ARGS ...)
     COMMAND2(ARGS ...)
 ...
ENDFOREACH(loop_var)

示例:

AUX_SOURCE_DIRECTORY(. SRC_LIST)
FOREACH(F ${SRC_LIST})
     MESSAGE(${F})
ENDFOREACH(F)

# 将当前路径下的所有源文件列表赋值给变量 SRC_LIST, 任何遍历 SRC_LIST 中的文件,并持续输出信息
# 信息内容是当前路径下所有源文件的名称

(2)范围语法

FOREACH(loop_var RANGE total)
    COMMAND1(ARGS ...)
    COMMAND2(ARGS ...)
    ...
ENDFOREACH(loop_var)

示例:

FOREACH(VAR RANGE 10)
   MESSAGE(${VAR})
ENDFOREACH(VAR)

# 示例从 0 到 total,此处为10, 以 1 为步进
# 此处输出为: 012345678910

(3)范围步进语法

FOREACH(loop_var RANGE start stop [step])
    COMMAND1(ARGS ...)
    COMMAND2(ARGS ...)
    ...
ENDFOREACH(loop_var)

# 从 start 开始,到 stop 结束, 以 step 为步进

示例:

FOREACH(A RANGE 5 15 3)
    MESSAGE(${A})
ENDFOREACH(A)

# 此处输出为:581114

猜你喜欢

转载自blog.csdn.net/JACK_YOUNG007/article/details/88875406