如何在CMake的execute_process中传递列表变量?

3
我想用execute_process在子目录中执行CMake命令,并通过-D选项传递一些缓存变量。如果该变量是字符串类型,则可行。但是,如果变量是一个列表,则似乎无法使用命令行中的传递列表的典型方法。我尝试了那个答案中列出的所有组合。我甚至试图使用"\\;""\\\\;"连接mylist。然而,execute_process似乎总是解压'-DVal2=a\\;b\\;c\\;''-DVal2=a;b;c'-Dval2=a b c。我该如何防止这种情况发生?只有-DVal2=a\\;b\\;c有效,但这非常烦人。
set(
    mylist
    a
    b
    c
)

set(
    cmake_args
    "-DVal1=abc"
    "'-DVal2=${mylist}'" #does not work, the execute_process will unpack it into seperated args
)

execute_process(
        COMMAND ${CMAKE_COMMAND} ${cmake_args} ${CMAKE_SOURCE_DIR}/subproject
        OUTPUT_FILE ${CMAKE_BINARY_DIR}/config.log
        ERROR_FILE ${CMAKE_BINARY_DIR}/config.log
        WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/subproject
        RESULT_VARIABLE config_result
)
2个回答

3

在传递该列表之前,请对其运行此行:

string(REPLACE ";" "\\;" escaped_list "${my_list}")

然后传递已转义的列表。在另一端,它将具有与my_list完全相同的值。

例如,

set(my_list "a\;b" "c" "d")
string(REPLACE ";" "\\;" escaped_list "${my_list}")
execute_process(COMMAND ${CMAKE_COMMAND} -Dmy_list=${escaped_list} -P test.cmake)

(已测试使用cmake 3.17版本)。

当将第一个参数分配给 cmake_args 并传递该参数时,这也可以起作用。例如,

test1.cmake

# Construction.
set(my_list "a\;b" "c" "d")
set(other_list "e" "f\;g" "h")

# For debugging purposes.
message("my_list = \"${my_list}\".")
foreach(arg ${my_list})
  message("-> ${arg}")
endforeach()
message("other_list = \"${other_list}\".")
foreach(arg ${other_list})
  message("-> ${arg}")
endforeach()

# Encoding.
string(REPLACE ";" "\\;" escaped_list "${my_list}")
message("escaped_list = \"${escaped_list}\".")

string(REPLACE ";" "\\;" other_escaped_list "${other_list}")
message("other_escaped_list = \"${other_escaped_list}\".")

set(cmake_args "-Dother_list=${other_escaped_list}" "-Dmy_list=${escaped_list}")

execute_process(
  COMMAND
  ${CMAKE_COMMAND} ${cmake_args} -P test2.cmake
)

test2.cmake

# For debugging purpose.
message("my_list = \"${my_list}\".")
foreach(arg ${my_list})
  message("-> ${arg}")
endforeach()

message("other_list = \"${other_list}\".")
foreach(arg ${other_list})
  message("-> ${arg}")
endforeach()

运行 cmake -P test1.cmake 的输出:

my_list = "a\;b;c;d".
-> a;b
-> c
-> d
other_list = "e;f\;g;h".
-> e
-> f;g
-> h
escaped_list = "a\\;b\;c\;d".
other_escaped_list = "e\;f\\;g\;h".
my_list = "a\;b;c;d".
-> a;b
-> c
-> d
other_list = "e;f\;g;h".
-> e
-> f;g
-> h

请仔细观察双引号的使用和未使用位置。

1
我认为您需要转义分号;字符,因为在CMake中,这是列表的默认分隔符,但是不清楚您如何做到这一点,以使其对您起作用。
因此,请尝试类似以下的内容。
set(mylist_str "")

foreach(item ${mylist})
  string(APPEND mylist_str ${item} "\;")
endforeach()

# this is for debugging
message(STATUS "List as string: ${mylist_str}")

set(cmake_args 
    "-DVal1=abc"
    "-DVal2=${mylist_str}"
    "-DVal3=\"${mylist_str}\"" # this has quotes around it
)

# this is for debugging
foreach(item ${cmake_args})
  message(STATUS "A list item: ${item}")
endforeach()

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