Javier Galan
Javier Galan

Reputation: 49

cmake: execute cmake commands at install time

I have the following lines that execute with out problem when I have them as they are in CMakeLists.txt main file.

set (git_cmd git)
set (git_arg rev-parse --verify HEAD )
message(STATUS \"git cmd: ${git_cmd}\")
execute_process(COMMAND ${git_cmd} ${git_arg}
  WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
  RESULT_VARIABLE git_result
  OUTPUT_VARIABLE git_ver)

message(STATUS \"git ver[${git_result}]: ${git_ver}\")

and I get the following output when I execute cmake

 -- "gitcmd:git"
 -- "gitver[0]:3268845bbbda4af12c951d75c25913d014da48ef

But what I really want is to execute that orders at install time, when I will execute "make install"

Thus, I enclose those LINES inside install: as install( CODE " LINES " )

install( CODE 
                "
set (git_cmd git)
set (git_arg rev-parse --verify HEAD )
message(STATUS \"git cmd: ${git_cmd}\")
execute_process(COMMAND ${git_cmd} ${git_arg}
  WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
  RESULT_VARIABLE git_result
  OUTPUT_VARIABLE git_ver)

message(STATUS \"git ver[${git_result}]: ${git_ver}\")
        "
)

However, the output when I execute "make install" seems to indicate thar git_cmd was not set

-- git cmd: 
CMake Error at cmake_install.cmake:196 (execute_process):
  execute_process given COMMAND argument with no value.

What I am doing wrong?

Thank you!

Upvotes: 3

Views: 3088

Answers (1)

Jan Hudec
Jan Hudec

Reputation: 76236

You are setting the variables inside the install script, but expanding them already in the configure script!

There are four options how you can fix it:

  1. Decide and hardcode the values at configure time:

    set (git_cmd git)
    set (git_arg "rev-parse --verify HEAD")
    install( CODE 
                    "
    message(STATUS \"git cmd: ${git_cmd}\")
    execute_process(COMMAND ${git_cmd} ${git_arg}
      WORKING_DIRECTORY \${PROJECT_SOURCE_DIR}
      RESULT_VARIABLE git_result
      OUTPUT_VARIABLE git_ver)
    
    message(STATUS \"git ver[\${git_result}]: \${git_ver}\")
            "
    )
    
  2. Escape the snippet correctly:

    install( CODE 
                    "
    set (git_cmd git)
    set (git_arg rev-parse --verify HEAD )
    message(STATUS \"git cmd: \${git_cmd}\")
    execute_process(COMMAND \${git_cmd} \${git_arg}
      WORKING_DIRECTORY \${PROJECT_SOURCE_DIR}
      RESULT_VARIABLE git_result
      OUTPUT_VARIABLE git_ver)
    
    message(STATUS \"git ver[\${git_result}]: \${git_ver}\")
            "
    )
    
  3. Set the variables in advance anyway, but expand them only at install time too. I am not sure whether they have to be in cache for that, but I suspect they do, so I add that:

    set (git_cmd git CACHE "" INTERNAL)
    set (git_arg rev-parse --verify HEAD CACHE "" INTERNAL)
    install( CODE 
                    "
    message(STATUS \"git cmd: \${git_cmd}\")
    execute_process(COMMAND \${git_cmd} \${git_arg}
      WORKING_DIRECTORY \${PROJECT_SOURCE_DIR}
      RESULT_VARIABLE git_result
      OUTPUT_VARIABLE git_ver)
    
    message(STATUS \"git ver[\${git_result}]: \${git_ver}\")
            "
    )
    
  4. Instead of trying to get the quoting right, use the install(SCRIPT form and put the commands in a separate file.

Note that:

  1. In both cases I escaped the $ in the last line, because those variables are always only defined inside the script and
  2. I also escaped the ${PROJECT_SOURCE_DIR}, but I am not completely certain the cache is loaded. If it is not, you'll have to escape it as \"${PROJECT_SOURCE_DIR}\" instead (and hope there will be no "s in the value).
  3. Also in the first case I put the git_arg value in quotes, because a list would expand separated with ;s and that would not read back correctly.

Due to the problems with special characters when reparsing I would NOT recommend the first option.

Upvotes: 3

Related Questions