file(STRINGS ...) command doesn't convert to binary when CWD is not a build directory (e.g. when run as script)
The file(STRINGS ...)
command tries automatically convert Intel Hex and Motorola S-record files to binary.
This has two issues:
-
It fails silently if anything goes wrong (such as a malformed file) in which case the file is read normally without converting it to binary. There is also no way to debug this behaviour directly (i.e. get some kind of error message on why it failed) apart from using strace to check if an
open()
-call to "FileCommandStringsBinaryFile" was issued. -
It writes the converted file to disk, which fails if the current working directory isn't a cmake build folder. This can happen for example when
file(STRING ...)
is executed as part of a cmake script. This is made worse by above issue, as no error is output and the conversion fails silently.
See also the TODO in https://gitlab.kitware.com/cmake/cmake/blob/72cfb3c3d2e8f6167cf08289691f7b0c61d0d331/Source/cmFileCommand.cxx#L544)
To reproduce this behaviour, execute the following in an empty directory:
# create files
$ echo ":10010000214601360121470136007EFE09D2190140\n:100110002146017E17C20001FF5F16002148011928" > test.ihx
$ echo 'file(STRINGS test.ihx contents)\nmessage("file contents: ${contents}")' > script.cmake
# execute script
$ cmake -P script.cmake
file contents: :10010000214601360121470136007EFE09D2190140;:100110002146017E17C20001FF5F16002148011928
# mimic directory structure of a build folder
$ mkdir CMakeFiles
# Now, file(STRINGS ...) behaves as expected:
$ cmake -P script.cmake
file contents: !F;6;!G;6;~; ;!F;~;_;!H
I expect the output of this script to be the same, no matter where I execute it.
This was tested on Fedora 24 with cmake 3.6.2 from the system repository and the latest cmake from git (v3.8.0-rc1-99-g8ff87662)
Some notes on the context where I discovered this: I'm working on a firmware for a microcontroller and I need some some safe-guard against overwriting critical sections in flash (such as a bootloader or a configuration sector). As my compiler doesn't seem to be able to prevent this I wrote a small cmake script (for maximum platform independence) that processes the final output (an Intel Hex file) and checks it against a protected address range. Manually parsing an Intel Hex file takes a while though and this is where I discovered that cmake can do this natively. I'd like this check to be run after every compilation and possibly also when compiling without cmake/make (some users are using CodeBlocks) so it would be nice if my script is location independent ;)
In conclusion: This bug doesn't really affect me as I have a working (albeit a bit slow) solution already. Also, can I even do math with binary data inside a cmake script (e.g. "address + offset < limit" checks)?