rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
98.58k stars 12.74k forks source link

Rust 1.35.0 x86_64-unknown-linux-musl has multiple definition of `__errno_location` #61264

Open oherrala opened 5 years ago

oherrala commented 5 years ago

This is breakage between 1.34(.2) and 1.35.0.

1.34 worked fine, 1.35 not any more. We are building x86_64-unknown-linux-musl using musl 1.1.22 (with clang).

/opt/musl/lib/libc.a(__errno_location.lo): In function `___errno_location': src/errno/__errno_location.c:(.text.__errno_location+0x0): multiple definition of `__errno_location'
/tmp/rustcHiVA0H/liblibc-a19d328d73c1ea73.rlib(__errno_location.lo):__errno_location.c:(.text.__errno_location+0x0): first defined here

The following Dockerfile can be used to demonstrate the issue. It's quite long because of building both musl and libressl for Musl compilation.

FROM rust:1.35.0
#         ^-- 1.35.0 build breaks, 1.34.2 here and build is good

ENV TARGET=x86_64-unknown-linux-musl

ARG LIBRESSL=libressl-2.9.1
ARG MUSL=musl-1.1.22

ARG DEBIAN_FRONTEND=noninteractive
RUN apt -y update && \
    apt -y install clang && \
    rustup target install ${TARGET}

RUN printf '[target.x86_64-unknown-linux-musl]\nlinker = "musl-clang"\n' >/usr/local/cargo/config

WORKDIR /work

RUN curl -fO https://www.musl-libc.org/releases/${MUSL}.tar.gz && \
    tar zxf ${MUSL}.tar.gz && \
    cd ${MUSL} && \
    ./configure CC=clang CFLAGS="-fPIC" --prefix=/opt/musl --enable-shared=no && \
    make V=1 -j4 && \
    make V=1 install

ENV PATH=/opt/musl/bin:$PATH

# We do Musl build hence point to correct tool
ENV CC_x86_64_unknown_linux_musl=musl-clang

# Musl is missing some kernel specific header files. Do symbolic links to fix
# this.
RUN \
    ln -s /usr/include/linux /opt/musl/include/ && \
    ln -s /usr/include/x86_64-linux-gnu/asm /opt/musl/include/ && \
    ln -s /usr/include/asm-generic /opt/musl/include/

RUN curl -fO https://ftp.openbsd.org/pub/OpenBSD/LibreSSL/${LIBRESSL}.tar.gz && \
    tar zxf ${LIBRESSL}.tar.gz && \
    cd ${LIBRESSL} && \
    ./configure CC=musl-clang LD=musl-clang CFLAGS="-fPIC" --prefix=/opt/libressl --enable-shared=no --sysconfdir=/etc && \
    make V=1 -j4 && make -j4 check && \
    make install

ENV X86_64_UNKNOWN_LINUX_MUSL_OPENSSL_LIB_DIR=/opt/libressl/lib
ENV X86_64_UNKNOWN_LINUX_MUSL_OPENSSL_INCLUDE_DIR=/opt/libressl/include

# cargo-outdated is innocent crate, it's just to trigger the error in build
RUN cargo install --target=$TARGET cargo-outdated

This error seem to happen with some, but not all crates. For example cargo-outdated triggers the error while linking but building bindgen works fine.

mati865 commented 5 years ago

Looks like incompatibility between musl 1.1.18 (Rust was built with this one) and 1.1.21+ probably introduced by https://git.musl-libc.org/cgit/musl/commit/?id=bf453d68393f7eea5965319e21311e56d71fa53c Nightly is using musl 1.1.22 and does not reproduce this issue.

smaeul commented 5 years ago

The problem is that you're trying to link libc.a twice: once bundled with liblibc, and once outside of rust, likely from some crate's native dependency. Can you try running this with -Z print-link-args to see why /opt/musl/lib/libc.a is getting pulled in?

mati865 commented 5 years ago

@smaeul wouldn't extra libc.a be coming from static libressl via openssl-sys crate?

smaeul commented 5 years ago

@mati865 No, libssl.a/libcrypto.a shouldn't contain definitions for any symbols from libc. And openssl-sys doesn't link libc (or liblibc), either.

oherrala commented 5 years ago

@smaeul Using the following Dockerfile I'll get the output attached: output.txt

However, since -Z print-link-args is nightly only flag, the compilation doesn't fail. But maybe this can enlighten what's happening?

FROM rust:1.35.0
#         ^-- 1.35.0 build breaks, 1.34.2 here and build is good

ENV TARGET=x86_64-unknown-linux-musl

ARG LIBRESSL=libressl-2.9.1
ARG MUSL=musl-1.1.22

ARG DEBIAN_FRONTEND=noninteractive
RUN apt -y update && \
    apt -y install clang && \
    rustup target install ${TARGET}

RUN printf '[target.x86_64-unknown-linux-musl]\nlinker = "musl-clang"\n' >/usr/local/cargo/config

WORKDIR /work

RUN curl -fO https://www.musl-libc.org/releases/${MUSL}.tar.gz && \
    tar zxf ${MUSL}.tar.gz && \
    cd ${MUSL} && \
    ./configure CC=clang CFLAGS="-fPIC" --prefix=/opt/musl --enable-shared=no && \
    make V=1 -j4 && \
    make V=1 install

ENV PATH=/opt/musl/bin:$PATH

# We do Musl build hence point to correct tool
ENV CC_x86_64_unknown_linux_musl=musl-clang

# Musl is missing some kernel specific header files. Do symbolic links to fix
# this.
RUN \
    ln -s /usr/include/linux /opt/musl/include/ && \
    ln -s /usr/include/x86_64-linux-gnu/asm /opt/musl/include/ && \
    ln -s /usr/include/asm-generic /opt/musl/include/

RUN curl -fO https://ftp.openbsd.org/pub/OpenBSD/LibreSSL/${LIBRESSL}.tar.gz && \
    tar zxf ${LIBRESSL}.tar.gz && \
    cd ${LIBRESSL} && \
    ./configure CC=musl-clang LD=musl-clang CFLAGS="-fPIC" --prefix=/opt/libressl --enable-shared=no --sysconfdir=/etc && \
    make V=1 -j4 && make -j4 check && \
    make install

ENV X86_64_UNKNOWN_LINUX_MUSL_OPENSSL_LIB_DIR=/opt/libressl/lib
ENV X86_64_UNKNOWN_LINUX_MUSL_OPENSSL_INCLUDE_DIR=/opt/libressl/include

# cargo-outdated is innocent crate, it's just to trigger the error in build
#RUN cargo install --target=$TARGET cargo-outdated

RUN rustup toolchain install nightly
RUN rustup target install --toolchain nightly ${TARGET}
WORKDIR /
RUN git clone https://github.com/kbknapp/cargo-outdated
WORKDIR /cargo-outdated
RUN cargo +nightly rustc --target ${TARGET} -- -Z print-link-args