Bazel规则执行OpenSSL Configure脚本时fallback参数报错问题
问题详情
在通过Bazel的rules_perl执行OpenSSL的Configure脚本时,触发如下错误:
"Parameter to use fallback must be a directory, not a file"
错误源自Configure脚本中的代码行:use OpenSSL::fallback "$FindBin::Bin/external/perl/MODULES.txt";
直接在本地终端执行./Configure完全正常,但通过Bazel执行时,无论用以下哪种方式都会触发相同错误:
- 基于
perl_binary和sh_binary配置的Bazel规则 - 执行包含
perl Configure && make的shell脚本
尝试修改该行代码无效,仅完全删除才能解决问题,推测是Bazel沙箱机制导致路径解析异常。另外尝试过rules_foreign_cc的OpenSSL示例,但系统提示找不到rm命令,无法正常使用。
原因分析
Bazel沙箱会重映射文件路径,导致$FindBin::Bin在沙箱环境中的指向与本地直接执行时不一致。OpenSSL的OpenSSL::fallback模块要求传入目录路径,但在沙箱中,$FindBin::Bin/external/perl/MODULES.txt被识别为文件而非目录——本质是沙箱中该路径的结构未按预期挂载,导致模块接收了错误的参数类型。
解决方案
1. 确保依赖目录正确挂载到沙箱
在BUILD文件中,给执行Configure的规则添加data依赖,包含external/perl整个目录,而非仅MODULES.txt文件:
# 示例:sh_binary规则配置 sh_binary( name = "build_openssl", srcs = ["build.sh"], data = [ ":Configure", "@perl//:perl", "@external_perl//:all_files", # 替换为你的perl目录依赖标签 ], )
这样Bazel会将整个external/perl目录挂载到沙箱中,确保$FindBin::Bin/external/perl是合法目录。
2. 修正Configure脚本的路径参数
OpenSSL::fallback实际需要的是包含Perl模块的目录,而非MODULES.txt文件,直接修改代码行:
# 原代码 use OpenSSL::fallback "$FindBin::Bin/external/perl/MODULES.txt"; # 修改为 use OpenSSL::fallback "$FindBin::Bin/external/perl";
如果Configure依赖MODULES.txt加载模块列表,需确认该目录下已包含所需的Perl模块文件,或调整fallback模块的加载逻辑。
3. 临时关闭沙箱(仅测试用)
在Bazel规则中添加sandbox = "never"属性,关闭沙箱机制,让脚本使用本地路径执行(不推荐生产环境使用):
perl_binary( name = "run_configure", srcs = ["Configure"], data = ["@perl//:perl"], sandbox = "never", )
4. 修复rules_foreign_cc的工具链问题
若想使用rules_foreign_cc,需确保Bazel工具链包含基础系统命令:
- 在终端执行
export BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN=1,让Bazel使用本地系统工具链 - 检查WORKSPACE文件,确保正确引入了系统工具链依赖
内容的提问来源于stack exchange,提问作者Andrew Katson

