【问题标题】:Compile Python 3.6 statically with OpenSSL使用 OpenSSL 静态编译 Python 3.6
【发布时间】:2019-04-30 20:41:04
【问题描述】:

我正在尝试使用 OpenSSL 在 Linux 上静态编译 Python 3.6。

我的构建发生在 dockerfile 中,但实际上是这样的:

$ ./configure --prefix=/task/build --disable-shared LDFLAGS="-static"
$ make altinstall

更新Modules/Setup.local 使其看起来像:

*static*

# Socket module helper for SSL support; you must comment out the other
# socket line above, and possibly edit the SSL variable:
SSL=/usr/local/ssl
_ssl _ssl.c \
 -DUSE_SSL -I$(SSL)/include -I$(SSL)/include/openssl \
 -L$(SSL)/lib -lssl -lcrypto

但是,在配置步骤中,我收到错误:

Step 9/14 : RUN ./configure --prefix=/task/build --disable-shared LDFLAGS="-static"
     ---> Running in cb79ee47052b
    checking for git... found
    checking build system type... x86_64-pc-linux-gnu
    checking host system type... x86_64-pc-linux-gnu
    checking for python3.6... no
    checking for python3... no
    checking for python... python
    checking for --enable-universalsdk... no
    checking for --with-universal-archs... no
    checking MACHDEP... linux
    checking for --without-gcc... no
    checking for --with-icc... no
    checking for gcc... gcc
    checking whether the C compiler works... no
    configure: error: in `/task/cpython':
    configure: error: C compiler cannot create executables
    See `config.log' for more details
The command '/bin/sh -c ./configure --prefix=/task/build --disable-shared LDFLAGS="-static"' returned a non-zero code: 77

如果我将配置命令更改为:

$ ./configure --prefix=/task/build --disable-shared

我得到一个已编译的二进制文件,但它没有静态链接到 OpenSSL。

我做错了什么?

谢谢!


构建 dockerfile:

FROM amazonlinux:2017.03.1.20170812

ARG python_version=3.6.8

WORKDIR /task
COPY Modules-Setup.local /task/Modules-Setup.local

# Install requirements
RUN yum install -y \
  gcc \
  git \
  gzip \
  openssl-devel \
  tar \
  zlib \
  zlib-devel

# Get openssl and python source
RUN git clone https://github.com/python/cpython.git
WORKDIR /task/cpython
RUN git checkout tags/v${python_version}

# Configure the build
RUN ./configure --prefix=/task/build --disable-shared LDFLAGS="-static"

# Append modules setup with custom values
RUN cat /task/Modules-Setup.local >> /task/cpython/Modules/Setup.local
RUN cat /task/cpython/Modules/Setup.local

# Build
RUN make altinstall

# Zip the results
WORKDIR /task/build
RUN tar --create --gzip --file=/task/python-${python_version}.tar.gz \
  lib/ bin/

【问题讨论】:

  • configure 命令不正确 - 尝试:LDFLAGS="-static" ./configure --prefix=/task/build --disable-shared。您能否详细说明静态链接到 OpenSSL 的含义?
  • 静态链接意味着将 OpenSSL 存档包含在我的 python lib 包中,如果澄清的话,请 lmk。
  • 我是这么认为的,您需要的第一件事是静态 OpenSSL 库。如果您没有这些,则在 Python 方面无能为力(就构建标志、选项而言)。 stackoverflow.com/questions/725472/….
  • 明白了——谢谢。我最终想要一个包含运行 python 所需的一切的文件夹(带有一些可用的链接模块,如 openssl),我可以将其复制到机器上并立即使用。应该按照下面 jww 的描述编译(静态)这些包并链接它们吗?
  • 这可能是 XY 问题。有一些工具(至少在 Win 上)可以收集运行一段 Python 代码所需的任何东西(例如 py2exe)。你弄错了静态链接:它指的是 python 可执行文件:如果是静态的,它将有 ~5MB,否则,它将有 ~10KB (但你也会有一个 .exe 所依赖的 libpython3.6m.so,以及包含所有 Python > 核心功能)。 @jww 解释得很好。底线:如果您想静态链接到某个东西,那么应该(也)为静态链接构建该东西。

标签: python linux openssl static-linking


【解决方案1】:

我正在尝试使用 OpenSSL 在 Linux 上静态编译 Python 3.6。
...

# Socket module helper for SSL support; you must comment out the other
# socket line above, and possibly edit the SSL variable:
SSL=/usr/local/ssl
_ssl _ssl.c \
 -DUSE_SSL -I$(SSL)/include -I$(SSL)/include/openssl \
 -L$(SSL)/lib -lssl -lcrypto

-lssl-lcrypto 更改为-l:libssl.a-l:libcrypto.a

SSL=/usr/local/ssl
_ssl _ssl.c \
  -DUSE_SSL -I$(SSL)/include -I$(SSL)/include/openssl \
  -L$(SSL)/lib -l:libssl.a -l:libcrypto.a

您也可以使用存档的完整路径:

SSL=/usr/local/ssl
_ssl _ssl.c \
  -DUSE_SSL -I$(SSL)/include -I$(SSL)/include/openssl \
  $(SSL)/lib/libssl.a $(SSL)/lib/libcrypto.a

存档 (*.a) 只是对象文件 (*.o) 的集合,因此您可以在任何使用对象文件的地方使用存档。

另见ld(2) man page中的-l:filename

--library=namespec

将 namespec 指定的档案或目标文件添加到列表中 要链接的文件。此选项可以使用任意次数。如果 namespec 的格式为 :filename,ld 将在库路径中搜索 一个名为 filename 的文件,否则它将在库路径中搜索 一个名为 libnamespec.a 的文件。

如果您正在使用/usr/local 中的其他组件,那么您可能需要将-L/usr/local/lib -Wl,-R,/usr/local/lib -Wl,--enable-new-dtags 添加到您的LDFLAGSnew-dtags 在 ELF 标头中嵌入了 RUNPATH(与 RPATH 相对)。 RUNPATH 可以被 LD_LIBRARY_PATH 覆盖。


我得到一个已编译的二进制文件,但它没有静态链接到 OpenSSL。

检查的方法是将ldd 与您在运行时使用的路径一起使用。例如,这里来自 Fedora 上的本地 OpenSSL 构建:

$ ldd /usr/local/bin/openssl
    linux-vdso.so.1 (0x00007fff3cde6000)
    libssl.so.1.0.0 => /usr/local/lib64/libssl.so.1.0.0 (0x00007f043dc4e000)
    libcrypto.so.1.0.0 => /usr/local/lib64/libcrypto.so.1.0.0 (0x00007f043d9df000)
    libdl.so.2 => /lib64/libdl.so.2 (0x00007f043d9c0000)
    libc.so.6 => /lib64/libc.so.6 (0x00007f043d7fa000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f043dcc0000)

这里有几个相关的问题,但看起来它们并不涉及使用 Python 进行静态链接。


需要明确的是,config.log 有错误,但您没有显示其中的相关部分:

checking whether the C compiler works... no
configure: error: in `/task/cpython':
configure: error: C compiler cannot create executables
See `config.log' for more details

静态 OpenSSL 可能(也可能不会)解决问题。

【讨论】:

  • 有没有办法(类似于ldd)来发现我编译的二进制文件将在执行期间(不仅仅是在启动时)导入的共享对象?
【解决方案2】:

我遇到了同样的问题并通过安装静态 glibc 库解决了它:

yum install glibc-static

【讨论】:

    猜你喜欢
    • 2019-08-10
    • 2018-10-18
    • 1970-01-01
    • 1970-01-01
    • 2017-07-17
    • 2018-09-07
    • 1970-01-01
    • 2021-01-21
    • 2010-11-12
    相关资源
    最近更新 更多