我有一个带有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 可以解决这个问题。
TL;DR- 使用pyproject.toml
构建项目时,默认使用构建隔离。此安装setuptools
来自pypi
,它未配置为与 conda 编译器一起使用。如果使用选项--no-build-isolation
,则会生成包。
这里的问题是pyproject.toml
构建隔离过程与具有自己的编译器conda
环境不兼容。已经有几份关于这种不兼容的报告,例如这里提到了这一点。
这里的核心问题是setuptools
依赖于一个名为sysconfigdata_xxx
的包来获取有关如何构建包的信息(请参阅此处),特别是获取链接器标志。默认情况下,它会获取包'_sysconfigdata_{abi}_{platform}_{multiarch}'
。当setuptools
与 conda 一起安装时,它会被修补以获取在 conda env 中设置的 env 变量_CONDA_PYTHON_SYSCONFIGDATA_NAME
中定义的不同系统配置。然后,_sysconfig_*
模块使用正确的编译标志。
通过构建隔离,将创建一个新的环境(在/tmp/pip-build-env-XXX/
年的 Linux 上),并安装一个新版本的setuptools
,与conda
中的不同。 这会将设置工具恢复为原始行为,即获取原始_sysconfig_*
文件。在 python3.8 中,此包为链接器标志设置了标志--sysroot=/
。因此,pthread
的共享库不是在conda
库中搜索,而是在似乎不存在正确版本的系统/lib64
中搜索,这就解释了为什么此配置会中断。这个_sysconfig_*
模块在python3.9
年已经更改,并且不再设置--sysroot=/
标志。这就是为什么它适用于python3.9
.
为了在不破坏构建隔离的情况下解决这个问题,我认为最好的方法是设法在调用构建环境时自动将_PYTHON_SYSCONFIGDATA_NAME
(这是查找模块名称的主要来源)设置为指向构建环境中的_CONDA_PYTHON_SYSCONFIGDATA_NAME
(指向正确的配置)。这需要使用以下补丁修补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 变量。