Skip to content

zig c++ errors with boostΒ #18770

Open
Open

Description

@marchelbling-aqemia

Zig Version

0.12.0-dev.2341+92211135f

Steps to Reproduce and Observed Behavior

I am trying to build some scientific tooling using zig so that I can have static binaries for a couple of architectures (and I'm pretty excited about zig for this!).

I am using the following Dockerfile [updated]:

# Usage: docker build -t smina:latest .

FROM debian:bullseye-slim as build
ARG BOOST_VERSION=1.75.0
ARG BESSENTIAL_VERSION=12.9
ARG OPENBABEL_VERSION=3.1.1
ARG EIGEN3_VERSION=3.3.9-2
ARG ZSTD_VERSION=v1.5.5
ARG ZLIB_VERSION=1.3.1
ARG SMINA_TAG=7369fc0
ARG ZIG_VERSION=0.12.0-dev.2341+92211135f
ARG ZIG_TARGET="x86_64-linux-gnu"
ENV DEBIAN_FRONTEND noninteractive


RUN mkdir /src \
 && apt-get update \
 && apt-get upgrade -y \
 && apt-get install -y -q \
        git \
        build-essential=${BESSENTIAL_VERSION} \
        cmake \
        cmake-curses-gui \
        wget \
        neovim \
        libeigen3-dev=${EIGEN3_VERSION}


WORKDIR /src
RUN git clone --recursive --depth 1 --branch "${ZSTD_VERSION}" https://github.com/facebook/zstd \
 && wget https://www.zlib.net/zlib-${ZLIB_VERSION}.tar.gz && tar -xf zlib-${ZLIB_VERSION}.tar.gz && mv zlib-${ZLIB_VERSION} zlib \
 && git clone --recursive --depth 1 --branch "boost-${BOOST_VERSION}" https://github.com/boostorg/boost \
 && git clone --depth 1 --branch "openbabel-$( echo ${OPENBABEL_VERSION} | tr '.' '-' )" https://github.com/openbabel/openbabel \
 && git clone --depth 1 git://git.code.sf.net/p/smina/code smina

WORKDIR /src
RUN wget https://ziglang.org/builds/zig-linux-$(uname -m)-${ZIG_VERSION}.tar.xz \
 && tar -xf zig-linux-$(uname -m)-${ZIG_VERSION}.tar.xz \
 && rm zig-linux-$(uname -m)-${ZIG_VERSION}.tar.xz \
 && mv zig-linux-$(uname -m)-${ZIG_VERSION} zig-${ZIG_VERSION}

ENV PATH "${PATH}:/src/zig-${ZIG_VERSION}"
ENV CC "zig cc -pthread -target ${ZIG_TARGET}"
ENV CXX "zig c++ -pthread -target ${ZIG_TARGET}"


WORKDIR /src/zstd
RUN mkdir tmp && cd tmp \
 && cmake \
        -DCMAKE_BUILD_TYPE=Release \
        -DBUILD_SHARED=OFF \
        -DCMAKE_INSTALL_PREFIX=/usr/local \
        -DCMAKE_POSITION_INDEPENDENT_CODE=ON \
    ../build/cmake \
 && make -j8 install


WORKDIR /src/zlib
RUN mkdir build && cd build \
 && cmake \
        -DCMAKE_BUILD_TYPE=Release \
        -DBUILD_SHARED=OFF \
        -DCMAKE_INSTALL_PREFIX=/usr/local \
        -DCMAKE_POSITION_INDEPENDENT_CODE=ON \
    .. \
 && make -j8 install


WORKDIR /src/boost
RUN ./bootstrap.sh --prefix=/usr/local --with-libraries=iostreams,timer,system,regex,thread,serialization,filesystem,program_options,date_time \
 && ./b2 variant=release link=static runtime-link=static install


WORKDIR /src/openbabel
RUN mkdir build && cd build \
 && cmake \
        -DBUILD_SHARED=OFF \
        -DCMAKE_INSTALL_PREFIX=/usr/local \
        -DCMAKE_POSITION_INDEPENDENT_CODE=ON \
        # note: we fake PTHREAD_LIBRARY that will handled by the compiler correctly \
        -DPTHREAD_LIBRARY=/usr/local/lib \
    .. \
 && make -j8 install


WORKDIR /src/smina
RUN mkdir build && cd build \
 && sed -i "s/\bunordered_map</boost::unordered_map</" ../src/lib/CommandLine2/CommandLine.cpp \
 && cmake \
        -DCMAKE_BUILD_TYPE=Release \
        -DBUILD_SHARED_LIBS=OFF \
        -DCMAKE_POSITION_INDEPENDENT_CODE=ON \
        -DBoost_INCLUDE_DIR=/usr/local/include \
        -DBoost_LIBRARY_DIR_RELEASE=/usr/local/lib \
        -DBOOST_TIMER_ENABLE_DEPRECATED=ON \
        -DBoost_USE_STATIC_LIBS=ON \
        -DOPENBABEL3_INCLUDE_DIR=/usr/local/include/openbabel3 \
        -DOPENBABEL3_LIBRARIES='/usr/local/lib/libopenbabel.a;/usr/local/lib/libz.a;/usr/local/lib/libzstd.a' \
    .. \
  && make smina -j8
  1. if I don't add the sed replacement before the last cmake, the compilation fails with zig (gcc (Debian 10.2.1-6) 10.2.1 20210110 compiles just fine)
/src/smina/src/lib/CommandLine2/CommandLine.cpp:1089:10: error: reference to 'unordered_map' is ambiguous
 1089 |     for (unordered_map<string, Option*>::iterator I = OptMap.begin(), E = OptMap.end();

Looking at the source (link), since <unordered_map> is not included, I would not expect the compiler to fail here, even if the code is

using namespace std;
using namespace boost;
  1. with the sed replacement, compilation works fine however the linker fails:
101.2 [100%] Linking CXX executable smina
102.2 ld.lld: error: undefined symbol: boost::program_options::option_description::long_name() const
102.2 >>> referenced by main.cpp:514 (/src/smina/src/main/main.cpp:514)
102.2 >>>               CMakeFiles/smina.dir/src/main/main.cpp.o:(get_occurrence(boost::program_options::variables_map&, boost::program_options::options_description&))
102.2 >>> referenced by main.cpp:531 (/src/smina/src/main/main.cpp:531)
102.2 >>>               CMakeFiles/smina.dir/src/main/main.cpp.o:(check_occurrence(boost::program_options::variables_map&, boost::program_options::options_description&))
102.2
...
102.2 ld.lld: error: undefined symbol: std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>::_M_create(unsigned long&, unsigned long)
102.2 >>> referenced by chrono.cpp
102.2 >>>               chrono.o:(boost::wrapexcept<boost::system::system_error>::clone() const) in archive /usr/local/lib/libboost_chrono.a
102.2 >>> referenced by chrono.cpp
102.2 >>>               chrono.o:(boost::wrapexcept<boost::system::system_error>::wrapexcept(boost::wrapexcept<boost::system::system_error> const&)) in archive /usr/local/lib/libboost_chrono.a
102.2 >>> referenced by convert.cpp
102.2 >>>               convert.o:(boost::program_options::to_internal(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&)) in archive /usr/local/lib/libboost_program_options.a
102.2 >>> referenced 202 more times
...

Expected Behavior

When relying on gcc (i.e. after removing the following lines:)

ENV PATH "${PATH}:/zig-${ZIG_VERSION}"
ENV CC "zig cc -pthread -target ${ZIG_TARGET}"
ENV CXX "zig c++ -pthread -target ${ZIG_TARGET}"

the build succeeds.

It seems that both issues somehow relate to the use of boost. I may be missing something obvious however I would expect that zig cc and zig c++ could be used as drop in replacements for gcc.

Activity

  1. added
    bugObserved behavior contradicts documented or intended behavior
    on Jan 31, 2024
  2. mikdusan commented on Feb 1, 2024

    @mikdusan
    Member

    Looking at the source since <unordered_map> is not included, I would not expect the compiler to fail here

    It's included (implicitly) somewhere, maybe even by libc++ implementation, otherwise the ambiguity error wouldn't present. This is probably explained by a difference between libc++ vs libstdc++ .

    however the linker fails:

    It's been a while since I used Dockerfile but what are you doing here? Earlier the versions are defined, and then just before they are used, the values get undefined? Dockerfile fails because clone command lines have empty arguments.

    ARG ZSTD_VERSION
    ARG ZLIB_VERSION
    ARG BOOST_VERSION
    ARG OPENBABEL_VERSION
    WORKDIR /src
    RUN git clone ........
    

    here too:

    ARG ZIG_ARCH
    ARG ZIG_VERSION
    WORKDIR /src
    RUN wget https://ziglang.org/builds/zig-linux-$(uname -m)-${ZIG_VERSION}.tar.xz \
     && tar -xf zig-linux-$(uname -m)-${ZIG_VERSION}.tar.xz \
     && rm zig-linux-$(uname -m)-${ZIG_VERSION}.tar.xz \
     && mv zig-linux-$(uname -m)-${ZIG_VERSION} zig-${ZIG_VERSION}
    
    ARG ZIG_VERSION
    ARG ZIG_TARGET
    ENV PATH "${PATH}:/src/zig-${ZIG_VERSION}"
    ENV CC "zig cc -pthread -target ${ZIG_TARGET}"
    ENV CXX "zig c++ -pthread -target ${ZIG_TARGET}"
    

    ... if that all works out, it may help if you provide the verbose link command line that is failing.

  3. marchelbling-aqemia commented on Feb 1, 2024

    @marchelbling-aqemia
    Author

    Thank you for the quick reply @mikdusan!

    It's included (implicitly) somewhere, maybe even by libc++ implementation, otherwise the ambiguity error wouldn't present. This is probably explained by a difference between libc++ vs libstdc++ .

    It's been a while since I dealt with C++. I thought that libc++ and libstdc++ should be pretty much entirely interchangeable so I would have expected that headers "layout" would be compatible and only actual implementation details would change.

    Earlier the versions are defined, and then just before they are used, the values get undefined? Dockerfile fails because clone command lines have empty arguments.

    Sorry, you are right that the ARGs do not have to be repeated (I believe that should not have been an issue, as the first occurrence provides the default value, at least it was not causing docker build issues on my end).
    I changed my actual Dockerfile before posting to ease testing and improve layers caching as the whole build is somewhat lengthy, sorry about that.
    I've updated the Dockerfile in my initial message for better readibility.

    The issue(s) I have both are in the last build (following WORKDIR /src/smina). The cmake call is fine and it's the make smina call that fails.

    All the other programs before (zstd, zlib, boost, openbabel) compile/link just fine with zig.

  4. mikdusan commented on Feb 1, 2024

    @mikdusan
    Member

    The issue(s) I have both are in the last build

    The boost build process does not respect env vars CC or CXX. You'll have to find another way to override which compiler boost selects. The link is currently failing because gcc was used to build boost.

    One way would be to create bin/ path and create your own { cc, c++ } or { gcc, g++ } shell scripts which call zig.

    Another way is the following snippet, create a user config file for boost b2; but this only gets me so far. It seems to break down not building iostreams with zlib extensions, maybe it can't find zlib? Or maybe it's a clang thing.

    As an aside, I ended up with using gcc instead of using clang because b2 inserts a --target command line option, and it doesn't match zig's target spec, causing error. I'm unaware of how to disable or override that.

    WORKDIR /src/boost
    RUN ./bootstrap.sh --prefix=/usr/local --with-libraries=iostreams,timer,system,regex,thread,serialization,filesystem,program_options,date_time \
     && echo "using gcc : : ${CXX} ;" > zig.jam \
     && ./b2 --user-config=zig.jam variant=release link=static runtime-link=static install
    
  5. marchelbling-aqemia commented on Feb 2, 2024

    @marchelbling-aqemia
    Author

    Thank you very much for following up!
    I clearly overlooked boost compilation configuration. I'll have to tinker with your inputs and other resources to make this work. Is it okay to let this issue open until I (or someone else) come up with a working solution to compile boost with zig?
    Anyway, definitively not a zig bug!

  6. marchelbling-aqemia commented on Jun 18, 2024

    @marchelbling-aqemia
    Author

    Alright, I have been back at this and made some progress:

    FROM debian:bullseye-slim as build
    ARG BESSENTIAL_VERSION=12.9
    ARG BOOST_VERSION=1.75.0
    ARG OPENBABEL_VERSION=3.1.1
    ARG EIGEN3_VERSION=3.3.9-2
    ARG ZSTD_VERSION=v1.5.5
    ARG ZLIB_VERSION=1.3.1
    ARG SMINA_TAG=7369fc0
    ARG ZIG_VERSION=0.13.0
    ARG ZIG_TARGET="x86_64-linux-gnu"
    ENV DEBIAN_FRONTEND noninteractive
    
    
    RUN mkdir /src \
     && apt-get update \
     && apt-get upgrade -y \
     && apt-get install -y -q \
            git \
            build-essential=${BESSENTIAL_VERSION} \
            cmake \
            cmake-curses-gui \
            wget \
            libeigen3-dev=${EIGEN3_VERSION}
    
    
    WORKDIR /src
    RUN git clone --recursive --depth 1 --branch "${ZSTD_VERSION}" https://github.com/facebook/zstd \
     && wget https://www.zlib.net/zlib-${ZLIB_VERSION}.tar.gz && tar -xf zlib-${ZLIB_VERSION}.tar.gz && mv zlib-${ZLIB_VERSION} zlib \
     && git clone --recursive --depth 1 --branch "boost-${BOOST_VERSION}" https://github.com/boostorg/boost \
     && git clone --depth 1 --branch "openbabel-$( echo ${OPENBABEL_VERSION} | tr '.' '-' )" https://github.com/openbabel/openbabel \
     && git clone --depth 1 git://git.code.sf.net/p/smina/code smina
    
    WORKDIR /src
    RUN wget https://ziglang.org/download/${ZIG_VERSION}/zig-linux-$(uname -m)-${ZIG_VERSION}.tar.xz \
     && tar -xf zig-linux-$(uname -m)-${ZIG_VERSION}.tar.xz \
     && rm zig-linux-$(uname -m)-${ZIG_VERSION}.tar.xz \
     && mv zig-linux-$(uname -m)-${ZIG_VERSION} zig-${ZIG_VERSION}
    
    ENV PATH "${PATH}:/src/zig-${ZIG_VERSION}"
    ENV CC "zig cc -pthread -target ${ZIG_TARGET}"
    ENV CXX "zig c++ -std=c++11 -pthread -target ${ZIG_TARGET} -Wno-deprecated-declarations -I/src/zig-0.13.0/lib/libcxx/include/"
    
    WORKDIR /src/zstd
    RUN mkdir tmp && cd tmp \
     && cmake \
            -DCMAKE_BUILD_TYPE=Release \
            -DBUILD_SHARED=OFF \
            -DCMAKE_INSTALL_PREFIX=/usr/local \
        ../build/cmake \
     && make -j8 install
    
    
    WORKDIR /src/zlib
    RUN mkdir build && cd build \
     && cmake \
            -DCMAKE_BUILD_TYPE=Release \
            -DBUILD_SHARED=OFF \
            -DCMAKE_INSTALL_PREFIX=/usr/local \
        .. \
     && make -j8 install
    
    
    WORKDIR /src/boost
    RUN echo "using clang : zig++ : ${CXX} ;" >> user-config.jam \
     && echo "using zlib : ${ZLIB_VERSION} : <include>\"/usr/local/include\" <search>\"/usr/local/lib\" ;" >> user-config.jam \
     && ./bootstrap.sh --prefix=/usr/local --with-libraries=atomic,iostreams,timer,system,regex,thread,serialization,filesystem,program_options,date_time \
     && ./b2 --user-config=user-config.jam variant=release link=static runtime-link=static install
    
    
    WORKDIR /src/openbabel
    RUN mkdir build && cd build \
     && cmake \
            -DBUILD_SHARED=OFF \
            -DCMAKE_INSTALL_PREFIX=/usr/local \
            -DCMAKE_FIND_LIBRARY_SUFFIXES=".a" \
            # note: we fake PTHREAD_LIBRARY that will handled by the compiler correctly \
            -DPTHREAD_LIBRARY=/usr/local/lib \
        .. \
     && make -j8 install
    
    
    WORKDIR /src/smina
    RUN mkdir build && cd build \
     && sed -i "s/\bunordered_map</boost::unordered_map</" ../src/lib/CommandLine2/CommandLine.cpp \
     && sed -i "s/filesystem::/boost::filesystem::/g" ../src/lib/CommandLine2/CommandLine.cpp \
     && cmake \
            -DCMAKE_BUILD_TYPE=Release \
            -DBUILD_SHARED_LIBS=OFF \
            -DBoost_INCLUDE_DIR=/usr/local/include \
            -DBoost_LIBRARY_DIR_RELEASE=/usr/local/lib \
            -DBOOST_TIMER_ENABLE_DEPRECATED=ON \
            -DBoost_USE_STATIC_LIBS=ON \
            -DOPENBABEL3_INCLUDE_DIR=/usr/local/include/openbabel3 \
            -DOPENBABEL3_LIBRARIES='/usr/local/lib/libopenbabel.a;/usr/local/lib/libz.a;/usr/local/lib/libzstd.a' \
        .. \
      && make smina -j8
    

    The issue with boost was that some headers were not found and then boost 1.75 leverages std::unary_function which is deprecated and both problems seems fixable by updating CXX.

    This script now terminates without errors. However the binaries are not fully static for a reason that I don't understand

    $ docker run --rm -t my_image:latest bash -c 'echo "smina: $(ldd /src/smina/build/smina)"; echo "obabel: $(ldd /src/openbabel/build/bin/obabel)"'
    smina:  linux-vdso.so.1 (0x00007fff22787000)
            libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x000079645392c000)
            libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x000079645390a000)
            libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x0000796453736000)
            libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x0000796453730000)
            /lib64/ld-linux-x86-64.so.2 (0x0000796453a76000)
    obabel:         linux-vdso.so.1 (0x00007fffd8f76000)
            libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x000078428278a000)
            libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x0000784282768000)
            libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x0000784282594000)
            libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x000078428258e000)
            /lib64/ld-linux-x86-64.so.2 (0x00007842828d4000)
    

    I am probably missing something obvious here.

  7. added this to the unplanned milestone on Aug 13, 2024
  8. kassane commented on Aug 30, 2024

    @kassane
    Contributor

    Hi @marchelbling-aqemia,

    I don't know if you've tried using build.zig. If it's feasible, I'd like to hear your feedback.

    https://github.com/allyourcodebase/boost-libraries-zig

  9. marchelbling-aqemia commented on Sep 2, 2024

    @marchelbling-aqemia
    Author

    @kassane I did not. Tbh, I didn't find many resources on using build.zig for non-Zig code and I didn't want to introduce a new "language" (vs just a compiler) at my workplace.
    Now that sounds like something I could give it a try on my free time, thank you for suggesting and making this project. I'll let you know how it goes!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugObserved behavior contradicts documented or intended behavior

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions