cmake - 字符串中的变量引用不会被“set”评估
问题描述
我想要与 如何在 CMake 中以“bar = foo”语法加载变量相同?
不同之处在于我的“值”条目包含对“键”(预期变量)的引用。
例如 BASEPATH 变量:
BASEPATH:=/home/SomePath
LIB_BASE?=$(BASEPATH)/lib/$(LIBREV)
ACCELMOD_BASE=$(BASEPATH)/SomeOtherPath
我已经修改了我的 CMakeLists.txt 脚本以将 [Key/value] 对从每一行提取到两个变量(请参见下面的代码)并最终得到类似的对(请注意,该值仍然包含对某些变量名称的引用,该名称通常是在文件开头定义):
[BASEPATH, /home/SomePath],
[LIB_BASE, ${BASEPATH}/lib/${LIBREV}],
[ACCELMOD_BASE, ${BASEPATH}/SomeOtherPath],
我写的代码如下:
# Part2
file(STRINGS revisions.mk ConfigContents)
foreach(NameAndValue ${ConfigContents})
# Strip leading spaces
string(REGEX REPLACE "^[ ]+" "" NameAndValue ${NameAndValue})
#remove commented lines
string(FIND ${NameAndValue} "#" commentIndex)
if(${commentIndex} EQUAL 0)
continue()
endif()
# Find variable name
string(REGEX MATCH "^[^\\?:=]+" Name ${NameAndValue})
# Find the value
string(REGEX REPLACE "^(.+)=(.+)$" "\\2" Value ${NameAndValue})
# Replace () with {} to denote a cmake's variable reference
string(REGEX REPLACE "\\(([^)]+)\\)" "{\\1}" Value ${Value})
# Set the variable
set(${Name} ${Value})
message("> Value of " ${Name} " : " ${${Name}})
endforeach()
我希望当我将键(名称)定义为变量(使用set命令)并将其值设置为键的对应值时,字符串中的引用将被引用变量的当前值替换。
然而,这种情况并非如此。例如对于给定输入,循环结束前的消息命令返回:
>Value of BASEPATH: /home/SomePath
>Value of LIB_BASE : ${BASEPATH}/lib/${LIBREV}
>Value of ACCELMOD_BASE: $(BASEPATH)/SomeOtherPath
即使已经定义了 BASEPATH。
为了验证我的预期,我编写了以下简单代码来模拟循环中的行为:
set(BASE 123)
set(RIGHT '${BASE}/SomePath/AA')
set(LEFT_STR "LEFT")
set(${LEFT_STR} ${RIGHT})
message(">" ${LEFT} "<>" ${${LEFT_STR}})
在这种情况下, ${BASE} 引用被正确替换并且
'123/SomePath/AA'<>'123/SomePath/AA'
按预期返回。
我可能做错了什么?
解决方案
从 CMake 3.18 开始,CMake 中有 eval - cmake_language(EVAL CODE
。请参阅https://cmake.org/cmake/help/latest/command/cmake_language.html?highlight=eval。
cmake_langauge(EVAL CODE "set(${Name} ${Value})")
eval
中没有cmake
。流行且容易出错的方法是创建一个脚本,然后包含它:
file(STRINGS revisions.mk ConfigContents)
set(varlist "")
foreach(NameAndValue ${ConfigContents})
# Strip leading spaces
string(REGEX REPLACE "^[ ]+" "" NameAndValue ${NameAndValue})
#remove commented lines
string(FIND ${NameAndValue} "#" commentIndex)
if(${commentIndex} EQUAL 0)
continue()
endif()
# Find variable name
string(REGEX MATCH "^[^\\?:=]+" Name ${NameAndValue})
# Find the value
string(REGEX REPLACE "^(.+)=(.+)$" "\\2" Value ${NameAndValue})
# Replace () with {} to denote a cmake's variable reference
string(REGEX REPLACE "\\(([^)]+)\\)" "{\\1}" Value ${Value})
# Set the variable
set(${Name} ${Value})
list(APPEND varlist ${Name})
endforeach()
set(script "")
foreach(i IN LISTS varlist)
string(APPEND script "set(${i} \"${${i}}\")\n")
endforeach()
file(WRITE script2.cmake ${script})
include(script2.cmake)
foreach(i IN LISTS varlist)
message(STATUS ${i}=${${i}})
endforeach()
这将创建包含以下内容的脚本script2.cmake
:
set(BASEPATH "/home/SomePath")
set(LIB_BASE "${BASEPATH}/lib/${LIBREV}")
set(ACCELMOD_BASE "${BASEPATH}/SomeOtherPath")
然后include
s它。包括这样的脚本将重新评估表达式,从而解决引用。
推荐阅读
- python-3.x - python中的端口扫描器无法正常工作
- powershell - PowerShell - 将属性 BULK 更改为用户列表
- linux - 如何在 GNU 并行中插入睡眠?
- angular - 提交,keyup.enter 不适用于 Angular 10
- flutter - 颤振 - 如何将文本表单字段提交到注册按钮?
- lua - Lua eof 函数,如何推断结束命令的数量和解释
- android - 如何在我的浮动按钮中仅单击一次
- python - 使用 Python 的 ggplot2 实现“plotnine”的每小时热图?
- reactjs - 如何动态更新数组的一个元素
- reactjs - 是否可以将clevertap推送通知与expo reactnative集成