Unquoted Special Characters in CFLAGS cause sh explain in unexcepted ways using Makefile Generator

CMake Version: All

Original Problem: I was using CMake in Bazel Foreign CC with custom toolchain with my own sysroot. Some CMake project failed to detect C ABI for there were special CFLAGS set in my project.

Detecting C compiler ABI info failed to compile with the following output:
Change Dir: /dev/shm/bazel-sandbox.f316d661a48e25ccef9f1eecf2ee79753df8a7d415e5ae7c930614d775411cf4/linux-sandbox/5851/execroot/moffett_software/bazel-out/k8-fastbuild/bin/external/tvm/tvm.build_tmpdir/CMakeFiles/CMakeTmp

Run Build Command(s):/dev/shm/bazel-sandbox.f316d661a48e25ccef9f1eecf2ee79753df8a7d415e5ae7c930614d775411cf4/linux-sandbox/5851/execroot/moffett_software/bazel-out/k8-opt-exec-2B5CBBC6/bin/external/rules_foreign_cc/toolchains/make/bin/make -f Makefile cmTC_c0496/fast && /dev/shm/bazel-sandbox.f316d661a48e25ccef9f1eecf2ee79753df8a7d415e5ae7c930614d775411cf4/linux-sandbox/5851/execroot/moffett_software/bazel-out/k8-opt-exec-2B5CBBC6/bin/external/rules_foreign_cc/toolchains/make/bin/make  -f CMakeFiles/cmTC_c0496.dir/build.make CMakeFiles/cmTC_c0496.dir/build
make[1]: Entering directory '/dev/shm/bazel-sandbox.f316d661a48e25ccef9f1eecf2ee79753df8a7d415e5ae7c930614d775411cf4/linux-sandbox/5851/execroot/moffett_software/bazel-out/k8-fastbuild/bin/external/tvm/tvm.build_tmpdir/CMakeFiles/CMakeTmp'
Building C object CMakeFiles/cmTC_c0496.dir/CMakeCCompilerABI.c.o
/dev/shm/bazel-sandbox.f316d661a48e25ccef9f1eecf2ee79753df8a7d415e5ae7c930614d775411cf4/linux-sandbox/5851/execroot/moffett_software/external/llvm_toolchain/bin/cc_wrapper.sh --sysroot=/dev/shm/bazel-sandbox.f316d661a48e25ccef9f1eecf2ee79753df8a7d415e5ae7c930614d775411cf4/linux-sandbox/5851/execroot/moffett_software/external/sysroot_data/sysroot   -DLLVM_ON_UNIX=1 -DHAVE_BACKTRACE=1 -DBACKTRACE_HEADER=<execinfo.h> -DLTDL_SHLIB_EXT=\".so\" -DLLVM_PLUGIN_EXT=\".so\" -DLLVM_ENABLE_THREADS=1 -DHAVE_DEREGISTER_FRAME=1 -DHAVE_LIBPTHREAD=1 -DHAVE_PTHREAD_GETNAME_NP=1 -DHAVE_PTHREAD_GETSPECIFIC=1 -DHAVE_PTHREAD_H=1 -DHAVE_PTHREAD_SETNAME_NP=1 -DHAVE_REGISTER_FRAME=1 -DHAVE_SETENV_R=1 -DHAVE_STRERROR_R=1 -DHAVE_SYSEXITS_H=1 -DHAVE_UNISTD_H=1 -D_GNU_SOURCE -DHAVE_LINK_H=1 -DHAVE_LSEEK64=1 -DHAVE_MALLINFO=1 -DHAVE_SBRK=1 -DHAVE_STRUCT_STAT_ST_MTIM_TV_NSEC=1 -DLLVM_NATIVE_ARCH=\"X86\" -DLLVM_NATIVE_ASMPARSER=LLVMInitializeX86AsmParser -DLLVM_NATIVE_ASMPRINTER=LLVMInitializeX86AsmPrinter -DLLVM_NATIVE_DISASSEMBLER=LLVMInitializeX86Disassembler -DLLVM_NATIVE_TARGET=LLVMInitializeX86Target -DLLVM_NATIVE_TARGETINFO=LLVMInitializeX86TargetInfo -DLLVM_NATIVE_TARGETMC=LLVMInitializeX86TargetMC -DLLVM_NATIVE_TARGETMCA=LLVMInitializeX86TargetMCA -DLLVM_HOST_TRIPLE=\"x86_64-unknown-linux-gnu\" -DLLVM_DEFAULT_TARGET_TRIPLE=\"x86_64-unknown-linux-gnu\" -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS --sysroot=/dev/shm/bazel-sandbox.f316d661a48e25ccef9f1eecf2ee79753df8a7d415e5ae7c930614d775411cf4/linux-sandbox/5851/execroot/moffett_software/external/sysroot_data/sysroot -no-canonical-prefixes -Wno-builtin-macro-redefined -D__DATE__=\"redacted\" -D__TIMESTAMP__=\"redacted\" -D__TIME__=\"redacted\" -fdebug-prefix-map=/dev/shm/bazel-sandbox.f316d661a48e25ccef9f1eecf2ee79753df8a7d415e5ae7c930614d775411cf4/linux-sandbox/5851/execroot/moffett_software/external/llvm_toolchain_llvm/=__bazel_toolchain_llvm_repo__/ -isystem /dev/shm/bazel-sandbox.f316d661a48e25ccef9f1eecf2ee79753df8a7d415e5ae7c930614d775411cf4/linux-sandbox/5851/execroot/moffett_software/external/llvm_toolchain_llvm/include/c++/v1 -isystem /dev/shm/bazel-sandbox.f316d661a48e25ccef9f1eecf2ee79753df8a7d415e5ae7c930614d775411cf4/linux-sandbox/5851/execroot/moffett_software/external/llvm_toolchain_llvm/lib/clang/13.0.0/include -isystem /dev/shm/bazel-sandbox.f316d661a48e25ccef9f1eecf2ee79753df8a7d415e5ae7c930614d775411cf4/linux-sandbox/5851/execroot/moffett_software/external/llvm_toolchain_llvm/13.0.0 -isystem /dev/shm/bazel-sandbox.f316d661a48e25ccef9f1eecf2ee79753df8a7d415e5ae7c930614d775411cf4/linux-sandbox/5851/execroot/moffett_software/external/sysroot_data/sysroot/usr/include    -v -MD -MT CMakeFiles/cmTC_c0496.dir/CMakeCCompilerABI.c.o -MF CMakeFiles/cmTC_c0496.dir/CMakeCCompilerABI.c.o.d -o CMakeFiles/cmTC_c0496.dir/CMakeCCompilerABI.c.o -c /home/mana/.cache/bazel/_bazel_mana/2839d09d05b0b4238bee86f1d6235c83/external/cmake-3.22.1-linux-x86_64/share/cmake-3.22/Modules/CMakeCCompilerABI.c
/bin/sh: execinfo.h: No such file or directory
make[1]: *** [CMakeFiles/cmTC_c0496.dir/build.make:79: CMakeFiles/cmTC_c0496.dir/CMakeCCompilerABI.c.o] Error 1
make[1]: Leaving directory '/dev/shm/bazel-sandbox.f316d661a48e25ccef9f1eecf2ee79753df8a7d415e5ae7c930614d775411cf4/linux-sandbox/5851/execroot/moffett_software/bazel-out/k8-fastbuild/bin/external/tvm/tvm.build_tmpdir/CMakeFiles/CMakeTmp'
make: *** [Makefile:127: cmTC_c0496/fast] Error 2

and I found In the try_compile Makefile:

CMakeFiles/cmTC_c0496.dir/CMakeCCompilerABI.c.o: CMakeFiles/cmTC_c0496.dir/compiler_depend.ts
	@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --progress-dir=/dev/shm/bazel-sandbox.f316d661a48e25ccef9f1eecf2ee79753df8a7d415e5ae7c930614d775411cf4/linux-sandbox/5851/execroot/moffett_software/bazel-out/k8-fastbuild/bin/external/tvm/tvm.build_tmpdir/CMakeFiles/CMakeTmp/CMakeFiles --progress-num=$(CMAKE_PROGRESS_1) "Building C object CMakeFiles/cmTC_c0496.dir/CMakeCCompilerABI.c.o"
	/dev/shm/bazel-sandbox.f316d661a48e25ccef9f1eecf2ee79753df8a7d415e5ae7c930614d775411cf4/linux-sandbox/5851/execroot/moffett_software/external/llvm_toolchain/bin/cc_wrapper.sh --sysroot=/dev/shm/bazel-sandbox.f316d661a48e25ccef9f1eecf2ee79753df8a7d415e5ae7c930614d775411cf4/linux-sandbox/5851/execroot/moffett_software/external/sysroot_data/sysroot $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -MD -MT CMakeFiles/cmTC_c0496.dir/CMakeCCompilerABI.c.o -MF CMakeFiles/cmTC_c0496.dir/CMakeCCompilerABI.c.o.d -o CMakeFiles/cmTC_c0496.dir/CMakeCCompilerABI.c.o -c /home/mana/.cache/bazel/_bazel_mana/2839d09d05b0b4238bee86f1d6235c83/external/cmake-3.22.1-linux-x86_64/share/cmake-3.22/Modules/CMakeCCompilerABI.c

here is my C_FLAGS


C_FLAGS = -DLLVM_ON_UNIX=1 -DHAVE_BACKTRACE=1 -DBACKTRACE_HEADER=<execinfo.h> -DLTDL_SHLIB_EXT=\".so\" -DLLVM_PLUGIN_EXT=\".so\" -DLLVM_ENABLE_THREADS=1 -DHAVE_DEREGISTER_FRAME=1 -DHAVE_LIBPTHREAD=1 -DHAVE_PTHREAD_GETNAME_NP=1 -DHAVE_PTHREAD_GETSPECIFIC=1 -DHAVE_PTHREAD_H=1 -DHAVE_PTHREAD_SETNAME_NP=1 -DHAVE_REGISTER_FRAME=1 -DHAVE_SETENV_R=1 -DHAVE_STRERROR_R=1 -DHAVE_SYSEXITS_H=1 -DHAVE_UNISTD_H=1 -D_GNU_SOURCE -DHAVE_LINK_H=1 -DHAVE_LSEEK64=1 -DHAVE_MALLINFO=1 -DHAVE_SBRK=1 -DHAVE_STRUCT_STAT_ST_MTIM_TV_NSEC=1 -DLLVM_NATIVE_ARCH=\"X86\" -DLLVM_NATIVE_ASMPARSER=LLVMInitializeX86AsmParser -DLLVM_NATIVE_ASMPRINTER=LLVMInitializeX86AsmPrinter -DLLVM_NATIVE_DISASSEMBLER=LLVMInitializeX86Disassembler -DLLVM_NATIVE_TARGET=LLVMInitializeX86Target -DLLVM_NATIVE_TARGETINFO=LLVMInitializeX86TargetInfo -DLLVM_NATIVE_TARGETMC=LLVMInitializeX86TargetMC -DLLVM_NATIVE_TARGETMCA=LLVMInitializeX86TargetMCA -DLLVM_HOST_TRIPLE=\"x86_64-unknown-linux-gnu\" -DLLVM_DEFAULT_TARGET_TRIPLE=\"x86_64-unknown-linux-gnu\" -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS --sysroot=/dev/shm/bazel-sandbox.f316d661a48e25ccef9f1eecf2ee79753df8a7d415e5ae7c930614d775411cf4/linux-sandbox/5851/execroot/moffett_software/external/sysroot_data/sysroot -no-canonical-prefixes -Wno-builtin-macro-redefined -D__DATE__=\"redacted\" -D__TIMESTAMP__=\"redacted\" -D__TIME__=\"redacted\" -fdebug-prefix-map=/dev/shm/bazel-sandbox.f316d661a48e25ccef9f1eecf2ee79753df8a7d415e5ae7c930614d775411cf4/linux-sandbox/5851/execroot/moffett_software/external/llvm_toolchain_llvm/=__bazel_toolchain_llvm_repo__/ -isystem /dev/shm/bazel-sandbox.f316d661a48e25ccef9f1eecf2ee79753df8a7d415e5ae7c930614d775411cf4/linux-sandbox/5851/execroot/moffett_software/external/llvm_toolchain_llvm/include/c++/v1 -isystem /dev/shm/bazel-sandbox.f316d661a48e25ccef9f1eecf2ee79753df8a7d415e5ae7c930614d775411cf4/linux-sandbox/5851/execroot/moffett_software/external/llvm_toolchain_llvm/lib/clang/13.0.0/include -isystem /dev/shm/bazel-sandbox.f316d661a48e25ccef9f1eecf2ee79753df8a7d415e5ae7c930614d775411cf4/linux-sandbox/5851/execroot/moffett_software/external/llvm_toolchain_llvm/13.0.0 -isystem /dev/shm/bazel-sandbox.f316d661a48e25ccef9f1eecf2ee79753df8a7d415e5ae7c930614d775411cf4/linux-sandbox/5851/execroot/moffett_software/external/sysroot_data/sysroot/usr/include    -v

Makefile Generator do not emit double quot around variable make shell try to parse “<” as pipe.

I found Makefile Generator just concat all “commands” field to an ostream, is it a designed feature? I think it would be better to emit quot at Makefile. In cmLocalUnixMakefileGenerator3::WriteMakeRule

Could you please create a minimal test case (basically just document how to reproduce what Bazel is doing here) which shows the problem and file an issue? Thanks.

bazel create an cross_tool.cmake file, which defines CFLAGS and CXXFLAGS like -DxxxHeader=<execinfo.h>
the angle brackets in CFLAGS went to an varibale in makefile, but cmake generate makefile using template that defines in CMAKE_C_COMPILE_OBJECT. and make script becomes something like
clang [some thing here] $CFLAGS [other parameters] , and angle brackets in CFlags becomes pipe operation in makefile. The root cause is that there is no quote around parameters in CMAKE_C_COMPILE_OBJECT and other build variables.
This behavior is same on both makefile generator and ninjia generator.

I will file an issue and report this, and attach an test case on gitlab issue

I don’t think this is a bug in CMake.

CFLAGS is a command-line string fragment, not an individual flag. If quoting is needed, it needs to be provided as part of the value.