pyenv install失败现象和初步分析
运行命令pyenv install 3.6.15
后失败,截图如下:
可以看到,关键信息为:
python-build: use zlib from homebrew
BUILD FAILED (OS X 14.4 using python-build 20180424)
Inspect or clean up the working tree at /var/folders/4t/q8vsd83j12v34_1z9lv5_z040000gn/T/python-build.20240327223108.17780
Results logged to /var/folders/4t/q8vsd83j12v34_1z9lv5_z040000gn/T/python-build.20240327223108.17780.log
configure: error: C compiler cannot create executables
See `config.log' for more details
大概意思就是,执行到use zlib from homebrew
这一步之后就BUILD FAILED
构建失败了
然后告诉我们,结果记录在了/var/folders/4t/q8vsd83j12v34_1z9lv5_z040000gn/T/python-build.20240327223108.17780.log
里面
跟我们总结原因,是C compiler cannot create executables
C编译器创建可执行文件失败
但这个原因太宏观了,我们需要去config.log
里面看更多细节。
尝试方案1:xcode和brew相关
1.1:xcode命令行工具没装
先丢给gpt,给出的回答是可能macOS的命令行工具xcode-select没装。
于是运行了命令
xcode-select --install
命运的转折点之1:如果没装的人这一步之后就可以重新尝试pyenv install了。
1.2:brew没有更新
但是大部分都是装过的,因为这个工具很底层,譬如我就是装过了的。
那么也有可能是这个工具装了,但是有点问题,我们需要重装。但是重装的风险有点大,因为需要把整个CommandLineTools目录删掉,那么我们先看一下是不是brew没有更新的原因,执行命令
brew update
命运的转折点之2:这一步真的有更新,或者有其他问题的同学,解决完更新或其他问题就可以再次尝试pyenv install。
brew install zstd / brew link zstd失败
譬如我这里还真的发现了有一个包zstd需要更新,而且zstd的链接有点问题,brew提示我运行brew link zstd
然后发现zstd安装失败,因为/usr/local/include文件夹无法写入。
这里我是知道根本原因的,其实不是文件夹无法写入,是根本就没有这个文件夹了,笑(
因为以上的步骤实际上是我pyenv崩掉的第二天了,而我第一天在尝试解决这个问题时看网上有个人把这个文件夹删掉之后就好了,我就也删掉了,真的很不可取🙅
解决方案当然是重新创建这个文件夹并且给可写的权限啦,然后重新brew link zstd。
sudo mkdir -p /usr/local/include
sudo chown -R $(whoami) /usr/local/include
brew link zstd
随后我再次pyenv install,仍!然!失!败!哈!哈!
超!
1.3 brew安装必要的包:openssl readline sqlite3 xz zlib tcl-tk
brew install openssl readline sqlite3 xz zlib tcl-tk
命运的转折点之3:这一步真的有没装的包的同学装完可以再次尝试pyenv install。
然而,大部分人应该都有装,一堆的 is already installed 我就不贴图了。
1.4 重装xcode
到这一步还没有解决,而且不想去细看报错日志的话,可以先冲一波xcode的重装了。1.2不是提到了吗,重装有风险。但冲就完事了,后面改环境变量啥的更有风险!
执行命令
sudo rm -rf /Library/Developer/CommandLineTools
xcode-select --install
命运的转折点之4:可以再次尝试pyenv install了。
尝试方案2:细看报错日志(设置环境变量SDKROOT、CFLAGS、 LDFLAGS)
2.1:研究日志
是的没错,尝试方案1的四步对我来说都没用,超!
此时我们真的要去看报错日志了。这里我把报错的pyenv install的信息再次贴上来。
于是输入命令
grep -C 3 'error' /var/folders/4t/q8vsd83j12v34_1z9lv5_z040000gn/T/python-build.20240327231149.7420/Python-3.6.15/config.log
这个命令的意思是在config.log下面查找包含字符串error的行,并且输出每个匹配行的前后三行
得到的信息如下
喂给gpt解释一下嘿嘿嘿:
-
clang: error: argument to ‘-V’ is missing (expected 1 value)
clang: error: no input files
这个错误是因为在运行clang -V命令时,缺少了参数,导致命令执行失败。这个错误可以忽略,不会影响后面的编译过程。 -
clang: error: unknown argument ‘-qversion’; did you mean ‘–version’?
clang: error: no input files
这个错误是因为在运行clang -qversion命令时,使用了未知的参数"-qversion",正确的参数应该是"–version"。这个错误可以忽略,不会影响后面的编译过程。 -
ld: library ‘System’ not found
clang: error: linker command failed with exit code 1 (use -v to see invocation)
这个错误是因为在编译过程中缺少了名为"System"的库文件。解决这个问题的方法是安装Xcode命令行工具,可以使用以下命令来安装:xcode-select --install
-
configure:4005: error: in `/var/folders/4t/q8vsd83j12v34_1z9lv5_z040000gn/T/python-build.20240327231149.7420/Python-3.6.15’:
configure:4007: error: C compiler cannot create executables
这个错误是因为C编译器无法创建可执行文件。这个问题可能是由于缺少必要的开发工具或库文件导致的。解决这个问题的方法是安装必要的开发工具和库文件,例如安装Xcode命令行工具、安装zlib库等。
2.2:设置环境变量找到System库文件
好的,第一点和第二点可以忽略,那么从第三点开始看。说找不到‘System’的库文件,也就是当前macOS系统的SDK。(吗的,这么底层吗?怪不得😭)
这里gpt给出的解决方案是再次安装xcode(乐),那肯定不行啊,我们先运行如下命令:
xcrun --show-sdk-path
这个命令得到的就是SDK的路径,一般人都会有
命运的转折点之5:没有的话出门左转先找下其他博客吧,这个问题很重要,需要先解决,但是太底层了,我没接触过(
然后就需要我们去指定环境变量让他找到System的库文件了。运行以下命令
export SDKROOT=`xcrun --show-sdk-path`
export CFLAGS="-isysroot $SDKROOT $CFLAGS"
export LDFLAGS="-isysroot $SDKROOT $LDFLAGS"
以上环境变量都用于在编译和链接C/C++程序时传递参数。SDKROOT环是编译和链接程序时使用的SDK路径。CFLAGS是编译器的参数,LDFLAGS是链接器的参数。
命运的转折点之6:再冲一波pyenv install!
见证奇迹的时刻!装成功了!
2.3:解决warning:No module named ‘_lzma’
刚刚我们虽然装成功了,但是还是有点问题的,就是找不到lzma模块。这个模块是数据压缩和解压缩相关的,日后很有可能需要这个模块功能。所以我们再来搞一波。安装XZ Utils库
brew install xz
说已经安装了,没关系,冲一波更新
brew upgrade xz
啊?已经是最新了?
没关系,那可能是链接有问题,强制重新链接。
brew unlink xz && brew link xz
可以看到解除的链接和新建的链接数确实不一样。
命运的转折点之7:再冲一波pyenv install!
这次完全没问题了捏嘿嘿。
下载python3.10,发现仍有问题,初步分析
再试着下一下python3.10
为什么又又又构建失败😭(此时已经是深夜一点,本人搞了一天了,心情崩溃)
没事,初步分析一下,可以看到关键信息为:
ModuleNotFoundError: No module named '_ssl'
ERROR: The Python ssl extension was not compiled. Missing the OpenSSL lib?
说缺少OpenSSL库,开玩笑,我们在尝试方案1的1.3就安装了openssl了好吧😑
那只可能是找不到文件所在了。
(同时浅浅分析一波为什么安装3.6的时候没有出现这个问题,貌似是因为3.6中,ssl扩展模块使用了自己的TLS实现,而不是依赖于OpenSSL库)
尝试方案3:环境变量大法
3.1:再次设置环境变量找到SSL库文件
运行以下命令:
export LDFLAGS="-L$(brew --prefix openssl)/lib $LDFLAGS"
export CPPFLAGS="-I$(brew --prefix openssl)/include $CPPFLAGS"
export PKG_CONFIG_PATH="$(brew --prefix openssl)/lib/pkgconfig:$PKG_CONFIG_PATH"
这里的-L
选项用于指定库文件的搜索路径,-I
选项用于指定头文件的搜索路径,$
用于引用变量,:
用于分隔路径
之所以LDFLAGS和CPPFLAGS没有用:
来分隔路径是因为他们是编译器和链接器的选项,使用空格来分隔路径,
这三条命令会在我们2.2设置的值的后面追加值,所以完全不用担心覆盖之前的值捏😋
by the way:PKG_CONFIG_PATH是一个环境变量,用于指定pkg-config命令的搜索路径。
命运的转折点之8:再冲一波pyenv install!
3.2:brew unlink and brew link
上一步没用?没事,我们抬手就是一个
brew unlink openssl && brew link --force openssl
可以看到前后的数量还是不太一样的,看起来很有希望的亚子(
命运的转折点之9:再冲一波pyenv install!
3.3:查看是否有多个环境的openssl
什么😧?
字数都已经来到6000+了,居然还没有解决🤯
而且报错还是一样的说找不到SSL库文件(你真是够了,住手吧电脑😔
哦对哦,突然想起来,貌似自己电脑上有openssl@1.1版本的,还有openssl@3版本的
(其实是之前看了一眼日志,貌似说两个版本的openssl都用了,但是截图现在找不到了)
可以使用如下命令确定一下电脑上的版本:
brew list | grep openssl
可以选择卸载掉其中一个版本,然后注意链接什么的要重连一下。也可以直接指定系统变量,瓦塔西选择了后者
export LDFLAGS="-L$(brew --prefix openssl@1.1)/lib $LDFLAGS"
export CPPFLAGS="-I$(brew --prefix openssl@1.1)/include $CPPFLAGS"
export PKG_CONFIG_PATH="$(brew --prefix openssl@1.1)/lib/pkgconfig:$PKG_CONFIG_PATH"
命运的转折点之10:再冲一波pyenv install!
芜湖!成功!
其他:
其实我最后的环境变量应该长下面那样,可以试试这最后一步
export LDFLAGS="-L$(brew --prefix openssl@1.1)/lib -L$(brew --prefix gdbm)/lib -L$(brew --prefix readline)/lib -L$(brew --prefix zlib)/lib -isysroot $SDKROOT $LDFLAGS"
export CPPFLAGS="-I$(brew --prefix openssl@1.1)/include -I$(brew --prefix gdbm)/include -I$(brew --prefix readline)/include -I$(brew --prefix zlib)/include -isysroot $SDKROOT $CPPFLAGS"
export PKG_CONFIG_PATH="$(brew --prefix openssl@1.1)/lib/pkgconfig:$(brew --prefix gdbm)/lib/pkgconfig:$PKG_CONFIG_PATH"