CMake中的if命令用于有条件地执行一组命令,其格式如下:
- if(
) -
- elseif(
) # optional block, can be repeated -
- else() # optional block
-
- endif()
根据Condition syntax评估if子句的条件参数(
Condition Syntax:以下语法适用于if、elsif和while子句的条件参数。
复合条件(compound condition)按以下优先顺序进行评估:
(1).括号(Parentheses).
(2).一元测试(unary tests),例如EXISTS、COMMAND和DEFINED。
(3).二元测试(binary tests),例如EQUAL,LESS,LESS_EQUAL,GREATER,GREATER_EQUAL,STREQUAL,STRLESS,STRLESS_EQUAL,STRGREATER,STRGREATER_EQUAL, VERSION_EQUAL,VERSION_LESS,VERSION_LESS_EQUAL,VERSION_GREATER,VERSION_GREATER_EQUAL, PATH_EQUAL和MATCHES.
(4).一元逻辑运算符(unary logical operator):NOT
(5).二元逻辑运算符(binary logical operators):AND和OR,从左到右,没有任何短路(without any short-circuit)。
1.Basic Expressions:
(1).if(
(2).if(
(3).if(
- if(ON)
- message("on") # print
- endif()
- if(OFF)
- message("off") # won't print
- endif()
-
- if(YES)
- message("yes") # print
- endif()
- if(NO)
- message("no") # won't print
- endif()
-
- if(true)
- message("true") # print
- endif()
- if(TRUE)
- message("TRUE") # print
- endif()
- if(FALSE)
- message("FALSE") # won't print
- endif()
-
- set(ENV{CMAKE_PREFIX_PATH} "github/fengbingchun")
- if(ENV{CMAKE_PREFIX_PATH})
- message("env") # won't print
- endif()
-
- if("csdn")
- message("csdn") # won't print
- endif()
2.Logic Operators:
(1).if(NOT
(2).if(
(3).if(
(4).if((condition) AND (condition OR (condition))):首先评估括号内的条件,然后像其它示例一样评估其它条件。在有嵌套括号的地方,最里面的小括号作为条件的一部分被评估。
- set(var "csdn")
-
- if(NOT var2)
- message("not var2") # print
- endif()
-
- if(var OR var2)
- message("var OR var2") # print
- endif()
- if(var AND var2)
- message("var AND var2") # won't print
- endif()
3.Existence Checks:
(1).if(COMMAND command-name):如果给定的name是可以调用的命令、宏或函数,则为true.
(2).if(POLICY policy-id):如果给定的name是存在的policy(形式为CMP
(3).if(TARGET target-name):如果给定的name是通过调用(在任何目录中)add_executable, add_library, 或add_custom_target命令创建的现有逻辑目标名称(existing logical target name),则为true.
(4).if(TEST test-name):如果给定的name是由add_test命令创建的现有测试名称(existing test name),则为true.
(5).if(DEFINED
(6).if(
- function(func)
- message("hello func")
- endfunction()
-
- if(COMMAND func)
- message("func") # print
- endif()
-
- if(POLICY CMP0010)
- message("policy") # print
- endif()
-
- find_package(OpenCV 3.4.2) # -- Found OpenCV: /opt/opencv3.4.2 (found suitable version "3.4.2", minimum required is "3.4.2")
- if(TARGET opencv_core)
- message("opencv_core") # print
- endif()
-
- set(var OFF) # 变量的值无关紧要
- if(DEFINED var)
- message("defined var") # print
- endif()
-
- set(var2 )
- if(DEFINED var2)
- message("defined var2") # won't print
- endif()
4.File Operations:
(1).if(EXISTS path-to-file-or-directory):如果指定的文件或目录存在,则为true。仅针对显式完整路径(Behavior is well-defined only for explicit full paths).解析符号链接,如果符号链接的目标存在,则为true.
(2).if(file1 IS_NEWER_THAN file2):如果file1比file2新,或两个文件中的一个不存在,则为true。仅针对完整路径。如果文件时间戳完全相同,则IS_NEWER_THAN比较返回true,这包括为file1和file2传递相同文件名的情况。
(3).if(IS_DIRECTORY path-to-directory):如果给定name是目录,则为true。仅针对完整路径。
(4).if(IS_SYMLINK file-name):如果给定name是符号链接,则为true.仅针对完整路径。
(5).if(IS_ABSOLUTE path):如果给定路径是绝对路径,则为true。注意以下特殊情况:空路径评估为false。在windows主机上,任何以驱动器号和冒号(例如 C:)、正斜杠或反斜杠开头的路径都将评估为true.这意味着像C:no\base\dir这样的路径将评估为true.在非windows主机上,任何以波浪号(~)开头的路径都为true.
- if(EXISTS /home/spring/GitHub/Linux_Code_Test/Samples_CMake/messy_usage)
- message("exists messy_usage") # print
- endif()
- if(EXISTS ../../Samples_Make)
- message("exists samples_make") # won't print
- endif()
-
- if(/home/spring/GitHub/Linux_Code_Test/Samples_CMake/messy_usage/test_find_package.cmake IS_NEWER_THAN /home/spring/GitHub/Linux_Code_Test/Samples_CMake/messy_usage/test_xxxx.cmake)
- message("is newer") # print
- endif()
-
- if(IS_DIRECTORY /home/spring/GitHub)
- message("is directory")
- endif()
-
- if(IS_SYMLINK /usr/bin/gcc) # /usr/bin/gcc -> gcc-11*
- message("is symlink") # print
- endif()
-
- if(IS_ABSOLUTE ~/.bashrc)
- message("is absolute") # print
- endif()
5.Comparisons:
(1).if(
(2).if(
(3).if(
(4).if(
(5).if(
(6).if(
(7).if(
(8).if(
(9).if(
(10).if(
(11).if(
- if("cSdN" MATCHES [A-Za-z])
- message("matches") # print
- endif()
-
- set(var1 4.1)
- set(var2 4.2)
- if(var1 LESS var2)
- message("less") # print
- endif()
- if(var2 GREATER var1)
- message("greater") # print
- endif()
- if(var1 EQUAL var1)
- message("equal") # print
- endif()
-
- set(var3 "abc")
- set(var4 "ABC")
- if(var4 STRLESS var3)
- message("strless") # print
- endif()
- if(var4 STRLESS_EQUAL var3)
- message("strelss equal") # print
- endif()
- if(var3 STRGREATER var4)
- message("strgreater") # print
- endif()
6.Version Comparisons:按组件的整数版本号比较(版本格式为major[.minor[.patch[.tweak]]],省略的组件被视为零)。任何非整数版本组件或版本组件的非整数结尾部分都会在该点有效截断字符串。
(1).if(
(2).if(
(3).if(
(4).if(
(5).if(
- set(cv_version1 4.2.1)
- set(cv_version2 4.2.5)
-
- if(cv_version1 VERSION_LESS cv_version2)
- message("version less") # print
- endif()
- if(cv_version2 VERSION_GREATER cv_version1)
- message("versoin greater") # print
- endif()
7.Path Comparisons:if(
由于对多个路径分隔符的处理,基于组件的比较优于基于字符串的比较。
执行上述测试代码需要3个文件:build.sh, CMakeLists.txt, test_if.cmake
build.sh内容如下:
- #! /bin/bash
-
- # supported input parameters(cmake commands)
- params=(function macro cmake_parse_arguments \
- find_library find_path find_file find_program find_package \
- cmake_policy cmake_minimum_required project include \
- string list set foreach message option if while return \
- math file)
-
- usage()
- {
- echo "Error: $0 needs to have an input parameter"
-
- echo "supported input parameters:"
- for param in ${params[@]}; do
- echo " $0 ${param}"
- done
-
- exit -1
- }
-
- if [ $# != 1 ]; then
- usage
- fi
-
- flag=0
- for param in ${params[@]}; do
- if [ $1 == ${param} ]; then
- flag=1
- break
- fi
- done
-
- if [ ${flag} == 0 ]; then
- echo "Error: parameter \"$1\" is not supported"
- usage
- exit -1
- fi
-
- if [[ ! -d "build" ]]; then
- mkdir build
- cd build
- else
- cd build
- fi
-
- echo "==== test $1 ===="
-
- # test_set.cmake: cmake -DTEST_CMAKE_FEATURE=$1 --log-level=verbose ..
- # test_option.cmake: cmake -DTEST_CMAKE_FEATURE=$1 -DBUILD_PYTORCH=ON ..
- cmake -DTEST_CMAKE_FEATURE=$1 ..
- # It can be executed directly on the terminal, no need to execute build.sh, for example: cmake -P test_set.cmake
CMakeLists.txt内容如下:
- cmake_minimum_required(VERSION 3.22)
- project(cmake_feature_usage)
-
- message("#### current cmake version: ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION}")
- include(test_${TEST_CMAKE_FEATURE}.cmake)
- message("==== test finish ====")
test_if.cmake:为上面的所有示例代码
可能的执行结果如下图所示:
