7.4 用指定参数定义函数或宏

    前面的示例中,我们研究了函数和宏,并使用了位置参数。这个示例中,我们将定义一个带有命名参数的函数。我们将复用第1节中的示例,使用函数和宏重用代码,而不是使用以下代码定义测试:。

    我们将这样调用函数:

    我们使用第1节中的示例,使用函数和宏重用代码,并保持C++源代码不变,文件树保持不变:

    1. .
    2. ├── cmake
    3. └── testing.cmake
    4. ├── CMakeLists.txt
    5. ├── src
    6. ├── CMakeLists.txt
    7. ├── main.cpp
    8. ├── sum_integers.cpp
    9. └── sum_integers.hpp
    10. └── tests
    11. ├── catch.hpp
    12. ├── CMakeLists.txt
    13. └── test.cpp

    我们对CMake代码进行一些修改,如下所示:

    1. 保持src/CMakeLists.txt

    2. tests/CMakeLists.txt中,将add_catch_test函数定义移动到cmake/testing.cmake,并且定义两个测试:

      1. add_executable(cpp_test test.cpp)
      2. target_link_libraries(cpp_test sum_integers)
      3. include(testing)
      4. add_catch_test(
      5. short
      6. LABELS
      7. short
      8. cpp_test
      9. 1.5
      10. )
      11. add_catch_test(
      12. NAME
      13. long
      14. LABELS
      15. long
      16. cpp_test
      17. COST
      18. 2.5
      19. )
    3. add_catch_testcmake/testing.cmake中定义:

    4. 测试输出:

      1. $ mkdir -p build
      2. $ cd build
      3. $ cmake ..
      4. -- ...
      5. -- defining a test ...
      6. -- NAME: short
      7. -- COST: 1.5
      8. -- REFERENCE_FILES:
      9. -- defining a test ...
      10. -- NAME: long
      11. -- LABELS: long;cpp_test
      12. -- COST: 2.5
      13. -- REFERENCE_FILES:
      14. -- ...

    示例的特点是其命名参数,因此我们可以将重点放在模块上。CMake提供cmake_parse_arguments命令,我们使用函数名(add_catch_test)选项(我们的例子中是none)、单值参数(NAMECOST)和多值参数(LABELSDEPENDSREFERENCE_FILES)调用该命令:

    1. function(add_catch_test)
    2. set(options)
    3. set(oneValueArgs NAME COST)
    4. set(multiValueArgs LABELS DEPENDS REFERENCE_FILES)
    5. cmake_parse_arguments(add_catch_test
    6. "${options}"
    7. "${oneValueArgs}"
    8. "${multiValueArgs}"
    9. ${ARGN}
    10. )
    11. ...
    12. endfunction()

    cmake_parse_arguments命令解析选项和参数,并在例子中定义如下:

    • add_catch_test_NAME
    • add_catch_test_COST
    • add_catch_test_LABELS
    • add_catch_test_DEPENDS
    • add_catch_test_REFERENCE_FILES

    可以查询,并在函数中使用这些变量。这种方法使我们有机会用更健壮的接口和更具有可读的函数/宏调用,来实现函数和宏。

    选项关键字(本例中我们没有使用)由cmake_parse_arguments定义为TRUEFALSEadd_catch_test函数,还提供test命令作为一个命名参数,为了更简洁的演示,我们省略了这个参数。