在环境中编译时,Conda 不会在正确的位置查找 libpthread 和 libpthread_nonshared

发布于 2025-01-11 19:34:57 字数 2202 浏览 0 评论 0原文

我有一个带有 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

森林迷了鹿 2025-01-18 19:34:57

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 时在本地工作):

index daeb7fb..a1c92b4 100644
--- a/pip/_internal/build_env.py
+++ b/pip/_internal/build_env_modified.py
@@ -128,7 +128,8 @@ class BuildEnvironment:
     def __enter__(self) -> None:
         self._save_env = {
             name: os.environ.get(name, None)
-            for name in ("PATH", "PYTHONNOUSERSITE", "PYTHONPATH")
+            for name in ("PATH", "PYTHONNOUSERSITE", "PYTHONPATH",
+                         "_PYTHON_SYSCONFIGDATA_NAME")
         }
 
         path = self._bin_dirs[:]
@@ -145,6 +146,8 @@ class BuildEnvironment:
                 "PYTHONPATH": os.pathsep.join(pythonpath),
             }
         )
+        if '_PYTHON_SYSCONFIGDATA_NAME' not in os.environ:
+            os.environ['_PYTHON_SYSCONFIGDATA_NAME'] = os.environ['_CONDA_PYTHON_SYSCONFIGDATA_NAME']
 
     def __exit__(
         self,

也许这可以在 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 install setuptools from pypi, 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 with conda 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 called sysconfigdata_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}'. When setuptools 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 of setuptools, different from the one in conda 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 for pthread are search not in conda 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 in python3.9, and the --sysroot=/ flag is not set anymore. This is why it work on python3.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 patching pip with the following patch (this works locally when patching pip in the reproducer env):

index daeb7fb..a1c92b4 100644
--- a/pip/_internal/build_env.py
+++ b/pip/_internal/build_env_modified.py
@@ -128,7 +128,8 @@ class BuildEnvironment:
     def __enter__(self) -> None:
         self._save_env = {
             name: os.environ.get(name, None)
-            for name in ("PATH", "PYTHONNOUSERSITE", "PYTHONPATH")
+            for name in ("PATH", "PYTHONNOUSERSITE", "PYTHONPATH",
+                         "_PYTHON_SYSCONFIGDATA_NAME")
         }
 
         path = self._bin_dirs[:]
@@ -145,6 +146,8 @@ class BuildEnvironment:
                 "PYTHONPATH": os.pathsep.join(pythonpath),
             }
         )
+        if '_PYTHON_SYSCONFIGDATA_NAME' not in os.environ:
+            os.environ['_PYTHON_SYSCONFIGDATA_NAME'] = os.environ['_CONDA_PYTHON_SYSCONFIGDATA_NAME']
 
     def __exit__(
         self,

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 or setup.py.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文