[build2] Linker Error when Installing build2 on Arch Linux using GCC 10.1.0

Matthew Krupcale mkrupcale at matthewkrupcale.com
Fri May 22 00:13:25 UTC 2020


On Thu, May 21, 2020 at 4:58 PM Markus Pawellek
<markus.pawellek at mailbox.org> wrote:
>
> ld build2-0.12.0/build2/exe{b}
> /usr/bin/ld: build2-0.12.0/libbuild2/cc/libbuild2-cc-0.12-0.12.so: undefined reference to `std::unique_lock<std::shared_mutex> build2::cc::common::insert_library<build2::bin::liba>(build2::context&, build2::bin::liba*&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, butl::basic_path<char, butl::dir_path_kind<char> > const&, std::optional<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, bool, butl::diag_mark<build2::trace_mark_base>&)'

I can confirm I'm seeing these linker errors on Fedora Rawhide (and
F32) building[1] build2 v0.12.0 with GCC 10.1.1, which did not happen
on F31 with GCC 9.2.1.

When built with GCC 9, we have:

$ readelf -Ws /usr/lib64/libbuild2-cc-0.12-0.12.so | c++filt | egrep
"(Value|insert_library)"
   Num:    Value          Size Type    Bind   Vis      Ndx Name
   402: 0000000000044e40   717 FUNC    WEAK   DEFAULT   13
std::unique_lock<std::shared_mutex>
build2::cc::common::insert_library<build2::bin::libs>(build2::context&,
build2::bin::libs*&, std::__cxx11::basic_string<char,
std::char_traits<char>, std::allocator<char> > const&,
butl::basic_path<char, butl::dir_path_kind<char> > const&,
std::optional<std::__cxx11::basic_string<char, std::char_traits<char>,
std::allocator<char> > >, bool,
butl::diag_mark<build2::trace_mark_base>&)
   405: 0000000000045110   717 FUNC    WEAK   DEFAULT   13
std::unique_lock<std::shared_mutex>
build2::cc::common::insert_library<build2::bin::lib>(build2::context&,
build2::bin::lib*&, std::__cxx11::basic_string<char,
std::char_traits<char>, std::allocator<char> > const&,
butl::basic_path<char, butl::dir_path_kind<char> > const&,
std::optional<std::__cxx11::basic_string<char, std::char_traits<char>,
std::allocator<char> > >, bool,
butl::diag_mark<build2::trace_mark_base>&)
   447: 00000000000448a0   717 FUNC    WEAK   DEFAULT   13
std::unique_lock<std::shared_mutex>
build2::cc::common::insert_library<build2::bin::libi>(build2::context&,
build2::bin::libi*&, std::__cxx11::basic_string<char,
std::char_traits<char>, std::allocator<char> > const&,
butl::basic_path<char, butl::dir_path_kind<char> > const&,
std::optional<std::__cxx11::basic_string<char, std::char_traits<char>,
std::allocator<char> > >, bool,
butl::diag_mark<build2::trace_mark_base>&)
   626: 0000000000044b70   717 FUNC    WEAK   DEFAULT   13
std::unique_lock<std::shared_mutex>
build2::cc::common::insert_library<build2::bin::liba>(build2::context&,
build2::bin::liba*&, std::__cxx11::basic_string<char,
std::char_traits<char>, std::allocator<char> > const&,
butl::basic_path<char, butl::dir_path_kind<char> > const&,
std::optional<std::__cxx11::basic_string<char, std::char_traits<char>,
std::allocator<char> > >, bool,
butl::diag_mark<build2::trace_mark_base>&)

When built with GCC 10, we have:

$ readelf -Ws /var/lib/mock/fedora-32-x86_64/root/builddir/build/BUILD/build2-toolchain-0.12.0/build2-0.12.0/libbuild2/cc/libbuild2-cc-0.12-0.12.so
| c++filt | egrep "(Value|insert_library)"
   Num:    Value          Size Type    Bind   Vis      Ndx Name
    78: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND
std::unique_lock<std::shared_mutex>
build2::cc::common::insert_library<build2::bin::liba>(build2::context&,
build2::bin::liba*&, std::__cxx11::basic_string<char,
std::char_traits<char>, std::allocator<char> > const&,
butl::basic_path<char, butl::dir_path_kind<char> > const&,
std::optional<std::__cxx11::basic_string<char, std::char_traits<char>,
std::allocator<char> > >, bool,
butl::diag_mark<build2::trace_mark_base>&)
   110: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND
std::unique_lock<std::shared_mutex>
build2::cc::common::insert_library<build2::bin::libs>(build2::context&,
build2::bin::libs*&, std::__cxx11::basic_string<char,
std::char_traits<char>, std::allocator<char> > const&,
butl::basic_path<char, butl::dir_path_kind<char> > const&,
std::optional<std::__cxx11::basic_string<char, std::char_traits<char>,
std::allocator<char> > >, bool,
butl::diag_mark<build2::trace_mark_base>&)
   341: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND
std::unique_lock<std::shared_mutex>
build2::cc::common::insert_library<build2::bin::libi>(build2::context&,
build2::bin::libi*&, std::__cxx11::basic_string<char,
std::char_traits<char>, std::allocator<char> > const&,
butl::basic_path<char, butl::dir_path_kind<char> > const&,
std::optional<std::__cxx11::basic_string<char, std::char_traits<char>,
std::allocator<char> > >, bool,
butl::diag_mark<build2::trace_mark_base>&)
   Num:    Value          Size Type    Bind   Vis      Ndx Name
  1810: 00000000000bd87e     0 NOTYPE  LOCAL  HIDDEN    13
.annobin__ZN6build22cc6common14insert_libraryINS_3bin4libaEEESt11unique_lockISt12shared_mutexERNS_7contextERPT_RKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKN4butl10basic_pathIcNSL_13dir_path_kindIcEEEESt8optionalISI_EbRNSL_9diag_markINS_15trace_mark_baseEEE.isra.0.start
  1811: 00000000000bd880  1078 FUNC    LOCAL  DEFAULT   13
std::unique_lock<std::shared_mutex>
build2::cc::common::insert_library<build2::bin::liba>(build2::context&,
build2::bin::liba*&, std::__cxx11::basic_string<char,
std::char_traits<char>, std::allocator<char> > const&,
butl::basic_path<char, butl::dir_path_kind<char> > const&,
std::optional<std::__cxx11::basic_string<char, std::char_traits<char>,
std::allocator<char> > >, bool,
butl::diag_mark<build2::trace_mark_base>&) [clone .isra.0]
  1812: 000000000002cf78    58 FUNC    LOCAL  DEFAULT   13
std::unique_lock<std::shared_mutex>
build2::cc::common::insert_library<build2::bin::liba>(build2::context&,
build2::bin::liba*&, std::__cxx11::basic_string<char,
std::char_traits<char>, std::allocator<char> > const&,
butl::basic_path<char, butl::dir_path_kind<char> > const&,
std::optional<std::__cxx11::basic_string<char, std::char_traits<char>,
std::allocator<char> > >, bool,
butl::diag_mark<build2::trace_mark_base>&) [clone .isra.0] [clone
.cold]
  1813: 00000000000bdcb6     0 NOTYPE  LOCAL  HIDDEN    13
.annobin__ZN6build22cc6common14insert_libraryINS_3bin4libaEEESt11unique_lockISt12shared_mutexERNS_7contextERPT_RKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKN4butl10basic_pathIcNSL_13dir_path_kindIcEEEESt8optionalISI_EbRNSL_9diag_markINS_15trace_mark_baseEEE.isra.0.end
  1814: 00000000000bdcb6     0 NOTYPE  LOCAL  HIDDEN    13
.annobin__ZN6build22cc6common14insert_libraryINS_3bin4libsEEESt11unique_lockISt12shared_mutexERNS_7contextERPT_RKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKN4butl10basic_pathIcNSL_13dir_path_kindIcEEEESt8optionalISI_EbRNSL_9diag_markINS_15trace_mark_baseEEE.isra.0.start
  1815: 00000000000bdcc0  1078 FUNC    LOCAL  DEFAULT   13
std::unique_lock<std::shared_mutex>
build2::cc::common::insert_library<build2::bin::libs>(build2::context&,
build2::bin::libs*&, std::__cxx11::basic_string<char,
std::char_traits<char>, std::allocator<char> > const&,
butl::basic_path<char, butl::dir_path_kind<char> > const&,
std::optional<std::__cxx11::basic_string<char, std::char_traits<char>,
std::allocator<char> > >, bool,
butl::diag_mark<build2::trace_mark_base>&) [clone .isra.0]
  1816: 000000000002cfb2    58 FUNC    LOCAL  DEFAULT   13
std::unique_lock<std::shared_mutex>
build2::cc::common::insert_library<build2::bin::libs>(build2::context&,
build2::bin::libs*&, std::__cxx11::basic_string<char,
std::char_traits<char>, std::allocator<char> > const&,
butl::basic_path<char, butl::dir_path_kind<char> > const&,
std::optional<std::__cxx11::basic_string<char, std::char_traits<char>,
std::allocator<char> > >, bool,
butl::diag_mark<build2::trace_mark_base>&) [clone .isra.0] [clone
.cold]
  1817: 00000000000be0f6     0 NOTYPE  LOCAL  HIDDEN    13
.annobin__ZN6build22cc6common14insert_libraryINS_3bin4libsEEESt11unique_lockISt12shared_mutexERNS_7contextERPT_RKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKN4butl10basic_pathIcNSL_13dir_path_kindIcEEEESt8optionalISI_EbRNSL_9diag_markINS_15trace_mark_baseEEE.isra.0.end
  2443: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND
std::unique_lock<std::shared_mutex>
build2::cc::common::insert_library<build2::bin::liba>(build2::context&,
build2::bin::liba*&, std::__cxx11::basic_string<char,
std::char_traits<char>, std::allocator<char> > const&,
butl::basic_path<char, butl::dir_path_kind<char> > const&,
std::optional<std::__cxx11::basic_string<char, std::char_traits<char>,
std::allocator<char> > >, bool,
butl::diag_mark<build2::trace_mark_base>&)
  2524: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND
std::unique_lock<std::shared_mutex>
build2::cc::common::insert_library<build2::bin::libs>(build2::context&,
build2::bin::libs*&, std::__cxx11::basic_string<char,
std::char_traits<char>, std::allocator<char> > const&,
butl::basic_path<char, butl::dir_path_kind<char> > const&,
std::optional<std::__cxx11::basic_string<char, std::char_traits<char>,
std::allocator<char> > >, bool,
butl::diag_mark<build2::trace_mark_base>&)
  3139: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND
std::unique_lock<std::shared_mutex>
build2::cc::common::insert_library<build2::bin::libi>(build2::context&,
build2::bin::libi*&, std::__cxx11::basic_string<char,
std::char_traits<char>, std::allocator<char> > const&,
butl::basic_path<char, butl::dir_path_kind<char> > const&,
std::optional<std::__cxx11::basic_string<char, std::char_traits<char>,
std::allocator<char> > >, bool,
butl::diag_mark<build2::trace_mark_base>&)

That is, with GCC 9, we have 4 symbols for insert_library, all of
which are WEAK binding:

insert_library<libs>
insert_library<lib>
insert_library<libi>
insert_library<liba>

whereas with GCC 10 we have 14 symbols, 4 of which are type FUNC, and
all of which are LOCAL binding:

insert_library<liba> [clone .isra.0]
insert_library<liba> [clone .isra.0] [clone .cold]
insert_library<libs> [clone .isra.0]
insert_library<libs> [clone .isra.0] [clone .cold]

Of the remaining 10 symbols, 4 are for annobin plugin corresponding to
liba and libs functions above, and the remaining 6 are UND for liba,
libs, and libi (2 each).

These isra functions appear to be the result of IPA-SRA optimization,
which has seen changes in GCC 10[2]. Building with
config.cxx.coptions+="-fno-ipa-sra" using GCC 10 does appear to result
in the WEAK symbols like from GCC 9 and successfully links exe{b}. I'm
not sure if this is a GCC bug or an issue with how the functions are
used or defined. Perhaps it is because the return value of
insert_library is not always used in libbuild2/cc/{common,msvc}.cxx?

Matthew

[1] https://copr.fedorainfracloud.org/coprs/mkrupcale/build2/build/1401181/
[2] https://gcc.gnu.org/gcc-10/changes.html#general



More information about the users mailing list