• CMake中if的使用


          CMake中的if命令用于有条件地执行一组命令,其格式如下:

    1. if()
    2. elseif() # optional block, can be repeated
    3. else() # optional block
    4. endif()

          根据Condition syntax评估if子句的条件参数()。如果结果为true,则执行if块(block)中的命令。否则,以相同方式处理可选的elseif块.最后,如果没有条件为true,则执行可选else块中的命令。

          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():如果常量为1, ON, YES, TRUE, Y或非零数(包括浮点数),则为true。如果常量为0, OFF, NO, FALSE, N, IGNORE, NOTFOUND, 空字符串或以后缀-NOTFOUND结尾,则为false.命名布尔常量不区分大小写。如果参数不是这些特定常量之一,则将其视为变量或字符串,并适用以下两种形式之一。
          (2).if():如果给定一个定义非false常量的值的变量,则为true。否则为false,包括变量未定义时。注意:宏参数不是变量。环境变量也不能以这种方式测试,例如if(ENV{some_var})将始终评估为false.
          (3).if():带引号的字符串始终评估为false,除非:字符串的值是真正的常量之一,或者Policy CMP0054为设置为NEW,并且字符串的值恰好是受CMP0054行为影响的变量名称。

    1. if(ON)
    2. message("on") # print
    3. endif()
    4. if(OFF)
    5. message("off") # won't print
    6. endif()
    7. if(YES)
    8. message("yes") # print
    9. endif()
    10. if(NO)
    11. message("no") # won't print
    12. endif()
    13. if(true)
    14. message("true") # print
    15. endif()
    16. if(TRUE)
    17. message("TRUE") # print
    18. endif()
    19. if(FALSE)
    20. message("FALSE") # won't print
    21. endif()
    22. set(ENV{CMAKE_PREFIX_PATH} "github/fengbingchun")
    23. if(ENV{CMAKE_PREFIX_PATH})
    24. message("env") # won't print
    25. endif()
    26. if("csdn")
    27. message("csdn") # won't print
    28. endif()

          2.Logic Operators:
          (1).if(NOT ):如果条件不为ture,,则为true.
          (2).if( AND ):如果这两个条件都被单独被认为是true,则为true.
          (3).if( OR ):如果任一条件单独被认为是true,则为true.
          (4).if((condition) AND (condition OR (condition))):首先评估括号内的条件,然后像其它示例一样评估其它条件。在有嵌套括号的地方,最里面的小括号作为条件的一部分被评估。

    1. set(var "csdn")
    2. if(NOT var2)
    3. message("not var2") # print
    4. endif()
    5. if(var OR var2)
    6. message("var OR var2") # print
    7. endif()
    8. if(var AND var2)
    9. message("var AND var2") # won't print
    10. endif()

          3.Existence Checks:
          (1).if(COMMAND command-name):如果给定的name是可以调用的命令、宏或函数,则为true.
          (2).if(POLICY policy-id):如果给定的name是存在的policy(形式为CMP),则为true.
          (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 |CACHE{}|ENV{}):如果定义了给定的变量、缓存变量或环境变量,则为true.变量的值无关紧要。注意:宏参数不是变量。无法直接测试是否为非缓存变量。如果存在缓存或非缓存变量someName,则表达式if(DEFINED someName)将评估为true.相比之下,表达式if(DEFINED CACHE{someName})仅在缓存变量someName存在时才为true。如果你需要知道是否存在非缓存变量,则需要测试两个表达式:if(DEFINED someName AND NOT DEFINED CACHE{someName})
          (6).if( IN_LIST ):如果给定元素包含在命名列表变量(named list variable)中,则为true.

    1. function(func)
    2. message("hello func")
    3. endfunction()
    4. if(COMMAND func)
    5. message("func") # print
    6. endif()
    7. if(POLICY CMP0010)
    8. message("policy") # print
    9. endif()
    10. find_package(OpenCV 3.4.2) # -- Found OpenCV: /opt/opencv3.4.2 (found suitable version "3.4.2", minimum required is "3.4.2")
    11. if(TARGET opencv_core)
    12. message("opencv_core") # print
    13. endif()
    14. set(var OFF) # 变量的值无关紧要
    15. if(DEFINED var)
    16. message("defined var") # print
    17. endif()
    18. set(var2 )
    19. if(DEFINED var2)
    20. message("defined var2") # won't print
    21. 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.

    1. if(EXISTS /home/spring/GitHub/Linux_Code_Test/Samples_CMake/messy_usage)
    2. message("exists messy_usage") # print
    3. endif()
    4. if(EXISTS ../../Samples_Make)
    5. message("exists samples_make") # won't print
    6. endif()
    7. 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)
    8. message("is newer") # print
    9. endif()
    10. if(IS_DIRECTORY /home/spring/GitHub)
    11. message("is directory")
    12. endif()
    13. if(IS_SYMLINK /usr/bin/gcc) # /usr/bin/gcc -> gcc-11*
    14. message("is symlink") # print
    15. endif()
    16. if(IS_ABSOLUTE ~/.bashrc)
    17. message("is absolute") # print
    18. endif()

          5.Comparisons:
          (1).if( MATCHES regex):如果给定的字符串或变量的值与给定的正则表达式匹配(matches),则为true.
          (2).if( LESS ):如果给定的字符串或变量的值是有效数字且小于右侧的数字,则为true.
          (3).if( GREATER ):如果给定的字符串或变量的值是有效数字且大于右侧的数字,则为true.
          (4).if( EQUAL ):如果给定的字符串或变量的值是有效数字且等于右侧的数字,则为true.
          (5).if( LESS_EQUAL ):如果给定的字符串或变量的值是有效数字且小于或等于右侧的数字,则为true.
          (6).if( GREATER_EQUAL ):如果给定的字符串或变量的值是有效数字且大于或等于右侧的数字,则为true.
          (7).if( STRLESS ):如果给定的字符串或变量的值按字典顺序(lexicographically)小于右侧的字符串或变量,则为true.
          (8).if( STRGREATER ):如果给定的字符串或变量的值按字典顺序(lexicographically)大于右侧的字符串或变量,则为true.
          (9).if( STREQUAL ):如果给定的字符串或变量的值按字典顺序(lexicographically)等于右侧的字符串或变量,则为true.
          (10).if( STRLESS_EQUAL ):如果给定的字符串或变量的值按字典顺序(lexicographically)小于或等于右侧的字符串或变量,则为true.
          (11).if( STRGREATER_EQUAL ):如果给定的字符串或变量的值按字典顺序(lexicographically)大于或等于右侧的字符串或变量,则为true.

    1. if("cSdN" MATCHES [A-Za-z])
    2. message("matches") # print
    3. endif()
    4. set(var1 4.1)
    5. set(var2 4.2)
    6. if(var1 LESS var2)
    7. message("less") # print
    8. endif()
    9. if(var2 GREATER var1)
    10. message("greater") # print
    11. endif()
    12. if(var1 EQUAL var1)
    13. message("equal") # print
    14. endif()
    15. set(var3 "abc")
    16. set(var4 "ABC")
    17. if(var4 STRLESS var3)
    18. message("strless") # print
    19. endif()
    20. if(var4 STRLESS_EQUAL var3)
    21. message("strelss equal") # print
    22. endif()
    23. if(var3 STRGREATER var4)
    24. message("strgreater") # print
    25. endif()

          6.Version Comparisons:按组件的整数版本号比较(版本格式为major[.minor[.patch[.tweak]]],省略的组件被视为零)。任何非整数版本组件或版本组件的非整数结尾部分都会在该点有效截断字符串。
          (1).if( VERSION_LESS ):如果给定的字符串或变量的值小于右侧的值,则为true.
          (2).if( VERSION_GREATER ):如果给定的字符串或变量的值大于右侧的值,则为true.
          (3).if( VERSION_EQUAL ):如果给定的字符串或变量的值等于右侧的值,则为true.
          (4).if( VERSION_LESS_EQUAL ):如果给定的字符串或变量的值小于或等于右侧的值,则为true.
          (5).if( VERSION_GREATER_EQUAL ):如果给定的字符串或变量的值大于或等于右侧的值,则为true.

    1. set(cv_version1 4.2.1)
    2. set(cv_version2 4.2.5)
    3. if(cv_version1 VERSION_LESS cv_version2)
    4. message("version less") # print
    5. endif()
    6. if(cv_version2 VERSION_GREATER cv_version1)
    7. message("versoin greater") # print
    8. endif()

          7.Path Comparisons:if( PATH_EQUAL ),逐个组件比较两个路径。只有当两条路径的每个组件都匹配时,两条路径比较的结果才为true.多个路径分隔符有效折叠成一个分隔符,但注意反斜杠不会转换为正斜杠。
          由于对多个路径分隔符的处理,基于组件的比较优于基于字符串的比较。

          执行上述测试代码需要3个文件:build.sh, CMakeLists.txt, test_if.cmake

          build.sh内容如下:

    1. #! /bin/bash
    2. # supported input parameters(cmake commands)
    3. params=(function macro cmake_parse_arguments \
    4. find_library find_path find_file find_program find_package \
    5. cmake_policy cmake_minimum_required project include \
    6. string list set foreach message option if while return \
    7. math file)
    8. usage()
    9. {
    10. echo "Error: $0 needs to have an input parameter"
    11. echo "supported input parameters:"
    12. for param in ${params[@]}; do
    13. echo " $0 ${param}"
    14. done
    15. exit -1
    16. }
    17. if [ $# != 1 ]; then
    18. usage
    19. fi
    20. flag=0
    21. for param in ${params[@]}; do
    22. if [ $1 == ${param} ]; then
    23. flag=1
    24. break
    25. fi
    26. done
    27. if [ ${flag} == 0 ]; then
    28. echo "Error: parameter \"$1\" is not supported"
    29. usage
    30. exit -1
    31. fi
    32. if [[ ! -d "build" ]]; then
    33. mkdir build
    34. cd build
    35. else
    36. cd build
    37. fi
    38. echo "==== test $1 ===="
    39. # test_set.cmake: cmake -DTEST_CMAKE_FEATURE=$1 --log-level=verbose ..
    40. # test_option.cmake: cmake -DTEST_CMAKE_FEATURE=$1 -DBUILD_PYTORCH=ON ..
    41. cmake -DTEST_CMAKE_FEATURE=$1 ..
    42. # It can be executed directly on the terminal, no need to execute build.sh, for example: cmake -P test_set.cmake

         CMakeLists.txt内容如下:

    1. cmake_minimum_required(VERSION 3.22)
    2. project(cmake_feature_usage)
    3. message("#### current cmake version: ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION}")
    4. include(test_${TEST_CMAKE_FEATURE}.cmake)
    5. message("==== test finish ====")

          test_if.cmake:为上面的所有示例代码

          可能的执行结果如下图所示:

          GitHub: https://github.com/fengbingchun/Linux_Code_Test

  • 相关阅读:
    推荐一款采用 .NET 编写的 反编译到源码工具 Reko
    centOS7集群hadoop环境搭建
    135:vue+openlayers添加海量点,使用WebGLPoints方法(示例代码)
    Unity3D智慧交通AI插件Urban Traffic System ,大量人物和车辆模型。
    【scala】foreach,forall,map,exists对比
    Vue-依赖注入(provide-inject)
    SpringAMQP
    利用二维码定位技术实现桌面机器人简易定位方案(上篇)
    球面近场多探头一致性校准方法研究
    「Daily OI Round 4」Snow(贪心+模拟)
  • 原文地址:https://blog.csdn.net/fengbingchun/article/details/127946047