Jack Jansen 在10年前坑了所有在 Yosemite 上编译 python 的人
把 mac 升到 yosemite 之后,gentoo prefix 的 gcc 在升级时果不其然的坏掉了。不想再折腾一遍当初升 mavericks 时经历的痛苦,而且 gentoo prefix 只能用 gcc ,而 gcc-apple 永远的停留在了 4.2 上,已经不是个称职的 OSX 包管理器了。所以,就打算转到 homebrew 上。
homebrew 上手很容易,python 的包都用 pip 管理,这个做法也挺好的。
但很快就发现在 homebrew 上,如果用 pip 装的包需要编译扩展模块,在 link 阶段就一定会 fail ,错误信息:
clang -bundle Python.framework/Versions/2.7/Python -L/usr/local/lib -L/usr/local/opt/sqlite/lib build/temp.macosx-10.10-x86_64-2.7/foo.o -o build/lib.macosx-10.10-x86_64-2.7/foo.so
clang: error: no such file or directory: 'Python.framework/Versions/2.7/Python'
error: command 'clang' failed with exit status 1
在 V2EX 上也有人发现了这个问题 http://www.v2ex.com/t/116219
这个 "clang -bundle Python.framework/Versions/2.7/Python -L/usr/local/lib -L/usr/local/opt/sqlite/lib" 是在 distutils/commands/build_ext.py 的 build_ext.run 方法中,通过调用 distutils.sysconfig.customize_compiler 给 compiler 对象设置在 linker_so 属性上的。看了一下 sysconfig.py 的源码,发现是从 _sysconfigdata.build_time_vars['LDSHARED'] 读出来的,这个是 python 编译期的配置,难道是 homebrew 编译 python 在编译期配置有问题?
问了一下员外,他是 Mavericks ,执行 python -c 'from _sysconfigdata import *; print build_time_vars["LDSHARED"]' 输出的结果很正常,所以还是怀疑是 python 本身的问题。
在 Python 的源码里 grep 了一下 LDSHARED ,看到 configure.ac 里这一段时,我都快要喷血了:
case $ac_sys_system/$ac_sys_release in
...
Darwin/*)
# Use -undefined dynamic_lookup whenever possible (10.3 and later).
# This allows an extension to be used in any Python
if test ${MACOSX_DEPLOYMENT_TARGET} '>' 10.2
then
if test "${enable_universalsdk}"; then
LDFLAGS="${UNIVERSAL_ARCH_FLAGS} -isysroot ${UNIVERSALSDK} ${LDFLAGS}"
fi
LDSHARED='$(CC) -bundle -undefined dynamic_lookup'
LDCXXSHARED='$(CXX) -bundle -undefined dynamic_lookup'
BLDSHARED="$LDSHARED"
else
LDSHARED='$(CC) -bundle'
...
就在这一句:
if test ${MACOSX_DEPLOYMENT_TARGET} '>' 10.2
大哥这是 shell 好不好,用字符串来比较版本号咩?
Yosemite 的版本号是 10.10 ,字符串比较下 "10.10" < "10.2" ,分支就走错了!
上 hg.python.org 看了一下发现最新的代码里已经修正了,是10天前报告的 bug http://bugs.python.org/issue21811 。然后就看到 hg log 里在紧锣密鼓的准备发布 2.7.8
一看 ftp 已经上传了 https://www.python.org/ftp/python/2.7.8/ ,赶紧 brew edit python 改了下载地址重新安装,万事大吉。
顺便 hg blame 了一下这个丢人的代码是十年前 Jack Jansen 引入的 http://hg.python.org/cpython/rev/32218#l3.56 。
记得看到不少 python 项目里会有类似这样的代码:
if sys.version < '2.5':
但是 python 不会有 2.8 了,这种代码要等到 python 10 的时候才能坑到人了。
homebrew 上手很容易,python 的包都用 pip 管理,这个做法也挺好的。
但很快就发现在 homebrew 上,如果用 pip 装的包需要编译扩展模块,在 link 阶段就一定会 fail ,错误信息:
clang -bundle Python.framework/Versions/2.7/Python -L/usr/local/lib -L/usr/local/opt/sqlite/lib build/temp.macosx-10.10-x86_64-2.7/foo.o -o build/lib.macosx-10.10-x86_64-2.7/foo.so
clang: error: no such file or directory: 'Python.framework/Versions/2.7/Python'
error: command 'clang' failed with exit status 1
在 V2EX 上也有人发现了这个问题 http://www.v2ex.com/t/116219
这个 "clang -bundle Python.framework/Versions/2.7/Python -L/usr/local/lib -L/usr/local/opt/sqlite/lib" 是在 distutils/commands/build_ext.py 的 build_ext.run 方法中,通过调用 distutils.sysconfig.customize_compiler 给 compiler 对象设置在 linker_so 属性上的。看了一下 sysconfig.py 的源码,发现是从 _sysconfigdata.build_time_vars['LDSHARED'] 读出来的,这个是 python 编译期的配置,难道是 homebrew 编译 python 在编译期配置有问题?
问了一下员外,他是 Mavericks ,执行 python -c 'from _sysconfigdata import *; print build_time_vars["LDSHARED"]' 输出的结果很正常,所以还是怀疑是 python 本身的问题。
在 Python 的源码里 grep 了一下 LDSHARED ,看到 configure.ac 里这一段时,我都快要喷血了:
case $ac_sys_system/$ac_sys_release in
...
Darwin/*)
# Use -undefined dynamic_lookup whenever possible (10.3 and later).
# This allows an extension to be used in any Python
if test ${MACOSX_DEPLOYMENT_TARGET} '>' 10.2
then
if test "${enable_universalsdk}"; then
LDFLAGS="${UNIVERSAL_ARCH_FLAGS} -isysroot ${UNIVERSALSDK} ${LDFLAGS}"
fi
LDSHARED='$(CC) -bundle -undefined dynamic_lookup'
LDCXXSHARED='$(CXX) -bundle -undefined dynamic_lookup'
BLDSHARED="$LDSHARED"
else
LDSHARED='$(CC) -bundle'
...
就在这一句:
if test ${MACOSX_DEPLOYMENT_TARGET} '>' 10.2
大哥这是 shell 好不好,用字符串来比较版本号咩?
Yosemite 的版本号是 10.10 ,字符串比较下 "10.10" < "10.2" ,分支就走错了!
上 hg.python.org 看了一下发现最新的代码里已经修正了,是10天前报告的 bug http://bugs.python.org/issue21811 。然后就看到 hg log 里在紧锣密鼓的准备发布 2.7.8
![]() |
一看 ftp 已经上传了 https://www.python.org/ftp/python/2.7.8/ ,赶紧 brew edit python 改了下载地址重新安装,万事大吉。
顺便 hg blame 了一下这个丢人的代码是十年前 Jack Jansen 引入的 http://hg.python.org/cpython/rev/32218#l3.56 。
记得看到不少 python 项目里会有类似这样的代码:
if sys.version < '2.5':
但是 python 不会有 2.8 了,这种代码要等到 python 10 的时候才能坑到人了。