一、背景
服务新增堆外缓存,考虑到空间利用率和序列化反序列化效率,我们采用了在时空方面都比较优秀的 protobuf !但在自动配置软件包(configure)和自动化构建工具(make)的过程中遇到一些问题,并在国内外并未找到特别符合的根因文档,特做此记录。
话不多讲,直接开始。
二、过程问题
首先说明,关于解压等相关问题并非难点,大家可以参考其它文档,例如:参考《# Protobuf 介绍与实战1:Mac环境下安装Protobuf(两种方式安装)》 其介绍了两种安装方式,我这里所描述问题在以上两种方式均可能遇到。
问题1:操作./configure时
./configure
操作后,自动配置运行中断,最后遇到以下类似的错误文案:
./configure: line 15798: sort: No such file or directory
./configure: line 15795: sed: No such file or directory
出现“No such file or directory
”错误表明系统缺少某些工具或这些工具的路径没有包含在 PATH
环境变量中。对于 sort
和 sed
工具,它们通常是 Unix 系统中的基本命令行工具,通常位于 /bin
或 /usr/bin
目录下。
首先确保 sort 和 sed 是否存在。可以通过以下命令检查:
which sort
which sed
如果这些命令返回空结果,表示工具可能没有安装或路径未正确配置。 但大概率问题不会在这里,而是在 环境变量。
首先需要确认 PATH
中是否包含 /bin
和 /usr/bin
,这是大多数系统工具所在路径。使用以下命令查看 PATH
:
echo $PATH
如果不包含这些目录,编辑你的 shell 配置文件(例如 ~/.bash_profile
, ~/.zshrc
)添加它们:
export PATH="/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:$PATH"
但是,即便你的环境变量中包含了 /bin
和 /usr/bin
,如果你的环境变量也像我的这样一坨,
/opt/homebrew/opt/coreutils/libexec/gnubin:/usr/local/bin:/opt/homebrew/opt/protobuf@3/bin:/opt/homebrew/bin:/opt/homebrew/sbin:./bin:/opt/homebrew/opt/coreutils/libexec/gnubin:/usr/local/bin:/opt/homebrew/opt/protobuf@3/bin:../opt/homebrew/opt/coreutils/libexec/gnubin:../opt/homebrew/bin:/System/Cryptexes/App/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin:/var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin:/usr/local/sbin:/Library/Java/JavaVirtualMachines/jdk1.8.0_291.jdk/Contents$ export JAVA_17_HOME=/Library/Java/JavaVirtualMachines/jdk-17.0.11.jdk/Contents$/bin:/Users/qinshaobo/MyApplication/apache-maven-3.8.1/bin:/Library/Java/JavaVirtualMachines/jdk1.8.0_291.jdk/Contents/Home/bin:/usr/local/Homebrew/bin
环境配置结构混乱,也有可能导致找不到sed、sort工具这个问题。 例如我的问题就诸如此类:
-
PATH
设置顺序和重复:- 多个地方修改
PATH
,特别是export PATH="$PATH:$M2_HOME/bin"
和PATH=".$PATH:$JAVA_HOME/bin"
,这种叠加可能导致问题。 - 有重复添加的路径(如
/opt/homebrew/opt/coreutils/libexec/gnubin
和/usr/local/bin
出现多次),可以优化和简化。
- 多个地方修改
-
误用
.
开头:PATH=".$PATH:$JAVA_HOME/bin"
中的.
可能是某种疏忽。.
代表当前目录,这在PATH
的配置中是极少直接建议的,通常是出于安全原因避免的。
-
路径的相对/绝对设置问题:
../
和类似./bin
这样指定路径的方法可能导致不需要的效果。应该尽量使用绝对路径,尤其在PATH
中。
-
其他不相关部分:
export JAVA_17_HOME=/Library/Java/JavaVirtualMachines/jdk-17.0.11.jdk/Contents$/bin:...
中的$
特别是在路径配置中是错误的,应当去掉。
经过我的环境变量整理后,./configure 终于不会报“No such file or directory
”了!
问题2:操作make时
运行后遇到如下错误:
./google/protobuf/stubs/common.h:38:10: fatal error: 'algorithm' file not found
38 | #include <algorithm>
| ^~~~~~~~~~~
1 error generated.
make[2]: *** [google/protobuf/compiler/main.o] Error 1
make[1]: *** [all-recursive] Error 1
make: *** [all] Error 2
这可能意味着在编译期间,一些标准库、头文件、开发工具你是缺失的。
解决方案特别简单通过下载在AppStore下载Xcode
即可解决,其原理就是通过Xcode补齐了构建阶段我们所缺失的一些必备前置要素,使得编译器能够找到 algorithm
等标准 C++ 头文件,并顺利完成 make
过程中的构建任务。
问题3:执行protoc时
如果protobuf已经make install完毕,则可以通过protoc --version
来验证
xxx@xxx src % ./protoc --version
libprotoc 3.4.0
如果将protoc配置在环境变量,你可以在任意文件下直protoc --version
xxx@xxx src % protoc --version
libprotoc 3.4.0
此时,如果你执行文件转换操作
--java_out=/Users/xxx/Desktop/ /Users/xxx/Desktop/ABC.proto
会发现报这个错:
/usr/local/protobuf/bin/protoc: /usr/local/protobuf/bin/protoc: cannot execute binary file
我这里遇到的问题是文件权限问题,此时需要通过chmod +x/usr/local/protobuf/bin/protoc
命令给予文件执行权,并且通过ls -l /usr/local/protobuf/bin/protoc
去查看、验证文件的权限。
此时再执行
--java_out=/Users/xxx/Desktop/ /Users/xxx/Desktop/ABC.proto
又报了这个错误:
File does not reside within any path specified using --proto_path (or -I). You must specify a --proto_path which encompasses this file. Note that the proto_path must be an exact prefix of the .proto file names -- protoc is too dumb to figure out when two paths (e.g. absolute and relative) are equivalent (it's harder than you think).
当你使用 protoc
来编译 .proto
文件时,如果看到这个错误信息,说明缺少 --proto_path
(或 -I
)选项指定 .proto
文件的搜索路径。protoc
需要知道从什么路径开始查找 .proto
文件,因为 .proto
文件可能包含其他 .proto
文件。
解决方案:只需要指定 --proto_path
参数即可,
protoc --proto_path=/Users/xxx/Desktop/ --java_out=/Users/xxx/Desktop/ /Users/xx/Desktop/xxx.proto
三、总结
到这里,我在protobuf的安装到完成文件转换的工作就可以顺利完成了,一共踩了3个坑,分别在configure
、make
和文件转换
阶段,每个问题都花费了不少的时间才研究明白,并最终解决,希望这个文档能对也在做相同事情的你有所帮助。