Home > Software engineering >  CMake string replace removes semi-colon
CMake string replace removes semi-colon

Time:05-03

I have a template cpp file that will contain several placeholders. Excerpt:

// WARNING! this file is autogenerated, do not edit manually
QString appName()
{
  return "APP_NAME_VALUE";
}

Cmake will read this file in, fill in the placeholders and write it back out to the shadow build directory for compilation

set(APP_NAME "real application name")

file(READ ${CMAKE_SOURCE_DIR}/templates/app-info.cpp APP_INFO)
string(REPLACE "APP_NAME_VALUE" ${APP_NAME} APP_INFO ${APP_INFO})
# other tag replacements
file(WRITE "${CMAKE_BINARY_DIR}/src/app-info.cpp" ${APP_INFO})

But every time I run cmake, it seems to strip the semi-colon from the file contents.

// WARNING! this file is autogenerated, do not edit manually
QString appName()
{
  return "real application name"
}

Is this expected behaviour? What can I do to counter this?

CodePudding user response:

From https://discourse.cmake.org/t/what-is-the-best-way-to-search-and-replace-strings-in-a-file/1879

In my CMake script, I need to modify other source files by searching and replacing specified strings. In my case, the configure_file 2 command is not a solution because I have no control over the input file. Previously I used the file and string commands in the following way -

file(READ header.h FILE_CONTENTS)
string(REPLACE "old text" "new text" FILE_CONTENTS ${FILE_CONTENTS})
file(WRITE header.h ${FILE_CONTENTS})

However this technique appears to strip out semi-colons from the input file.

Answer: put quotes around ${FILE_CONTENTS} in both commands

Explanation:

It comes from a CMake’s list syntax, which is ;-separated, the fact that arguments passed to CMake commands are basically mashed together into a list, and that those commands take unbounded number of inputs. So you end up with one longer list.

Quoting prevents the semicolons in the expansion from being treated as list-element-separators.

Consider:

WRITE;header.h;x;y;z

vs

WRITE;header.h;"x;y;z"

So in your case, it will appear as such:

set(APP_NAME "real application name")

file(READ ${CMAKE_SOURCE_DIR}/templates/app-info.cpp APP_INFO)
string(REPLACE "APP_NAME_VALUE" ${APP_NAME} APP_INFO "${APP_INFO}")
# other tag replacements
file(WRITE "${CMAKE_BINARY_DIR}/src/app-info.cpp" "${APP_INFO}")
  • Related