Bash 在shell脚本中传递CMAKE_CXX_标志
显然,我有一个涉及bash和cmake以及引用的乏味问题。 我需要用不同的cmake标志多次编译一个程序。经过大量猜测,我在bash脚本中提出了以下结构: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 .
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
(=
)的值设置为valueclang-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
(杂质!我知道我知道…)。很抱歉我的回复太晚,谢谢你对这个话题的解释!我尝试了两种方法,但是,我仍然无法让它工作。当我使用第一个ideacmake${cmake_params[$I]}
时,cmake_CXX_标志设置不正确。我在命令行参数中得到了errorParse 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