gpt4 book ai didi

bash - 在 shell 脚本中传递 CMAKE_CXX_FLAGS

转载 作者:行者123 更新时间:2023-11-29 09:31:14 25 4
gpt4 key购买 nike

很明显,我遇到了一个涉及 bash 和 cmake 以及引用的乏味问题。我需要使用不同的 cmake 标志多次编译一个程序。经过大量猜测,我在 bash 脚本中得出了以下结构:

cmake_params[1]=-DCMAKE_CXX_FLAGS=-O2\ -DNDEBUG
cmake_params[2]=-DCMAKE_CXX_FLAGS=-march=native\ -O2\ -DNDEBUG
# ....

#compile with:

for i in {1..n}
do
# .. prepare ..
mkdir build
cd build
cmake "${cmake_params[$i]}" ..
make
done

请注意,我在 cmake_params 中转义了空格,并且使用双引号调用了 cmake。然而,最后,我需要能够将标志扩展到像这样糟糕的东西:

cmake_params[1]=-DCMAKE_CXX_COMPILER="clang++"\
-DCMAKE_C_COMPILER="clang"\
-DCMAKE_CXX_FLAGS=-march=native\ -O3\ -DNDEBUG\
-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=true\
-DCMAKE_POLICY_DEFAULT_CMP0069=NEW

但这行不通。我尝试在 CXX 标志周围加上引号,在编译器周围省略引号,在实际的 cmake 调用中尝试省略引号,但都没有成功。错误消息各不相同,最突出的是:

The CMAKE_CXX_COMPILER:

clang++ -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_FLAGS=-march=native -O3 -DNDEBUG
-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=true -DCMAKE_POLICY_DEFAULT_CMP0069=NEW

is not a full path and was not found in the PATH.

很明显,cmake 误解了我的命令行。更清楚地说,我想将 clang++ 作为 CMAKE_CXX_COMPILER 传递,将 -march=native -O3 -DNDEBUG 作为 CMAKE_CXX_FLAGS 传递。

哪个 bash 脚本会执行此操作以及为什么 - 是否有任何关于引用和参数传递如何工作的资源?我真的是一个接一个地尝试找到有用的东西,但这甚至不是有根据的猜测..

最佳答案

当你写的时候(在 bash 中):

cmake "${cmake_params[$i]}"

您要求它调用命令行实用程序 cmake,向该实用程序传递一个参数,该参数是 cmake_params 数组的指定元素的值。与任何其他命令行实用程序一样,cmake 不会尝试重新解释它接收到的参数;它假定您已安排向其传递正确的参数。所以当它收到一个参数时,它说:

-DCMAKE_C_COMPILER=clang -DCMAKE_CXX_FLAGS=-march=native -O3 -DNDEBUG -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=true -DCMAKE_POLICY_DEFAULT_CMP0069=NEW

它继续将其内部变量 CMAKE_C_COMPILER 的值(= 之前的 id)设置为值 clang -DCMAKE_CXX_FLAGS=-march=native -O3 -DNDEBUG -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=true -DCMAKE_POLICY_DEFAULT_CMP0069=NEW

cmake 随后尝试通过搜索文件名的路径来找到编译器>。显然,它没有找到该文件。

如果事情没有那样进行,那么基本上不可能在文件路径中有空格的地方使用文件名参数。

如果这对您来说不重要,您可以采用一个非常简单的解决方案:像这样调用 cmake:

cmake ${cmake_params[$i]}

这告诉 shell 获取数组 cmake_params 的指示元素的值,然后(因为它没有被引用)它对该值执行分词和路径名扩展,导致一个参数列表,然后将其单独传递给 cmake

在您提供的示例中,这应该可以正常工作。但它很脆弱,甚至很危险。首先,因为会进行路径名扩展,所以值中的*可能会变成当前目录下的完整文件列表。其次,因为分词是使用变量 $IFS 的值完成的,可以想象它可能已被更改。最后,请注意 shell 解释扩展值内的引号(包括反斜杠)或参数扩展,因此无法将值内的某些空白标记为免于分词。这意味着您将无法使用其中包含空格的文件名或文件路径。

在现代 bash 版本中,您可以使用 namerefs 实现更精确的解决方案。 nameref 是用 -n 标志声明的变量,并带有另一个变量的名称。您不能创建 nameref 数组,但 nameref 可以引用数组。

考虑到这一点,我们可以重写您最初的想法:

# Each param set has its own array variable. There is no need to use
# integer suffixes; you could use more descriptive tags. Just make sure
# that there is no other variable whose name starts with the same prefix.
# Since we are creating arrays, we do *not* quote whitespace *unless*
# it is really part of a parameter value.
declare -a cmake_params_1=(-DCMAKE_CXX_FLAGS=-O2 -DNDEBUG)
declare -a cmake_params_2=(-DCMAKE_CXX_FLAGS=-march=native -O2 -DNDEBUG)
# ....

# Now we can loop through the various arrays of parameter lists:

# ${!word*} expands to a list of existing variables whose names start with word
for name in "${!cmake_params_*}"; do
# Create a nameref for the array whose name we got from the list
declare -n array=$name
# .. prepare ..
mkdir build
cd build
# Here we can use "array" as though it were the variable named in the argument
cmake "${array[@]}" ..
make
done

关于bash - 在 shell 脚本中传递 CMAKE_CXX_FLAGS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49459975/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com