hsutter / cppfront

A personal experimental C++ Syntax 2 -> Syntax 1 compiler
Other
5.4k stars 233 forks source link

[BUG] gcc-12.2 on Arch Linux does not link w/o -ltbb #158

Closed arabusov closed 1 year ago

arabusov commented 1 year ago

Describe the bug Gcc-12.2 on current Arch Linux requires the -ltbb option to link a code generated by cppfront without errors.

To Reproduce Steps to reproduce the behavior:

Sample code is provided just for an example, the behavior should be similar with any valid cpp2 code

main: () -> int = {
    words: std::vector<std::string> = (
        "one", "two", "three" );
    print_and_decorate(words[3]);
}

print_and_decorate: (thing: _) =
    std::cout << "[" << thing << "]" << std::endl;

The produced C++ code:

// ----- Cpp2 support -----
#define CPP2_USE_MODULES         Yes
#include "cpp2util.h"

#line 1 "dec.cpp2"
[[nodiscard]] auto main() -> int;
#line 7 "dec.cpp2"
auto print_and_decorate(auto const& thing) -> void;

//=== Cpp2 definitions ==========================================================

#line 1 "dec.cpp2"
[[nodiscard]] auto main() -> int{
    std::vector<std::string> words { 
        "one", "two", "three" }; 
    print_and_decorate(cpp2::assert_in_bounds(words, 3));
}

auto print_and_decorate(auto const& thing) -> void { 
    std::cout << "[" << thing << "]" << std::endl; }

Compilation goes as follows:

[cppfront]$ cppfront dec.cpp2 -p -s
dec.cpp2... ok (all Cpp2, passes safety checks)

[cppfront]$ g++ -std=c++20 -o dec dec.cpp
/usr/bin/ld: /tmp/ccInhq4C.o: in function `tbb::detail::d1::execution_slot(tbb::detail::d1::execution_data const&)':
dec.cpp:(.text._ZN3tbb6detail2d114execution_slotERKNS1_14execution_dataE[_ZN3tbb6detail2d114execution_slotERKNS1_14execution_dataE]+0x14): undefined reference to `tbb::detail::r1::execution_slot(tbb::detail::d1::execution_data const*)'
/usr/bin/ld: /tmp/ccInhq4C.o: in function `tbb::detail::d1::current_thread_index()':
dec.cpp:(.text._ZN3tbb6detail2d120current_thread_indexEv[_ZN3tbb6detail2d120current_thread_indexEv]+0xe): undefined reference to `tbb::detail::r1::execution_slot(tbb::detail::d1::execution_data const*)'
collect2: error: ld returned 1 exit status
[cppfront]$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-pc-linux-gnu/12.2.0/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: /build/gcc/src/gcc/configure --enable-languages=c,c++,ada,fortran,go,lto,objc,obj-c++,d --enable-bootstrap --prefix=/usr --libdir=/usr/lib --libexecdir=/usr/lib --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=https://bugs.archlinux.org/ --with-build-config=bootstrap-lto --with-linker-hash-style=gnu --with-system-zlib --enable-__cxa_atexit --enable-cet=auto --enable-checking=release --enable-clocale=gnu --enable-default-pie --enable-default-ssp --enable-gnu-indirect-function --enable-gnu-unique-object --enable-libstdcxx-backtrace --enable-link-serialization=1 --enable-linker-build-id --enable-lto --enable-multilib --enable-plugin --enable-shared --enable-threads=posix --disable-libssp --disable-libstdcxx-pch --disable-werror
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 12.2.0 (GCC) 

When I add the -ltbb option, Gcc-12 compiles and links the code. The binary produces the expected result:

[cppfront]$ g++ -std=c++20 -o dec dec.cpp -ltbb
[cppfront]$ ./dec 
Bounds safety violation: out of bounds access attempt detected
terminate called without an active exception
Aborted (core dumped)

A simple fix would be to point out in README that generated code needs to be linked against the TBB library if the Gcc-12 backend is used. Additionally, the TBB library should be installed in advance.

hsutter commented 1 year ago

Thanks.

generated code needs to be linked against the TBB library if the Gcc-12 backend is used. Additionally, the TBB library should be installed in advance.

That seems to be new, I haven't encountered that with g++ 10. I'm guessing TBB is Intel's TBB (Threading Building Blocks)? The generated .cpp code above should be just portable C++ code and standard library headers... shouldn't vanilla gcc 12 compile such code without also installing TBB?

I did try to reproduce this result, but haven't been able to: In Godbolt CE, I pasted the generated .cpp code above, replaced #include "cpp2util.h" with the contents of cpp2util.h, and compiled it with gcc 12.2 and trunk, and it all worked. Here's an example using gcc 12.2.

Can you make a repro that fails on Godbolt? Or could it be something about your local machine's environment, perhaps you have TBB installed and that made a change?

JohelEGP commented 1 year ago

The CE instance probably doesn't use Arch Linux.

filipsajdak commented 1 year ago

As stated here: https://github.com/wolfpld/tracy/issues/48#issuecomment-645685669

There is no (direct) dependency on TBB in Tracy. The implementation of parallel algorithms in libstdc++ depends on TBB and is horribly broken, as you need to manually link with the library. Unless you're working with an older version of libstdc++, which doesn't support parallel algorithms, in which case it's not needed. It's a mess. Just working out-of-the-box is in another castle.

Probably it is a fault of the standard library you link against.

arabusov commented 1 year ago

@filipsajdak thanks for the comment, I agree that probably the actual "bug" is on the Gcc side.

With Clang-14.0.6 everything works just fine:

[cppfront]$ cppfront dec.cpp2 -p -s
dec.cpp2... ok (all Cpp2, passes safety checks)

[cppfront]$ clang++ -o dec -std=c++20 dec.cpp
./dec[arabusov@r2-d2 cppfront]$ ./dec
Bounds safety violation: out of bounds access attempt detected
terminate called without an active exception
Aborted (core dumped)
arabusov commented 1 year ago

@hsutter thanks for your quick comment. I'm afraid (also, as @JohelEGP correctly pointed out) it is quite hard to reproduce the report because of the rolling-release nature of my host. But this might be helpful:

[cppfront]$ pacman -Q --info gcc-libs
Name            : gcc-libs
Version         : 12.2.0-1
Description     : Runtime libraries shipped by GCC
Architecture    : x86_64
URL             : https://gcc.gnu.org
Licenses        : GPL3  LGPL  FDL  custom
Groups          : None
Provides        : gcc-libs-multilib  libgo.so=21-64  libgfortran.so=5-64  libgphobos.so=3-64  libubsan.so=1-64  libasan.so=8-64  libtsan.so=2-64  liblsan.so=0-64
Depends On      : glibc>=2.27
Optional Deps   : None
Required By     : aeolus  aom  aspell  audacity  audiofile  base  blackbox  blas  box2d  brltty  brotli  carla  chromaprint  clthreads  clucene  clxclient  compiler-rt  crypto++  db
                  ddrescue  debuginfod  dosbox  double-conversion  draco  drumstick  edid-decode-git  elfutils  exempi  exiv2  fcgi  fftw  flac  fltk  fmt  gc  gcc  gdb  geos  gettext
                  glslang  gmp  gnutls  gptfdisk  graphite  groff  gtest  highway  hunspell  icu  imath  jack2  jdk-openjdk  jre-openjdk  jre-openjdk-headless  js60  js68  js78  jsoncpp
                  ladspa  libao  libb2  libbs2b  libcamera  libcdio  libde265  libebml  libelf  libftdi-compat  libgme  libimagequant  libinih  libmfx  libmodplug  libnumbertext  libopenmpt
                  libplacebo  libproxy  libptytty  libreoffice-fresh  libsbsms  libsigc++  libsoxr  libvoikko  libvpx  libwpd  libxcomp  libyuv  llvm-libs  log4cplus  lshw  luajit
                  mjpegtools  mpd  ncmpcpp  ncurses  ngspice  ninja  nlopt  ntk  openal  openmpi  p7zip  pcre  pcre2  plotutils  poppler  portaudio  portsmf  powertop  protobuf  ptex
                  pugixml  pystring  qemu-audio-dbus  qemu-block-curl  qemu-block-nfs  qemu-block-ssh  qemu-common  qemu-hw-display-qxl  qemu-hw-usb-redirect  qemu-hw-usb-smartcard  qemu-img
                  qemu-pr-helper  qemu-system-aarch64  qemu-system-alpha  qemu-system-arm  qemu-system-avr  qemu-system-cris  qemu-system-hppa  qemu-system-loongarch64  qemu-system-m68k
                  qemu-system-microblaze  qemu-system-mips  qemu-system-nios2  qemu-system-or1k  qemu-system-ppc  qemu-system-riscv  qemu-system-rx  qemu-system-s390x  qemu-system-sh4
                  qemu-system-sparc  qemu-system-tricore  qemu-system-x86  qemu-system-xtensa  qemu-tools  qemu-ui-curses  qemu-ui-dbus  qemu-ui-gtk  qemu-ui-spice-core  qemu-user
                  qemu-vhost-user-gpu  qemu-virtiofsd  qjackctl  qsynth  qtractor  ragel  rav1e  re2  rosegarden  rtosc  rubberband  shaderc  smartmontools  snappy  soundtouch  speex
                  speexdsp  spirv-tools  suil  swig  tbb  thin-provisioning-tools  unrar  v4l-utils  vamp-plugin-sdk  vid.stab  vmaf  vmpk  vtk  vulkan-validation-layers
                  webrtc-audio-processing  wine-staging  wireshark-qt  x265  xerces-c  yaml-cpp  zeromq  zimg  zita-alsa-pcmi  zita-resampler  zstd  zxing-cpp  zynaddsubfx
Optional For    : None
Conflicts With  : None
Replaces        : gcc-libs-multilib  libgphobos
Installed Size  : 137.72 MiB
Packager        : Frederik Schwan <freswa@archlinux.org>
Build Date      : Sat 20 Aug 2022 03:12:31 AM CEST
Install Date    : Fri 16 Sep 2022 10:37:39 PM CEST
Install Reason  : Installed as a dependency for another package
Install Script  : No
Validated By    : SHA-256 Sum
hsutter commented 1 year ago

OK, one last idea though:

Perhaps it might be triggered by one of the many headers that -p pulls in to simulate C++23 import std; on a compiler that doesn't support it yet. Could you try this please:

If it's just one or a few headers, and they're lesser-used headers, then I could add an #ifdef to not bring those in on GCC 12.2 in the -p simulation of #import std; on a non-C++23 compiler.

arabusov commented 1 year ago

If I remove #include <execution> from the example you've provided the code compiles:

[gcc]$ g++ -std=c++20 76.cpp -o 76.exe
[gcc]$ ./76.exe 
Bounds safety violation: out of bounds access attempt detected
terminate called without an active exception
Aborted (core dumped)

godbolt

hsutter commented 1 year ago

Aha, so <execution> is the culprit. Thanks.

I know Intel contributed the parallel algorithms a few years ago... do you remember what GCC release added the TBB dependency, was it 11? (I don't hit this in g++-10, and you're using 12.2, but I'm not sure where Intel's parallel algorithms submission was merged... let me assume it was 11 for now.)

So the #ifdef would be something like this I think:

#if defined(__GNUC__) && __GNUC__ < 11
    #include <execution>
#endif
JohelEGP commented 1 year ago

See https://github.com/hsutter/cppfront/commit/52cc059f836343b9289700486732a63128f7f472#commitcomment-92111503:

This only includes if for GCC, not exclude it for only GCC >= 11. It should be #if not defined(__GNUC__) || __GNUC__ < 11. And considering that Clang likes to pass off as GCC:

#if defined(__clang__) || not defined(__GNUC__) || __GNUC__ < 11
hsutter commented 1 year ago

@JohelEGP D'oh! Thanks, re-fixed in later commit.

@arabusov Can you confirm that this commit resolves the problem for you?

Also is __GNUC__ < 11 the right version? This probably doesn't matter since most code won't try to use <execution> but I'd like to keep the workaround as accurate as possible.

JohelEGP commented 1 year ago

Actually, the fix should be looking at libstdc++, not GCC or Clang.

hsutter commented 1 year ago

Re Clang: I've done that, but I'm actually not sure about that because this is about the standard library (not the language compiler) and Clang works with both libstd++ and libc++. Now that I'm thinking about it, probably better would be to check for libstd++ __GLIBCXX__ rather than GCC.

hsutter commented 1 year ago

Ah, racing comment! :) So what's the right version of __GLIBCXX__ to use as a cutoff, 20210101 perhaps?

JohelEGP commented 1 year ago

I gather from https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101228#c4 that it was added in version 9.1 (see https://gcc.gnu.org/onlinedocs/libstdc++/manual/status.html#status.iso.2017, "The Parallelism TS Should be Standardized", "P0024R2"). https://gcc.gnu.org/onlinedocs/gcc-4.8.5/libstdc++/manual/manual/abi.html instructs to follow https://gcc.gnu.org/develop.html#timeline for the value of __GLIBCXX__ in version 9.1. It's dated 2019-05-03, so the value should be < 20190503.

JohelEGP commented 1 year ago

The README uses GCC 10, so maybe <execution> can be unconditionally excluded for libstdc++.

arabusov commented 1 year ago

@hsutter I checked out the latest include/cpp2util.h and the link error is gone. Thank you!

hsutter commented 1 year ago

OK, I think you're right, unconditionally excluding it is best.

FWIW I'm testing with g++-10 that's the default in Ubuntu 20.04 LTS, so my guess is that they probably also install TBB and that's probably why I didn't encounter it before. But I don't want users who haven't gotten TBB automatically to have the build break problem just for the sake of a header that's rarely used.

Thanks, everyone!