为什么在Alpine上用musl编译失败而在ArchLinux上成功

时间:2019-02-16 08:53:30

标签: compilation musl

这是一个好奇心问题:为什么?

为什么对于完全相同的代码会有不同的行为?

我经常遇到这样的问题:我可以在一个发行版中编译某些内容,而不能在另一个发行版中编译。因此,今天我再次碰到了其中一个问题:当我以与ArchLinux相同的方式构建PostgreSQL的pg_dump时,它可以运行,但是当我在Alpine上运行时,它会因以下错误而失败:

gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -Wno-format-truncation -Wno-stringop-truncation -static -fPIC -D_REENTRANT -D_THREAD_SAFE -D_POSIX_PTHREAD_SEMANTICS -fPIC -shared -Wl,-soname,libpq.so.5 -Wl,--version-script=exports.list -o libpq.so.5.11 fe-auth.o fe-auth-scram.o fe-connect.o fe-exec.o fe-misc.o fe-print.o fe-lobj.o fe-protocol2.o fe-protocol3.o pqexpbuffer.o fe-secure.o libpq-events.o chklocale.o inet_net_ntop.o noblock.o pgstrcasecmp.o pqsignal.o thread.o getpeereid.o pg_strong_random.o encnames.o wchar.o base64.o ip.o md5.o scram-common.o saslprep.o unicode_norm.o sha2.o -L../../../src/port -L../../../src/common    -Wl,--as-needed -Wl,-rpath,'/usr/local/pgsql/lib',--enable-new-dtags    
/lib/gcc/x86_64-linux-musl/8.2.0/../../../../x86_64-linux-musl/bin/ld: /lib/gcc/x86_64-linux-musl/8.2.0/crtbeginT.o: relocation R_X86_64_32 against hidden symbol `__TMC_END__' can not be used when making a shared object
/lib/gcc/x86_64-linux-musl/8.2.0/../../../../x86_64-linux-musl/bin/ld: /lib/gcc/x86_64-linux-musl/8.2.0/crtend.o: relocation R_X86_64_32 against `.ctors' can not be used when making a shared object; recompile with -fPIC
/lib/gcc/x86_64-linux-musl/8.2.0/../../../../x86_64-linux-musl/bin/ld: final link failed: nonrepresentable section on output
collect2: error: ld returned 1 exit status
make[1]: Leaving directory '/src/src/interfaces/libpq'
make[1]: *** [../../../src/Makefile.shlib:309: libpq.so.5.11] Error 1
make: *** [../../../src/Makefile.global:580: submake-libpq] Error 2

这是Alpine的Dockerfile:

FROM muslcc/x86_64:x86_64-linux-musl

RUN apk update && apk add make

ENV DOWNLOAD_URL https://ftp.postgresql.org/pub/source/v11.2/postgresql-11.2.tar.bz2

WORKDIR /src
RUN wget "$DOWNLOAD_URL" && \
    tar xvjf "${DOWNLOAD_URL##*/}" --strip-components=1 && \
    rm -fv "${DOWNLOAD_URL##*/}"

# NOTE: I left the -fPIC here for clarity sake but it fails with
#       the same error with or without it
RUN ./configure --without-readline --without-zlib CFLAGS="-static -fPIC"
RUN cd src/bin/pg_dump && make pg_dump

这是ArchLinux的Dockerfile:

FROM archlinux/base

RUN pacman -Syu --noconfirm --needed base-devel musl

ENV DOWNLOAD_URL https://ftp.postgresql.org/pub/source/v11.2/postgresql-11.2.tar.bz2

WORKDIR /src
RUN curl -o "${DOWNLOAD_URL##*/}" "$DOWNLOAD_URL" && \
    tar xvjf "${DOWNLOAD_URL##*/}" --strip-components=1 && \
    rm -fv "${DOWNLOAD_URL##*/}"

RUN ./configure --without-readline --without-zlib CC="musl-gcc" CFLAGS="-static"
RUN cd src/bin/pg_dump && make pg_dump

我什至不知道在哪里看。 musl的版本可能有所不同吗?另一个编译工具?我真的不想要解决方案,我想了解原因。

1 个答案:

答案 0 :(得分:1)

我没有使用Alpine Linux的丰富经验,我需要自己使用它,但是似乎有些相当基本的标准C库是作为非平台无关代码(PIC)构建的,这意味着您不允许将动态库与其链接。

我将开始就此向Alpine Linux开发人员寻求帮助,因为PostgreSQL可能有一些配置标志,这些标志允许您构建所需的内容。

现在,我注意到一件事。您将CFLAGS=-static传递给编译,但是没有意义,因为./configure已经将其设置为共享-请仔细查看引用的编译器调用。如果要进行静态构建,则需要找到适当的配置标志并将其与./configure一起使用。 我您的案件--disable-shared应该可以解决。

CFLAGS="-static" CXXFLAGS="-static" LDFLAGS="-Wl,-Bstatic" ./configure --without-readline --without-zlib

似乎在不离开-static的情况下启用了-shared