First of all, thank you all for trying to help out! Unfortunately, so far no solution has been found yet. I am updating the description to make the problem more reproducible.
- Update1: use shellcheck.net to clear all other potential issues.
- Update2: describe the real use case where we run cmake below.
Section 1: minimal case
First found the issue with cmake
but it may not be limited to it, by changing cmake
in the following minimal reproducible example to make
or something else could also reproduce the problem.
#!/bin/bash
set -x
run() {
arg=$1
printf '%q\n' "$arg"
cmake "$arg" 1>/dev/null 2>&1
}
TEXT="local -DCMAKE_ARG=\"arg1;arg2\""
CMAKE_OPTS1=$(echo "$TEXT" | awk '/local/ {for (i=1; i<=NF; i++) {if ($i ~ /^-D/) {printf "%s ", $i}}}' | tr -d '";')
CMAKE_OPTS2=$(echo "$TEXT" | awk '/local/ {for (i=1; i<=NF; i++) {if ($i ~ /^-D/) {printf "%s ", $i}}}' )
CMAKE_OPTS3=("$(echo "$TEXT" | awk '/local/ {for (i=1; i<=NF; i++) {if ($i ~ /^-D/) {printf "%s ", $i}}}' )")
run $CMAKE_OPTS1
run $CMAKE_OPTS2
run "${CMAKE_OPTS3[@]}"
the print out results are (reducing to the lines of interests)
-DCMAKE_ARG=arg1arg2
+ cmake -DCMAKE_ARG=arg1arg2
-DCMAKE_ARG=\"arg1\;arg2\"
+ cmake '-DCMAKE_ARG="arg1;arg2"'
-DCMAKE_ARG=\"arg1\;arg2\"\
+ cmake '-DCMAKE_ARG="arg1;arg2" '
Unfortunately, cmake '-DCMAKE_ARG="arg1;arg2"'
does not work properly.
- CMAKE_OPTS1 is only used for reference, in this case no special characters present in the variable string, and it seems to be working as expected.
- CMAKE_OPTS2 is the real case where I wish to pass variable containing special characters as argument to a command. Hence the single marks seem to be interfering with command argument parsing.
- CMAKE_OPTS3 is what I have found from similar issues on this forum, and it does not work either.
Section 2: original script
with lots of modification to minimize the script of course. Hence it involves pulling from a docker and a GitHub repo, both are public and open source.
First, pull docker from Docker Hub (to ensure necessary clang env):
docker pull rocm/miopen:ci
Then within the docker, use the following script:
#!/bin/bash
set -x
build_miopen_ck() {
echo "Building Composable Kernel"
ck_commit=$1
ck_cmake_opts=$2
if [ -z "$ck_commit" ]; then
echo "Composable Kernel entry was not found in requirements.txt"
return
fi
mkdir -p /tmp/composable_kernel && cd /tmp/composable_kernel || exit
wget -nv "https://www.github.com/ROCmSoftwarePlatform/composable_kernel/archive/${ck_commit}.tar.gz"
tar -xzf "${ck_commit}.tar.gz"
cd "composable_kernel-${ck_commit}" || exit
rm -rf build
mkdir -p build && cd build || exit
cmake -DBUILD_DEV=OFF \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_CXX_COMPILER="/opt/rocm/llvm/bin/clang++" \
-DCMAKE_C_COMPILER="/opt/rocm/llvm/bin/clang" \
-DCMAKE_PREFIX_PATH="$ROCM_PATH" \
"${ck_cmake_opts}" \
..
make -j"$(nproc)" install
echo "Finished building Composable Kernel"
}
TEXT="ROCmSoftwarePlatform/composable_kernel@5f28614222bd590bc31d98838bc019e9c3a7ad45 -DGPU_TARGETS=\"gfx900;gfx906;gfx908;gfx90a;gfx1030;gfx1100;gfx1101;gfx1102\""
CK_COMMIT=$(echo "$TEXT" | awk '/composable_kernel/ {split($1, s, "@"); print s[2]}')
CK_CMAKE_OPTS=$(echo "$TEXT" | awk '/composable_kernel/ {for (i=1; i<=NF; i++) {if ($i ~ /^-D/) {printf "%s ", $i}}}')
build_miopen_ck "$CK_COMMIT" "$CK_CMAKE_OPTS"
Soon (might be a while) the build will fail with the following error:
clang-15: error: invalid target ID 'gfx900 --offload-arch=gfx906 --offload-arch=gfx908 --offload-arch=gfx90a --offload-arch=gfx1030 --offload-arch=gfx1100 --offload-arch=gfx1101 --offload-arch=gfx1102'; format is a processor name followed by an optional colon-delimited list of features followed by an enable/disable sign (e.g., 'gfx908:sramecc+:xnack-')
and by diagnosing the log, the single quotes look suspecious:
cmake -DBUILD_DEV=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=/opt/rocm/llvm/bin/clang++ -DCMAKE_C_COMPILER=/opt/rocm/llvm/bin/clang -DCMAKE_PREFIX_PATH= '-DGPU_TARGETS="gfx900;gfx906;gfx908;gfx90a;gfx1030;gfx1100;gfx1101;gfx1102" ' ..
if I go to the directory, and re-run cmake with
cmake -DBUILD_DEV=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=/opt/rocm/llvm/bin/clang++ -DCMAKE_C_COMPILER=/opt/rocm/llvm/bin/clang -DCMAKE_PREFIX_PATH= -DGPU_TARGETS="gfx900;gfx906;gfx908;gfx90a;gfx1030;gfx1100;gfx1101;gfx1102" ..
then everything works as expected from there.
From the error above, it should have something to do with shell parameter expansion:
- it should read as
'--offload-arch=gfx900' '--offload-arch=gfx906' ...
but instead, the single quotes are messing up the **secondary** parsing process, and it reads as if it is:
'--offload-arch=gfx900 --offload-arch=gfx906 ...'
As related to the minimal example above, if passing variable containing special characters as argument to a command does not automatically add a pair of single quote, we should not have this secondary parsing issues?
A few experiments so far:
- as recommended by one of the users below, removing
set -x
does not resolve this issue unfortunately :( - maybe the minimal example above is still a good starting point? Is there a way to avoid adding single quotes? When are they added and how to remove? It's not part of the string itself unfortunately.
Workaround:
So far a working workaround is to grep the string after -DGPU_TARGETS=
, i.e. instead of cmake "$arg"
we can make the following work cmake -DGPU_TARGETS="${subset_arg}"
. However, this is a workaround and the original issue still persists.