Reputation: 7009
Take this minimized example
Critical place:
bison_target(parser
numgrammar.y
${CMAKE_CURRENT_BINARY_DIR}/parser.cc
COMPILE_FLAGS "--defines=${CMAKE_CURRENT_BINARY_DIR}/numgrammar.tab.hh")
Then please create some folder with space inside name like:
> mkdir "test folder" && cd "test folder"
> cmake ${ADVGRAMMAR}
> make VERBOSE=1
You will see something like:
> /usr/bin/bison --defines=/mnt/c/research/test folder/advgrammar/build/numgrammar.tab.hh -d -o ....
You see the problem: space in "test folder" not escaped.
Ok, now lets try to escape:
bison_target(parser
numgrammar.y
${CMAKE_CURRENT_BINARY_DIR}/parser.cc
COMPILE_FLAGS "--defines=\"${CMAKE_CURRENT_BINARY_DIR}/numgrammar.tab.hh\"")
You will see:
/usr/bin/bison --defines=\"/mnt/c/research/test folder/advgrammar/build/numgrammar.tab.hh\" -d -o ....
Now cmake added wrong escape mark for quotes.
Of course no problem if cmake in some neutral-named folder without spaces, but I want any folder.
I tried to google really hard. I tried string with CONFIGURE, I tried generator expressions, I tried this and that and everything and looks like I can't get behavior I want.
I want simply this:
/usr/bin/bison --defines="/mnt/c/research/test folder/advgrammar/build/numgrammar.tab.hh" -d -o ....
Of course I can do it with my own custom target. But I want this with bison_target.
Really need cmake experts help. Any ideas appreciated.
Upvotes: 1
Views: 279
Reputation: 46
Just in case: there is an option DEFINES_FILE
in the bison_target
macro. As for me it looks like more portable. You can use it instead of COMPILE_FLAGS
.
bison_target(parser
numgrammar.y
${CMAKE_CURRENT_BINARY_DIR}/parser.cc
## COMPILE_FLAGS "--defines=${CMAKE_CURRENT_BINARY_DIR}/numgrammar.tab.hh")
DEFINES_FILE ${CMAKE_CURRENT_BINARY_DIR}/numgrammar.tab.hh
)
It works fine at least on Catalina.
$ cmake -G Ninja -S . -B "build with spaces"
$ cmake --build "build with spaces" -- -nv
[1/6] cd /Users/tonnyred/td && /usr/local/opt/bison/bin/bison "--defines=/Users/tonnyred/td/build with spaces/numgrammar.tab.hh" -o "/Users/tonnyred/td/build with spaces/parser.cc" numgrammar.y
[2/6] cd /Users/tonnyred/td && /usr/local/opt/flex/bin/flex "-o/Users/tonnyred/td/build with spaces/lexer.cc" numgrammar.l
...
Upvotes: 0
Reputation: 20016
This is because the bison_target
macro calls1 separate_arguments
on the value of the COMPILE_FLAGS
without using the new form that respects native shell rules (it just blindly replaces spaces with semicolons).
Unfortunately, the macro doesn't give you a chance to inject flags in a more modern way, either, so the best I could come up with was to use the variable_watch
command to hack at the internals of bison_target
, at least until this bug is fixed.
Here's a full example:
cmake_minimum_required(VERSION 3.22)
project(test)
find_package(FLEX REQUIRED)
find_package(BISON REQUIRED)
# Hack around FindBISON's incorrect use of separate_arguments
if (CMAKE_VERSION VERSION_LESS 3.24)
function(patch_flags variable access value ip stack)
set(invalid "${CMAKE_CURRENT_BINARY_DIR}")
separate_arguments(invalid)
string(REPLACE "${invalid}" "${CMAKE_CURRENT_BINARY_DIR}" "${variable}" "${value}")
set("${variable}" "${${variable}}" PARENT_SCOPE)
endfunction()
variable_watch(BISON_TARGET_cmdopt patch_flags)
endif ()
flex_target(scanner
numgrammar.l
"${CMAKE_CURRENT_BINARY_DIR}/lexer.cc"
)
bison_target(
parser
numgrammar.y
"${CMAKE_CURRENT_BINARY_DIR}/parser.cc"
COMPILE_FLAGS "--defines=${CMAKE_CURRENT_BINARY_DIR}/numgrammar.tab.hh"
)
add_flex_bison_dependency(scanner parser)
add_executable(
numgrammar
driver.cc
${BISON_parser_OUTPUTS}
${FLEX_scanner_OUTPUTS}
)
And here's a shell interaction:
$ cmake -G Ninja -S . -B "build with space"
$ cmake --build "build with space" -- -nv # n = dry-run, v = verbose
[1/6] cd "/home/alex/test/build with space" && /usr/bin/bison "--defines=/home/alex/test/build with space/numgrammar.tab.hh" -d -o "/home/alex/test/build with space/parser.cc" /home/alex/test/numgrammar.y
[2/6] cd "/home/alex/test/build with space" && /usr/bin/flex "-o/home/alex/test/build with space/lexer.cc" /home/alex/test/numgrammar.l
[3/6] /usr/bin/c++ -MD -MT CMakeFiles/numgrammar.dir/driver.cc.o -MF CMakeFiles/numgrammar.dir/driver.cc.o.d -o CMakeFiles/numgrammar.dir/driver.cc.o -c /home/alex/test/driver.cc
[4/6] /usr/bin/c++ -MD -MT CMakeFiles/numgrammar.dir/parser.cc.o -MF CMakeFiles/numgrammar.dir/parser.cc.o.d -o CMakeFiles/numgrammar.dir/parser.cc.o -c '/home/alex/test/build with space/parser.cc'
[5/6] /usr/bin/c++ -MD -MT CMakeFiles/numgrammar.dir/lexer.cc.o -MF CMakeFiles/numgrammar.dir/lexer.cc.o.d -o CMakeFiles/numgrammar.dir/lexer.cc.o -c '/home/alex/test/build with space/lexer.cc'
[6/6] : && /usr/bin/c++ CMakeFiles/numgrammar.dir/driver.cc.o CMakeFiles/numgrammar.dir/parser.cc.o CMakeFiles/numgrammar.dir/lexer.cc.o -o numgrammar && :
As you can see the bison rule correctly quotes the spaces.
... /usr/bin/bison "--defines=/home/alex/test/build with space/numgrammar.tab.hh" ...
1. See https://github.com/Kitware/CMake/blob/6b6bdcbb64e1aa2ddac4f09a0807553f5684165a/Modules/FindBISON.cmake#L131 and https://github.com/Kitware/CMake/blob/6b6bdcbb64e1aa2ddac4f09a0807553f5684165a/Modules/FindBISON.cmake#L249
Upvotes: 2