Shinyapps.io部署失败:编译terra包报错,求原因及部署方案
本地Windows 10上运行正常的Shiny应用,部署到shinyapps.io时因terra包编译失败终止。
错误信息
核心错误
Error building image: Error building terra (1.8-29). Build exited with non-zero status: 1
编译细节日志
RcppModule.cpp:665:184: error: wrong number of template arguments (8, should be 4) 662 | class_<SpatRaster>("SpatRaster") | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 663 | .constructor() | ~~~~~~~~~~~~~~ 664 | // .constructor<std::string, int>() | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 665 | .constructor<std::vector<std::string>, std::vector<int>, std::vector<std::string>, bool, std::vector<std::string>, std::vector<std::string>, std::vector<size_t>, bool>() | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~ make: *** [/opt/R/4.3.2/lib/R/etc/Makeconf:200: RcppModule.o] Error 1 ERROR: compilation failed for package ‘terra’
已尝试的解决方法
- 使用旧版terra(1.7-39):
remotes::install_version("terra", version = "1.7-39", repos = "http://cran.us.r-project.org") - 确保依赖包(sf、raster、sp)以二进制形式安装:
install.packages(c("sf", "raster", "sp"), type = "binary") - 检查shinyapps.io上的系统依赖(GDAL、PROJ、GEOS、UDUNITS2),日志显示libgdal-dev等已安装,但terra仍编译失败(sf安装正常)
- 禁用renv和锁文件以避免依赖冲突
- 部署时强制以二进制形式安装包
- 尝试带有特定依赖的替代terra版本
环境信息
- 本地系统:Windows 10
- R版本:4.3.2
- shinyapps.io服务器系统:Linux(基于Ubuntu)
- 尝试的terra版本:1.8-29(默认)、1.7-39(旧稳定版)
- sf版本:1.0-14
- 服务器GDAL版本:3.4.1
- PROJ版本:8.2.1
- GEOS版本:3.10.2
注:未直接调用terra包,但leaflet包依赖它
编译失败原因
这个错误是terra版本与服务器上的Rcpp版本不兼容导致的。从日志看,constructor模板参数数量不匹配,说明terra代码中使用的Rcpp API在服务器当前的Rcpp版本中不支持——你尝试的terra版本(无论新/旧)使用了Rcpp的新特性,但shinyapps.io服务器上的Rcpp版本偏旧,无法解析带有8个模板参数的constructor调用,该版本的Rcpp仅支持最多4个参数的构造器模板。
另外,Windows本地使用二进制包,不会触发编译过程,所以本地运行正常;而shinyapps.io的Linux环境需要源码编译terra,直接暴露了版本兼容问题。
解决办法
1. 指定兼容的Rcpp版本
在部署配置中强制安装与目标terra版本匹配的Rcpp版本。比如terra 1.7-39适配的Rcpp版本可通过CRAN归档确认,之后在部署脚本中添加:
remotes::install_version("Rcpp", version = "1.0.10") # 示例版本,需与terra版本严格匹配
2. 强制使用shinyapps.io的预编译二进制terra包
shinyapps.io提供部分热门包的预编译二进制包,可避免源码编译。在app.R开头添加:
options(repos = c(CRAN = "https://cran.rstudio.com/")) install.packages("terra", type = "binary")
或通过rsconnect配置指定:
rsconnect::configureApp(appName = "your-app-name", pkgType = "binary")
3. 锁定依赖包版本到兼容组合
创建renv.lock文件,手动调整其中的包版本为shinyapps.io支持的兼容组合,确保terra、Rcpp、sf等包的版本互相匹配。
4. 降级R版本匹配服务器环境
若本地R版本(4.3.2)比shinyapps.io服务器上的R版本新,可能引发依赖冲突。可在本地降级到与服务器相同的R版本,重新生成依赖后再部署。
5. 调整leaflet的依赖逻辑
如果不需要terra的全部功能,可尝试让leaflet使用raster包替代terra:
library(raster) library(leaflet) options(leaflet.useTerra = FALSE) # 需leaflet版本支持该选项
内容的提问来源于stack exchange,提问作者Stevestingray

