我们可以在模板源文件中使用CMake foreach吗?

3

为了对我的函数进行单元测试,我已自动生成名称,如下:

test_implode test_range

并将它们存储到CMake变量中。

我想在 C 语言中自动调用这些函数。我在 CMake 中还使用了配置文件(.in.c)。

set(CONFIG configuration)
configure_file(${CONFIG}.in.c ${CONFIG}.c)
set(CONFIG_SRC ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG}.c)

但是在CMake中,函数的名称仅仅是一个列表,并不是有效的C语法。我可以在CMake中生成具有适当语法的变量,但是在配置文件中生成输出将使CMake源文件保持清洁并且可能非常强大。

具体来说,我想做的是(虚构的语法):

#include "tests.h"

void all_tests() {

    void(*tests)()[] = {
    @FOREACH(FUNC FUNCTIONS)@
        test_@FUNC@,
    @ENDFOREACH()@
        NULL
    };

    void(*test_function)() = tests[0];

    while(test_function) {
        test_function();
        test_function++;
    }
}

与Blade或PHP类似,我能否将CMake用作脚本语言(或foreach)?或者必须将其放在CMake源文件中并将其存储到变量中?目前我正在做的事情是可接受的,但我想学习并了解它是否仍然可行。
foreach(PHP_FUNCTION ${PHP_FUNCTIONS})
  list(APPEND GENERATED_C_CODE_RUN_TEST "\n\ttest_${PHP_FUNCTION}()")
endforeach()

set(GENERATED_C_CODE_RUN_TEST "${GENERATED_C_CODE_RUN_TEST};")
set(CONFIG configuration)
configure_file(${CONFIG}.in.c ${CONFIG}.c)
set(CONFIG_SRC ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG}.c)
add_executable(...);

#include "tests.h"

void all_tests() {

    @GENERATED_C_CODE_RUN_TEST@
}

CMake模板引擎用于configure_file,功能不是很强大。它所支持的一切在文档中都有描述。正如您所看到的,它没有“foreach”功能。因此,如果您不想使用另一个模板引擎(非CMake),则需要构建中间变量。顺便说一下,CMake也会在其自己的一些模块中做这样的事情。例如,查看Modules/目录中的CheckTypeSize.c.in或其他.in文件。 - Tsyvarev
1个回答

3
一种解决方法是将列表中的每个测试名称附加上前缀test_,然后使用list(JOIN ...)构造一个表示逗号分隔列表的字符串(这是有效的C语法)。
list(APPEND PHP_FUNCTIONS
    func1
    func2
    func3
)

# Append the 'test_' prefix to each test function name.
foreach(PHP_FUNCTION ${PHP_FUNCTIONS})
    list(APPEND FUNCTION_NAMES_LIST "test_${PHP_FUNCTION}")
endforeach()
message(STATUS "FUNCTION_NAMES_LIST: ${FUNCTION_NAMES_LIST}")

# Construct a comma-separated string from the list.
list(JOIN FUNCTION_NAMES_LIST "," FUNCTION_NAMES_STRING)
message(STATUS "FUNCTION_NAMES_STRING: ${FUNCTION_NAMES_STRING}")

这将打印以下内容:

FUNCTION_NAMES_LIST: test_func1;test_func2;test_func3
FUNCTION_NAMES_STRING: test_func1,test_func2,test_func3

接着,您可以修改您的configuration.in.c文件,这样只需要替换一个变量:

void all_tests() {

    void(*tests)()[] = {
        @FUNCTION_NAMES_STRING@,
        NULL
    };

    void(*test_function)() = tests[0];

    while(test_function) {
        test_function();
        test_function++;
    }
}

您可以尝试使用不同的“粘合剂”或分隔符字符串来连接CMake列表。在我的例子中,我使用了",",但您也可以使用 ", "",\n\t" 使结果 C 代码更加美观易读。CMake的 list()(和string())有许多操作选项可供尝试,鼓励您去查看。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接