我正在尝试编写一个脚本,该脚本将使用 bash 脚本为不同的消毒剂构建多个 cppUtes lib.a 文件。
当尝试将编译器标志作为变量传递给 cmake 时,我无法正确格式化它们。请参阅下面的简短示例。
#!/bin/sh
set -euo pipefail
COMMON_OPTS='-fno-common -g -fno-omit-frame-pointer'
ASAN_OPT='-fsanitize=address'
ASAN_C_FLAGS="-DCMAKE_C_FLAGS=\"$ASAN_OPT $COMMON_OPTS\""
echo "cmake ../ $ASAN_C_FLAGS"
cmake ../ $ASAN_C_FLAGS
make
echo 的输出正是我所期望的,以及在未在 bash 脚本中运行时设置标志的有效方法:
cmake ../ -DCMAKE_C_FLAGS="-fsanitize=address -fno-common -g -fno-omit-frame-pointer"
但是,当我运行脚本时,cmake 无法正确解释这些标志。它们不会出现在配置期间显示的 cmake 标志中:
CppUTest CFLAGS: -include "/home/ubuntu/cpputest/include/CppUTest/MemoryLeakDetectorMallocMacros.h" -Wall -Wextra -pedantic -Wshadow -Wswitch-default -Wswitch-enum -Wconversion -Wsign-conversion -Wno-padded -Wno-long-long -Wstrict-prototypes
最后,我从 make 中得到以下编译错误:
c++: error: unrecognized argument to '-fsanitize=' option: 'address -g -fno-omit-frame-pointer'
任何帮助将不胜感激。
答案1
请考虑使用数组来保存选项。这样,您仍然能够正确地将它们cmake
作为单独的参数提供,而不是作为 shell 将在空格上分割并执行文件名通配的单个字符串。
shellsh
通常不支持数组,因此我更改了 -line#!
来调用bash
:
#!/bin/bash
set -euo pipefail
common_opts=( -fno-common -g -fno-omit-frame-pointer )
asan_opt='-fsanitize=address'
asan_c_cflags=( -DCMAKE_C_FLAGS="$asan_opt" "${common_opts[@]}" )
echo "cmake ${asan_c_cflags[@]} ../"
cmake "${asan_c_cflags[@]}" ../
make
在这里,数组允许我们传递多个带引号的参数,而cmake
无需将它们降级为单个字符串并依赖 shell 正确地 split+glob 它。这也使我们能够正确传递可能由带空格的字符串组成的参数。
有关的:
答案2
此处的问题是由于 中的转义引号ASAN_C_FLAGS
,CMake 会将其变量视为带引号的值CMAKE_C_FLAGS
,因此会将整个变量作为单个参数传递给编译器。删除这些转义引号后,CMake 应在将传递的参数传递给编译器之前,在空格处正确拆分传递的参数。