Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/cmake/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/heroku/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash 在shell脚本中传递CMAKE_CXX_标志_Bash_Cmake_Escaping_Quoting - Fatal编程技术网

Bash 在shell脚本中传递CMAKE_CXX_标志

Bash 在shell脚本中传递CMAKE_CXX_标志,bash,cmake,escaping,quoting,Bash,Cmake,Escaping,Quoting,显然,我有一个涉及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 .

显然,我有一个涉及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_参数中转义了空格,并且使用双引号调用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\u CXX\u编译器
-march=native-O3-DNDEBUG
作为
CMAKE\u CXX\u标志
传递

哪个bash脚本会这样做?为什么?有关于引用和参数传递工作原理的参考资料吗?我真的一件接一件地试图找到一些有效的方法,但这甚至不是经过教育的猜测。

当你(在bash中)写作时:

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

-DCMAKE_C_COMPILER=clang -DCMAKE_CXX_FLAGS=-march=native -O3 -DNDEBUG -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=true -DCMAKE_POLICY_DEFAULT_CMP0069=NEW
它继续将其内部变量
CMAKE\u C\u COMPILER
=
)的值设置为value
clang-DCMAKE\u CXX\u FLAGS=-march=native-O3-DNDEBUG-DCMAKE\u过程间优化=true-DCMAKE\u策略\u默认值\u CMP0069=NEW

cmake
随后尝试通过搜索文件名路径来查找编译器
clang-DCMAKE\u CXX\u FLAGS=-march=native-O3-DNDEBUG-DCMAKE\u INTERPROCEDURAL\u OPTIMIZATION=true-DCMAKE\u POLICY\u DEFAULT\u CMP0069=NEW
。显然,它找不到那个文件

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

如果这对您来说无关紧要,您可以使用一个非常简单的解决方案:像这样调用
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

以下几点对我很有用:

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\u CXX\u FLAGS\u RELEASE
包装在
\“\”
中,然后调用
eval
(杂质!我知道我知道…)。

很抱歉我的回复太晚,谢谢你对这个话题的解释!我尝试了两种方法,但是,我仍然无法让它工作。当我使用第一个idea
cmake${cmake_params[$I]}
时,cmake_CXX_标志设置不正确。我在命令行参数中得到了error
Parse error:-DNDEBUG
-我认为,这意味着-DNDEBUG直接传递给cmake,而不是作为cmake\u CXX\u标志的一部分。在CMAKE_CXX_标志周围使用引号没有帮助,例如
-DCMAKE_CXX_标志=“-march=native-DNDEBUG-O3”
。根据ccmake的输出,如果我使用nameref思想,则根本不会传递标志。。。。。。这有点奇怪,当我对它们使用echo命令时,这些标志就在那里。我的bash似乎很老了,我的版本(4.2.26)不知道declare命令的-n标志。你有什么运气吗?
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