As part of my larger project, I need to retrieve a file from an external SVN repo to be included in the final RPM build step. This repo is kind of slow… about 50% of the time the download times out, but it’s annoying when you are in a heavy edit/compile cycle to have to wait on a useless download.
For now, I have a separate CMakeLists.txt file for this download. I wasn’t sure how to make it a target, so I ended up with this:
file(DOWNLOAD
"http://${download_svnhost}/${download_source}"
${download_target}
${download_credentials}
${download_hash}
INACTIVITY_TIMEOUT 3
TIMEOUT 5
STATUS download_status
)
message(INFO " download status: ${download_status}")
### Add the documentation file(s) to the distribution
install(FILES
${download_target}
COMPONENT doc
DESTINATION doc
)
What I’d like to do is only download this file as a final step prior to building the packages. Can I get there from here?
You could download the file as part of an install(SCRIPT) or install(CODE) snippet. I would then skip the download if the file already exists and has a valid checksum.
Thanks. It took a bit of finagling; the documentation for install(SCRIPT|CODE) is a bit sparse, but I finally got this to more-or-less work
### Add the documentation file(s) to the distribution
install(CODE "message(INFO \" downloading user's manual (${download_target}) from ${download_url}\")"
COMPONENT doc
)
install(CODE
"file(DOWNLOAD
${download_url}
${download_target}
${download_credentials}
${download_hash}
STATUS download_status
)"
COMPONENT doc
)
install(CODE "message(INFO \" download complete; status=${download_status}\")"
COMPONENT doc
)
install(FILES
${download_target}
COMPONENT doc
DESTINATION doc
)
What wasn’t clear to me was that I still needed to have install(FILES) after the download (CODE apparently doesn’t honor the DESTINATION tag). It also wasn’t clear that I couldn’t have multiple commands in the CODE block, but I did find that multiple install(CODE) blocks worked.
What I stumbled upon digging through the generated cmake_install.cmake file is that everyinstall command should have a COMPONENT tag (if you use components), otherwise it is attached to the “Unspecified” component. This has the undesirable side-effect of creating a “myprog-Unspecified-vers.arch.rpm” when building RPMs.
The piece I don’t have right is detecting an error in the download. I purposely put in a bogus host and the build completes without incident. Instead of raising an error, is creates a 0-length file and puts it in the RPM. Note that download_status is local to the install(CODE) command that downloads the file, and so is not viisble in the final message.
can you suggest a snippet? As noted, I was unsuccessful in having multiple commands, and the status variable for the download is not visible outside that command.
I had trouble with multiple commands inside a CODE so I tried SCRIPT. The problem I ran into was that SCRIPT didn’t inherit variables from the calling context. Or it may have been an order of parsing issue … see below.
After quite a bit of experimentation, I did figure out how to have multiple commands inside a CODE argument. Apparently CMake relies on newlines as statement delimiters, but newlines within strings are allowed. And I also learned the importance of understanding how strings are parsed. One of the key things I learned was that any "${variable}" strings have the variable substituted at generation time, not at run time. In order to reference variables set inside my script, I had to escape the $ to defer substitution until run time.