Search code examples
c++powershellcmdcmake

CMake: What formatting does execute_process() do?


I need to call the findstr Windows command (grep on Linux) from my CMakeList.txt.
If I do this, it is working :

execute_process(
    COMMAND findstr "NABO_VERSION " nabo\\nabo.h
    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
    RESULT_VARIABLE FINDSTR_RESULT
    ERROR_VARIABLE FINDSTR_ERROR
    OUTPUT_VARIABLE FINDSTR_OUT
    OUTPUT_STRIP_TRAILING_WHITESPACE
)

I get the output:

FINDSTR_ERROR =
FINDSTR_OUT =   
  #define NABO_VERSION "1.0.7"
  #define NABO_VERSION_INT 10007
FINDSTR_RESULT = 0

However, the space at the end of "NABO_VERSION " is not taken into account. I have to add /c: before my string.

So I get this following code :

execute_process(
    COMMAND findstr /c:"NABO_VERSION " nabo\\nabo.h
    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
    RESULT_VARIABLE FINDSTR_RESULT
    ERROR_VARIABLE FINDSTR_ERROR
    OUTPUT_VARIABLE FINDSTR_OUT
    OUTPUT_STRIP_TRAILING_WHITESPACE
)

But now it doesn't work and I get this:

FINDSTR_ERROR =
FINDSTR_OUT =
FINDSTR_RESULT = 1

The command works well in PowerShell or CMD, but not from CMake. I think that CMake modify the command, but in what way ?


Solution

  • So I created a test file called nabo\nabo.h with the following contents:

    #define NABO_VERSION "1.0.7"
    #define NABO_VERSION_INT 10007
    

    Then at cmd, I wrote:

    > findstr "NABO_VERSION " nabo\nabo.h
    #define NABO_VERSION "1.0.7"
    #define NABO_VERSION_INT 10007
    

    and got both lines back. Adding /c: is necessary:

    > findstr /c:"NABO_VERSION " nabo\nabo.h
    #define NABO_VERSION "1.0.7"
    

    Now to write this in CMake:

    # test.cmake
    
    cmake_minimum_required(VERSION 3.21)
    # Script mode, no project() call
    
    execute_process(
        COMMAND findstr "/c:NABO_VERSION " [[nabo\nabo.h]]
        WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
        RESULT_VARIABLE FINDSTR_RESULT
        ERROR_VARIABLE FINDSTR_ERROR
        OUTPUT_VARIABLE FINDSTR_OUT
        OUTPUT_STRIP_TRAILING_WHITESPACE
    )
    
    message(STATUS "FINDSTR_ERROR  = ${FINDSTR_ERROR}")
    message(STATUS "FINDSTR_OUT    = ${FINDSTR_OUT}")
    message(STATUS "FINDSTR_RESULT = ${FINDSTR_RESULT}")
    

    Running this script returns the expected result:

    >cmake -P test.cmake
    -- FINDSTR_ERROR  =
    -- FINDSTR_OUT    = #define NABO_VERSION "1.0.7"
    -- FINDSTR_RESULT = 0
    

    This works because, as the findstr /? output says:

    Use spaces to separate multiple search strings unless the argument is prefixed with /C.

    So then you just need the quotes in CMake to ensure the space is included in the whole argument.