Using install(script ... correctly

I’m trying to use “install(script …” correctly, but it seems to fail silently and I can’t work out why (precisely because its silent - there are no diagnostic or error messages being sent out).

This is the script I want to run (stored as scriptfile.cmake):

file(GLOB sofiles ${CMAKE_INSTALL_FULL_BINDIR}/../lib/python2.7/sil/*.so)
foreach (sofile ${sofiles})
    message("Removing RPATH from ${sofile}")
    execute_process(COMMAND chrpath -d ${sofile}
                    COMMAND_ECHO STDOUT)
endforeach() 

And I’d like to run it from my main script like this:

install(SCRIPT ${CMAKE_CURRENT_LIST_DIR}/scriptfile.cmake)

I know that the script is being found, as I get an error message if I don’t put it there, or if I rename it: but I’m not seeing the messages and the files don’t get changed. What am I doing wrong?

Have you verified that at install time (i.e. when the script runs), CMAKE_INSTALL_FULL_BINDIR contains what you expect? Have you tried adding a message (or write to a file) to the script to check both that and sofiles?

OK, I am embarrassed now.

I did put a line with:

install(CODE "execute_process(COMMAND echo ${CMAKE_INSTALL_FULL_BINDIR})")

immediately before the install(SCRIPT line, so that confirmed that I had the correct CMAKE_INSTALL_FULL_BINDIR. However, the message("..") statement only gets run if the ‘sofiles’ list is non-empty, and it turns out that in my case it was empty.

No idea why; the path is correct, and I’m fairly sure I have the “file(GLOB…” syntax correct, though this is the first time I’ve tried using it. That’s the next thing to investigate…

Be careful: in the command install(CODE "execute_process(COMMAND echo ${CMAKE_INSTALL_FULL_BINDIR})"), CMAKE_INSTALL_FULL_BINDIR will be expanded at CMake configure time, that is, when the installation script is generated. The reference inside scriptfile.cmake will only be expanded at install time (running make install), when the installation script is executed. Put the echo into the script instead of into install(CODE), to verify what the variable value is at install time.

Thank you. Once again your intuition was spot-on, and indeed CMAKE_INSTALL_FULL_BINDIR wasn’t defined at install time. I fixed that by making my scriptfile.cmake into scriptfile.cmake.in, then using configure_file to store the value of CMAKE_INSTALL_FULL_BINDIR at configuration time and then run it at install time.

I’m still not out of the woods, though, since I cannot get file(GLOB to populate its list properly. In my current configuration I have

execute_process(COMMAND ls ${CMAKE_INSTALL_FULL_BINDIR}/../lib/python2.7/sil)
file(GLOB sofiles "${CMAKE_INSTALL_FULL_BINDIR}/../lib/python2.7/sil/*.so")
message("sofiles contains ${sofiles}")
foreach (sofile ${sofiles})
    message("Converting RPATH in ${sofile} to RUNPATH")
    execute_process(COMMAND chrpath --convert ${sofile}
                    COMMAND_ECHO STDOUT)
endforeach()

…and in my output I get a listing of all the files in the target directory at install time, including all the .so files I’d expect, but ‘sofiles’ remians stubbornly empty. I’ve tried it with and without the quotes.

OK, I’ve solved this.

Because I had used configure_file to store the value of CMAKE_INSTALL_FULL_BINDIR in my generated file, but ‘sofiles’ had no value at this time, ‘${sofiles}’ was being set to an empty string.

The solution was simply to set the contents of scriptfile.cmake.in to:

execute_process(COMMAND ls @CMAKE_INSTALL_FULL_BINDIR@/../lib/python2.7/sil)
file(GLOB sofiles @CMAKE_INSTALL_FULL_BINDIR@/../lib/python2.7/sil/*.so)
message("sofiles contains ${sofiles}")
foreach (sofile ${sofiles})
    message("Converting RPATH in ${sofile} to RUNPATH")
    execute_process(COMMAND chrpath --convert ${sofile}
                    COMMAND_ECHO STDOUT)
endforeach()

…and invoke configure_file using the @ONLY option.