Skip to content

[BUG] Failure to compile when using libc++ rather than libstdc++ #663

Closed

Description

@0x6e6174

Describe the bug
ncmpcpp fails to compile when CXXFLAGS include -stdlib=libc++ with both clang and gcc.

To Reproduce
Steps to reproduce the behavior:

  • on a gentoo system with an llvm profile:

    1. emerge ncmpcpp
  • on any system:

    1. git clone https://github.com/ncmpcpp/ncmpcpp.git
    2. cd ncmpcpp
    3. autoreconf
    4. ./configure CXX=clang++ LD=ld.lld (or CXX=g++, LD=ld.bfd)
    5. sed -i 's/^CXXFLAGS = /CXXFLAGS = -stdlib=libc++ /' Makefile src/Makefile
      For some reason (at least on my system), setting CXXFLAGS in the cmdline of ./configure results in configure failing to find boost libs, even when --with-boost=$BOOST_PATH. No idea what is going on with that, and it wasn't particularly related to the problem. Accordingly I just ran the Makefiles configure generates through sed.
    6. make -j$(nproc)

Expected behavior
ncmpcpp compiles.

Screenshots/Logs
attached are the outputs of make(1) compiling against libc++ with gcc and clang.

gcc-bfd-libc++.log

clang-lld-libc++.log

Desktop (please complete the following information):

  • OS: gentoo on default/linux/amd64/23.0/split-usr/musl/llvm profile
  • Terminal: N/A
  • Version: HEAD, 0.10.1

I reproduced the same issue on another gentoo system, this one using a normal glibc/gcc profile. Because the issue is compiler/STL specific, I of course had libc++ installed on the reproducing system and was using that with clang, but that I reproduced this on a more normal system demonstrates that the issue isn't caused from some weirdness arising from musl or something like that.

Additional context
For some reason, the following patch makes ncmpcpp compile properly with libc++ with clang. It still fails to build with gcc (due to all the -Wtemplate-body errors), but all the weird type errors about iterators and LocaleBasedSorting are no longer present.

diff --git a/src/screens/sel_items_adder.cpp b/src/screens/sel_items_adder.cpp
index e48eeac6..469aba0a 100644
--- a/src/screens/sel_items_adder.cpp
+++ b/src/screens/sel_items_adder.cpp
@@ -253,7 +253,7 @@ void SelectedItemsAdder::populatePlaylistSelector(BaseScreen *old_screen)
 				std::bind(&Self::addToExistingPlaylist, this, it->path())
 			));
 		};
-		std::sort(m_playlist_selector.beginV()+begin, m_playlist_selector.endV(),
+		std::stable_sort(m_playlist_selector.beginV()+begin, m_playlist_selector.endV(),
 			LocaleBasedSorting(std::locale(), Config.ignore_leading_the));
 		if (begin < m_playlist_selector.size())
 			m_playlist_selector.addSeparator();

I am not a C++ programmer (I just like messing with, finding novel ways to break computers), so I am not really sure what is going on here. I'm not convinced that this is a bug with ncmpcpp (it seems more likely that this is a bug in libc++? Why on earth would std::stable_sort() accept iterators that std::sort() doesn't? I don't know, I'm not a C++ programmer), so I don't expect this to be fixed here and will be submitting this to gentoo's bugtracker when I can get to it also. That in mind, this is the only program I have had issue with thus far when building things against libc++ instead of libstdc++, so I'm curious for any insight anyone here may have.

Activity

  1. namtsui commented on Aug 27, 2026

    @namtsui

    I am seeing this in openbsd when compiling ncmpcpp against a test update to libcxx22 (19.1.7 --> 22.1.6)

  2. namtsui commented on Aug 27, 2026

    @namtsui

    Patching /usr/include/c++/v1/__algorithm/sift_down.h as a crude hack, to be more similar to 19.1.7, worked. I had a theory that there was something wrong with the brackets operator because there were errors such as:

    /usr/include/c++/v1/__algorithm/sift_down.h:49:39: error: no matching function for call to object of type 'LocaleBasedSorting'
       49 |   } else if ((__child + 1) < __len && __comp(__first[__child], __first[__child + 1])) {
          |                                       ^~~~~~
    
    ...
    
    screens/sel_items_adder.cpp:256:8: note: in instantiation of function template specialization 'std::sort<boost::iterato
    rs::transform_iterator<NC::Menu<RunnableItem<std::string, void ()>>::Item::ExtractValue<Const::No>, std::__wrap_iter<NC
    ::Menu<RunnableItem<std::string, void ()>>::Item *>>, LocaleBasedSorting>' requested here
      256 |                 std::sort(m_playlist_selector.beginV()+begin, m_playlist_selector.endV(),
          |                      ^
    ./utility/comparators.h:56:7: note: candidate function not viable: no known conversion from 'operator_brackets_proxy<bo
    ost::iterators::transform_iterator<NC::Menu<RunnableItem<std::string, void ()>>::Item::ExtractValue<Const::No>, std::__
    wrap_iter<NC::Menu<RunnableItem<std::string, void ()>>::Item *>, boost::use_default, boost::use_default>>' to 'const st
    d::string' (aka 'const basic_string<char>') for 1st argument
       56 |         bool operator()(const std::string &a, const std::string &b) const {
          |              ^          ~~~~~~~~~~~~~~~~~~~~
    

    I'll keep poking around at LocaleBasedSorting in src/utility/comparators.h or maybe boost::iterators::transform_iterator. Maybe they have some relationship with the brackets operator.

    build log:
    build_log.txt

    /usr/include/c++/v1/__algorithm/sift_down.h:

    --- sift_down.h.orig    Thu Aug 27 00:35:48 2026
    +++ sift_down.h Thu Aug 27 00:58:02 2026
    @@ -45,14 +45,14 @@
     
       if _LIBCPP_CONSTEXPR (__assume_both_children) {
         // right-child exists and is greater than left-child
    -    __child += __comp(__first[__child], __first[__child + 1]);
    -  } else if ((__child + 1) < __len && __comp(__first[__child], __first[__child + 1])) {
    +    __child += __comp(*(__first + __child), *(__first + __child + 1));
    +  } else if ((__child + 1) < __len && __comp(*(__first + __child), *(__first + __child + 1))) {
         // right-child exists and is greater than left-child
         ++__child;
       }
     
       // check if we are in heap-order
    -  if (__comp(__first[__child], __first[__start]))
    +  if (__comp(*(__first + __child), *(__first + __start)))
         // we are, __start is larger than its largest child
         return;
     
    @@ -69,14 +69,14 @@
         __child = 2 * __child + 1;
     
         if _LIBCPP_CONSTEXPR (__assume_both_children) {
    -      __child += __comp(__first[__child], __first[__child + 1]);
    -    } else if ((__child + 1) < __len && __comp(__first[__child], __first[__child + 1])) {
    +      __child += __comp(*(__first + __child), *(__first + __child + 1));
    +    } else if ((__child + 1) < __len && __comp(*(__first + __child), *(__first + __child + 1))) {
           // right-child exists and is greater than left-child
           ++__child;
         }
     
         // check if we are in heap-order
    -  } while (!__comp(__first[__child], __top));
    +  } while (!__comp(*(__first + __child), __top));
       __first[__start] = std::move(__top);
    
  3. added a commit that references this issue on Sep 14, 2026
    10718bb
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

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions