在shell脚本中传递CMAKE_CXX_FLAGS

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在shell脚本中传递CMAKE_CXX_FLAGS相关的知识,希望对你有一定的参考价值。

显然,我有一个涉及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随后尝试通过搜索文件名clang -DCMAKE_CXX_FLAGS=-march=native -O3 -DNDEBUG -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=true -DCMAKE_POLICY_DEFAULT_CMP0069=NEW的路径来查找编译器。显然,它没有找到该文件。

如果事情不起作用,那么在文件路径中有空格的情况下使用文件名参数基本上是不可能的。

如果这对您无关紧要,您可以使用一个非常简单的解决方案:像这样调用cmake

cmake ${cmake_params[$i]}

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

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

在现代bash版本中,您可以使用namerefs实现更精确的解决方案。 nameref是使用-n标志声明的变量,其中包含另一个变量的名称。您无法创建namerefs数组,但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
另一答案

以下对我有用:

CMAKE_OPTS="-DBUILD_TESTING=OFF"
CMAKE_DEFAULTS="-GNinja 
                -DCMAKE_BUILD_TYPE=Release 
                "-DCMAKE_CXX_FLAGS_RELEASE:STRING=-Wformat -Werror=format-security -DNDEBUG -Ofast -march=native -flto -mtune=native" 
                -DCMAKE_PREFIX_PATH=${INSTALL_PREFIX} 
                -DCMAKE_INSTALL_PREFIX=${INSTALL_PREFIX} 
"

curl -L -o source.tar.gz ${SRC_URL}
tar -xzf source.tar.gz

rm -rf build_ && mkdir build_ && cd build_
eval "cmake ${CMAKE_DEFAULTS} ${CMAKE_OPTS} ${SRC_PATH}"
cmake --build . --target install

基本上,事情是将整个-DCMAKE_CXX_FLAGS_RELEASE包裹在""中,然后在那上面调用eval(Impurity!我知道我知道......)。

以上是关于在shell脚本中传递CMAKE_CXX_FLAGS的主要内容,如果未能解决你的问题,请参考以下文章

将 $@ 传递给 shell 脚本中的函数

Linux Shell脚本之向脚本传递参数

[Shell]向shell脚本传递参数

shell脚本在java中传递值属性文件

如何在 Python 中使用 argparse 传递 Shell 脚本样式参数

如何将 shell 脚本中的结果传递给 Job 中的变量