在环境中编译时,Conda 不会在正确的位置查找 libpthread 和 libpthread_nonshared
我有一个带有 Cython 扩展的 python 包,我正在尝试编译它。
我收到以下错误作为 pip install
的输出:
/home/user/anaconda3/envs/benchopt_lasso/bin/x86_64-conda-linux-gnu-c++ -pthread -shared
-B /home/user/anaconda3/envs/benchopt_lasso/compiler_compat -L/home/user/anaconda3/envs/benchopt_lasso/lib -Wl,
-rpath=/home/user/anaconda3/envs/benchopt_lasso/lib -Wl,--no-as-needed -Wl,--sysroot=/
-Wl,-O2 -Wl,--sort-common -Wl,--as-needed -Wl,-z,relro -Wl,-z,now -Wl,--disable-new-dtags -Wl,--gc-sections -Wl,--allow-shlib-undefined
-Wl,-rpath,/home/user/anaconda3/envs/benchopt_lasso/lib
-Wl,-rpath-link,/home/user/anaconda3/envs/benchopt_lasso/lib -L/home/user/anaconda3/envs/benchopt_lasso/lib -march=nocona
-mtune=haswell -ftree-vectorize -fPIC -fstack-protector-strong -fno-plt -O2 -ffunction-sections -pipe
-isystem /home/user/anaconda3/envs/benchopt_lasso/include -DNDEBUG
-D_FORTIFY_SOURCE=2 -O2 -isystem /home/user/anaconda3/envs/benchopt_lasso/include build/temp.linux-x86_64-3.8/celer/lasso_fast.o
-o build/lib.linux-x86_64-3.8/celer/lasso_fast.cpython-38-x86_64-linux-gnu.so
/home/user/anaconda3/envs/benchopt_lasso/compiler_compat/ld: cannot find /lib64/libpthread.so.0
/home/user/anaconda3/envs/benchopt_lasso/compiler_compat/ld: cannot find /usr/lib64/libpthread_nonshared.a
collect2: error: ld returned 1 exit status
这些库不在 /usr/lib64 中,它们位于 /home/user/anaconda3/envs/benchopt_lasso/x86_64-conda- linux-gnu/sysroot/usr/lib64/
为什么 conda 的编译器找不到它们?我怀疑选项 -sysroot=/
,而默认值指向正确的位置
/home/user/anaconda3/envs/benchopt_lasso/bin/x86_64-conda-linux-gnu-c++ --print-sysroot
/home/user/anaconda3/envs/benchopt_lasso/bin/../x86_64-conda-linux-gnu/sysroot
在新终端中使用以下 env.yml 重现的步骤(使用另一个包)
文件:
name: reprod
channels:
- conda-forge
- nodefaults
dependencies:
- python=3.8
- numpy
- cython
- compilers
- pip
conda env create -n reprod -f env.yml
conda activate reprod
pip install git+https://bitbucket.org/mathurinm/cd_solver.git@module_structure -v
在 env 要求中更改为 python=3.9 可以解决该问题。
I have a python package with a Cython extension that I'm trying to compile.
I get the following error as the output of pip install
:
/home/user/anaconda3/envs/benchopt_lasso/bin/x86_64-conda-linux-gnu-c++ -pthread -shared
-B /home/user/anaconda3/envs/benchopt_lasso/compiler_compat -L/home/user/anaconda3/envs/benchopt_lasso/lib -Wl,
-rpath=/home/user/anaconda3/envs/benchopt_lasso/lib -Wl,--no-as-needed -Wl,--sysroot=/
-Wl,-O2 -Wl,--sort-common -Wl,--as-needed -Wl,-z,relro -Wl,-z,now -Wl,--disable-new-dtags -Wl,--gc-sections -Wl,--allow-shlib-undefined
-Wl,-rpath,/home/user/anaconda3/envs/benchopt_lasso/lib
-Wl,-rpath-link,/home/user/anaconda3/envs/benchopt_lasso/lib -L/home/user/anaconda3/envs/benchopt_lasso/lib -march=nocona
-mtune=haswell -ftree-vectorize -fPIC -fstack-protector-strong -fno-plt -O2 -ffunction-sections -pipe
-isystem /home/user/anaconda3/envs/benchopt_lasso/include -DNDEBUG
-D_FORTIFY_SOURCE=2 -O2 -isystem /home/user/anaconda3/envs/benchopt_lasso/include build/temp.linux-x86_64-3.8/celer/lasso_fast.o
-o build/lib.linux-x86_64-3.8/celer/lasso_fast.cpython-38-x86_64-linux-gnu.so
/home/user/anaconda3/envs/benchopt_lasso/compiler_compat/ld: cannot find /lib64/libpthread.so.0
/home/user/anaconda3/envs/benchopt_lasso/compiler_compat/ld: cannot find /usr/lib64/libpthread_nonshared.a
collect2: error: ld returned 1 exit status
These libs are not in /usr/lib64, they are in /home/user/anaconda3/envs/benchopt_lasso/x86_64-conda-linux-gnu/sysroot/usr/lib64/
Why is conda's compiler not finding them ? I'm suspecting the option -sysroot=/
, whereas the default value points to the correct location
/home/user/anaconda3/envs/benchopt_lasso/bin/x86_64-conda-linux-gnu-c++ --print-sysroot
/home/user/anaconda3/envs/benchopt_lasso/bin/../x86_64-conda-linux-gnu/sysroot
Steps to reproduce (with another package), in a fresh terminal, with the following env.yml
file:
name: reprod
channels:
- conda-forge
- nodefaults
dependencies:
- python=3.8
- numpy
- cython
- compilers
- pip
conda env create -n reprod -f env.yml
conda activate reprod
pip install git+https://bitbucket.org/mathurinm/cd_solver.git@module_structure -v
Changing to python=3.9 in the env requirement solves the issue.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
TL;DR - 使用
pyproject.toml
构建项目时,默认使用构建隔离。此命令从pypi
安装setuptools
,该工具未配置为与 conda 编译器一起使用。如果您使用选项--no-build-isolation
,则会构建包。这里的问题是 pyproject.toml 构建隔离过程与拥有自己的编译器的 conda env 不兼容。有几份关于这种不兼容性的报告,例如此处提到了这一点。
这里的核心问题是
setuptools
依赖于一个名为sysconfigdata_xxx
的包来获取有关如何构建包的信息(请参阅此处),特别是获取链接器标志。默认情况下,它会获取包'_sysconfigdata_{abi}_{platform}_{multiarch}'
。当setuptools
与 conda 一起安装时,它是 修补 以获取在env 变量_CONDA_PYTHON_SYSCONFIGDATA_NAME
,在 conda env 中设置。然后,_sysconfig_*
模块使用正确的编译标志。通过构建隔离,将创建一个新的环境(在 Linux 上的
/tmp/pip-build-env-XXX/
中)和新版本的setuptools
,与conda
中的一个已安装。这会将 setuptools 恢复为原始行为,即获取原始_sysconfig_*
文件。在python3.8中,这个包为链接器标志设置了标志--sysroot=/
。因此,pthread 的共享库不是在 conda 库中搜索,而是在系统 /lib64 中搜索,其中似乎不存在正确的版本,这解释了为什么此配置会中断。此_sysconfig_*
模块已在python3.9
中更改,并且不再设置--sysroot=/
标志。这就是它在python3.9
上工作的原因。为了在不破坏构建隔离的情况下解决这个问题,我认为最好的方法是自动将
_PYTHON_SYSCONFIGDATA_NAME
(这是查找模块名称的主要来源)设置为指向_CONDA_PYTHON_SYSCONFIGDATA_NAME
调用时在构建环境中添加 code> (指向正确的配置)。这需要使用以下补丁修补pip
(这在复制器环境中修补 pip 时在本地工作):也许这可以在
conda-forge/pip-feedstock
上传播,但是这个似乎不切实际。我没有看到任何方法可以仅使用配置文件或 setup.py 来更改 pip 构建系统中的 env 变量。TL;DR - when building a project with
pyproject.toml
, the default is to use build-isolation. This installsetuptools
frompypi
, which is not configured to work with conda compilers. If you use the option--no-build-isolation
, the package builds.The issue here is that
pyproject.toml
build isolation process is not compatible withconda
env that have its own compilers. There has been several report of this incompatibility, for instance this is mentionned here.The core issue here is that
setuptools
relies on a package calledsysconfigdata_xxx
to get info on how to build packages (see here) and in particular fetch the linker flags. By default, it fetches the package'_sysconfigdata_{abi}_{platform}_{multiarch}'
. Whensetuptools
is installed with conda, it is patched to fetch a different sysconfig defined in the env variable_CONDA_PYTHON_SYSCONFIGDATA_NAME
, set in the conda env. The_sysconfig_*
module then uses the correct compilation flags.With the build isolation, a new env is create (on linux in
/tmp/pip-build-env-XXX/
) and a new version ofsetuptools
, different from the one inconda
is installed. This reverts setuptools to the orignal behavior, i.e. fetching the orignal_sysconfig_*
file. In python3.8, this package set the flag--sysroot=/
for the linker flags. Thus, the shared library forpthread
are search not inconda
libraries but in system/lib64
where it seems the right version are not present, which explains why this breaks for this config. This_sysconfig_*
module has been changed inpython3.9
, and the--sysroot=/
flag is not set anymore. This is why it work onpython3.9
.To solve this without breaking the build isolation, I think the best way would be to manage to automatically set
_PYTHON_SYSCONFIGDATA_NAME
(which is the primary source to find the module name) to point on_CONDA_PYTHON_SYSCONFIGDATA_NAME
(which point to the right config) in the build env when it is called. This requires patchingpip
with the following patch (this works locally when patching pip in the reproducer env):Maybe this could be propagated on
conda-forge/pip-feedstock
but this seems unpractical. I did not see any way to change env variable in the pip build system just with config files orsetup.py
.