add_executable(main main.cpp)
target_link_options(main PUBLIC --preload-file=temp$.txt)
and an arbitrary file named temp$.txt, it doesn’t find the txt file because the dollar sign gets changed into something like \$$ in the actual compiler invocation.
(Don’t mind the actual link option, it’s an Emscripten specific one, but the problem I believe is not specific to Emscripten development.)
What should I do to make it find my file which has a dollar sign in its name? This doesn’t help:
target_link_options(main PUBLIC [=[--preload-file=temp$.txt]=])
Do you really need to have $ in the name? Is there no other character that can work? CMake doesn’t guarantee that arbitrary text can make it through untouched (e.g., a filename with ; in it is going to have a horrible time). I think $ may just be in the same bucket as I believe it is important to all non-Xcode generators in some way.
I observe that using CMAKE_EXE_LINKER_FLAGS is not affected by the same escaping behavior. Consider:
cmake_minimum_required(VERSION 3.21)
project(test)
set(CMAKE_EXE_LINKER_FLAGS "--preload-file=temp$.txt")
add_executable(main main.cpp) # main.cpp is empty for demo
Then at the terminal, we can see:
$ cmake -G Ninja -S . -B build -DCMAKE_BUILD_TYPE=Release
-- The C compiler identification is GNU 9.3.0
-- The CXX compiler identification is GNU 9.3.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /path/to/build
$ cmake --build build/ -- -nv
[1/2] /usr/bin/c++ -O3 -DNDEBUG -MD -MT CMakeFiles/main.dir/main.cpp.o -MF CMakeFiles/main.dir/main.cpp.o.d -o CMakeFiles/main.dir/main.cpp.o -c /home/alex/test2/main.cpp
[2/2] : && /usr/bin/c++ -O3 -DNDEBUG --preload-file=temp$.txt CMakeFiles/main.dir/main.cpp.o -o main && :
This also works with Unix Makefiles, though it is obscured in the command output.
Escaping with \$$ looks like a bug, though. Depending on the backend, I would expect to see either\$or$$, not the two laid on top of each other. Also, shouldn’t CMAKE_*_LINKER_FLAGS* escape the same way as target_link_options, add_link_options, etc.?
Hmm. Good point. Unfortunately, fixing any of this is going to be a policy. The CMAKE_<LANG>_LINKER_FLAGS are “old” and probably don’t have the same codepaths as the usage requirement-using target_link_* bits.
A \$$ looks perfectly fine inside a Makefile or Ninja using a shell. The \ quotes the dollar sign for the shell command line and the $$ is a single dollar sign in Make/Ninja syntax.
But the Makefile generated by CMake does not call the linker directly. Instead it generates a link.txt file which is given to cmake -E cmake_link_script. In that case doing a $$ quoting is a bug, the working string is \$. Most probably introduced with the cmake_link_script feature.
And a Ninja file generated by CMake file contains \$$$$ which is also a bug. The working string is \$$.