(This is a more specific version of the problem discussed in bash - expand arguments from array containing double quotes .)
I want bash to call cmake with arguments from an array with double quotes which itself contain items from another array. Here is an example for clarification:
cxx_flags=()
cxx_flags+=(-fdiagnostics-color)
cxx_flags+=(-O3)
cmake_arguments=()
cmake_arguments+=(-DCMAKE_BUILD_TYPE=Release)
cmake_arguments+=("-DCMAKE_CXX_FLAGS=\"${cxx_flags[@]}\"")
The arguments shall be printed pretty like this:
$ echo "CMake arguments: ${cmake_arguments[@]}"
CMake arguments: -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="-fdiagnostics-color -O3"
Problem
And finally cmake should be called (this does not work!):
cmake .. "${cmake_arguments[@]}"
It expands to (as set -x
produces):
cmake .. -DCMAKE_BUILD_TYPE=Release '-DCMAKE_CXX_FLAGS="-fdiagnostics-color' '-O3"'
Workaround
echo "cmake .. ${cmake_arguments[@]}" | source /dev/stdin
Expands to:
cmake .. -DCMAKE_BUILD_TYPE=Release '-DCMAKE_CXX_FLAGS=-fdiagnostics-color -O3'
That's okay but it seems like a hack. Is there a better solution?
Update
If you want to iterate over the array you should use one more variable (as randomir and Jeff Breadner suggested):
cxx_flags=()
cxx_flags+=(-fdiagnostics-color)
cxx_flags+=(-O3)
cxx_flags_string="${cxx_flags[@]}"
cmake_arguments=()
cmake_arguments+=(-DCMAKE_BUILD_TYPE=Release)
cmake_arguments+=("-DCMAKE_CXX_FLAGS=\"$cxx_flags_string\"")
The core problem remains (and the workaround still works) but you could iterate over cmake_arguments
and see two items (as intended) instead of three (-DCMAKE_BUILD_TYPE=Release
, -DCMAKE_CXX_FLAGS="-fdiagnostics-color
and -O3"
):
echo "cmake .. \\"
size=${#cmake_arguments[@]}
for ((i = 0; i < $size; ++i)); do
if [[ $(($i + 1)) -eq $size ]]; then
echo " ${cmake_arguments[$i]}"
else
echo " ${cmake_arguments[$i]} \\"
fi
done
Prints:
cmake .. \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_CXX_FLAGS="-fdiagnostics-color -O3"