如何使用CMake作为自定义目标下载任意文件?

6

CMake通过其ExternalProject,使得在构建期间下载大型存档文件变得容易,从而保持存储库的清洁。举个例子,我可以像这样下载并解压缩Eigen:

include(ExternalProject)

ExternalProject_Add(
    eigen
    URL http://bitbucket.org/eigen/eigen/get/3.2.8.tar.bz2
    URL_HASH SHA512=53c27ba530c985dfef52188e03273eeef33abbc67e3f150cacd3371c8b9ddbd399228730595821c4c56c061d109cf509266c1dab2b8a7c730902cbd6fb18c100
    INSTALL_COMMAND ""
)

我希望能够对任意文件执行相同的操作,例如为演示目的下载附加数据。 CMake提供了file(DOWNLOAD...)来实现这一目的,它可以很好地工作,例如:

file(DOWNLOAD
    http://graphics.stanford.edu/pub/3Dscanrep/bunny.tar.gz
    ${CMAKE_BINARY_DIR}/demo/bunny.tar.gz
    SHA512=59e7b43db838dbe6f02fda5e844d18e190d32d2ca1a83dc9f6b1aaed43e0340fc1e8ecabed6fffdac9f85bd34e7e93b5d8a17283d59ea3c14977a0372785d2bd
    SHOW_PROGRESS
)
add_custom_target(demo tar -xzf ${CMAKE_BINARY_DIR}/demo/bunny.tar.gz -C ${CMAKE_BINARY_DIR}/demo)

这个命令下载一个存档文件,进行验证,然后通过make demo提取。但是,该存档每次运行CMake时都会被下载,不仅仅是一次,并且不依赖于目标demo的调用。
这个问题可以通过CMake实现吗?我认为ExternalData无法解决此问题,因为我真的只想从互联网上下载任意文件。
1个回答

4

然而,归档文件每次运行CMake时都会被下载,而不仅仅是一次,并且它不依赖于目标演示被调用。

难怪。你没有将 eigen 或其他目标作为 demo 的依赖项添加。

所以,像以下这样的内容应该可以工作:

ExternalProject_Add(
    bunny
    PREFIX "demo"
    URL http://graphics.stanford.edu/pub/3Dscanrep/bunny.tar.gz
    URL_HASH SHA512=59e7b43db838dbe6f02fda5e844d18e190d32d2ca1a83dc9f6b1aaed43e0340fc1e8ecabed6fffdac9f85bd34e7e93b5d8a17283d59ea3c14977a0372785d2bd
    CONFIGURE_COMMAND ""
    BUILD_COMMAND ""
    INSTALL_COMMAND ""
)

注意: ExternalProject_Add 产生的目标默认会提取归档文件。您正在下载名为 bunny.tar.gz 的包含另一个捆绑在内的 src/bunny.tar.gz 的归档文件。

编辑: 如果我们谈论较新的CMake(>=3.11),您也应该查看官方文档中的FetchContent(),这可能也会减轻一些负担。


太好了,ExternalProject 运行良好。它实际上使自定义目标变得多余,因为档案会自动解压缩。但是可能需要稍微移动一下生成的文件。 - Shedeki
与说明相反,归档文件bunny.tar.gz并不包含另一个归档文件 src/bunny.tar.gz。 CMake似乎只是在那个位置保留了一份副本。 - Shedeki
@Shedeki,哦,那很抱歉。某种花哨的缓存可能会搞砸事情......顺便说一句,默认情况下它还会尝试构建提供的外部项目。除非明确说明不要这样做。 - Kamiccolo
为什么不直接使用 file(DOWNLOAD url) - Sandburg
ExternalProject可以省去额外的custom_target()和手动提取的需要。 - Kamiccolo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接