Summary
Building charlock_holmes 0.7.9 fails on systems with ICU 77+ because the native extension is compiled without an explicit C++ standard, and modern ICU headers now require C++17 features (std::u16string_view, std::enable_if_t, std::is_same_v, auto non-type template parameters, etc.).
Environment
- OS: Fedora 44
- Compiler: GCC 15
- ICU: 77.1 (system
libicu-devel)
- Ruby: 4.0.3
- charlock_holmes: 0.7.9
- Bundler: 2.7.2
The same issue is reproducible on any distro that has shipped libicu 76+ where the compiler / Ruby CXXFLAGS does not already default to -std=c++17 or newer.
Steps to reproduce
gem install charlock_holmes -v 0.7.9
Actual behavior
Compilation of transliterator.cpp fails with hundreds of errors originating in ICU's own headers, e.g.:
/usr/include/unicode/char16ptr.h:271:38: error: 'enable_if_t' in namespace 'std' does not name a template type
271 | template<typename T, typename = std::enable_if_t<std::is_same_v<T, UChar>>>
/usr/include/unicode/char16ptr.h:271:33: note: 'std::enable_if_t' is only available from C++14 onwards
/usr/include/unicode/unistr.h:3035:19: error: expected type-specifier
3035 | inline operator std::u16string_view() const {
/usr/include/unicode/localpointer.h:561:26: error: parameter declared 'auto'
561 | template <typename Type, auto closeFunction>
Full failure mode is make exiting with Error 1 while compiling transliterator.o.
Root cause
ICU 76 (Oct 2024) and especially ICU 77 (Mar 2025) updated their public headers to use C++17 features as part of their normal API surface — std::u16string_view, std::enable_if_t, std::is_same_v, and auto non-type template parameters. ICU's own build documentation now states it requires a C++17-capable compiler.
charlock_holmes's extconf.rb does not set -std=c++17 (or newer) in $CXXFLAGS. Because Ruby's mkmf-generated Makefile typically inherits whatever RbConfig::CONFIG['CXXFLAGS'] was set to at Ruby build time, the compiler often ends up using C++11 (or no explicit standard at all), which then can't parse the modern ICU headers.
Workaround
Setting the C++ standard explicitly via Bundler works:
bundle config build.charlock_holmes --with-cxxflags=-std=c++17
gem uninstall charlock_holmes -v 0.7.9 -I
bundle install
Or directly via gem:
gem install charlock_holmes -v 0.7.9 -- --with-cxxflags=-std=c++17
Suggested fix
Append -std=c++17 to $CXXFLAGS in ext/charlock_holmes/extconf.rb, ideally guarded so it only applies when the compiler is GCC/Clang. Something like:
$CXXFLAGS << " -std=c++17" if RbConfig::CONFIG["CXX"] =~ /g\+\+|clang\+\+/
This matches what other gems wrapping modern C++ libraries have already done.
Happy to send a PR if that approach sounds right.
Summary
Building
charlock_holmes0.7.9 fails on systems with ICU 77+ because the native extension is compiled without an explicit C++ standard, and modern ICU headers now require C++17 features (std::u16string_view,std::enable_if_t,std::is_same_v,autonon-type template parameters, etc.).Environment
libicu-devel)The same issue is reproducible on any distro that has shipped
libicu76+ where the compiler / RubyCXXFLAGSdoes not already default to-std=c++17or newer.Steps to reproduce
Actual behavior
Compilation of
transliterator.cppfails with hundreds of errors originating in ICU's own headers, e.g.:Full failure mode is
makeexiting withError 1while compilingtransliterator.o.Root cause
ICU 76 (Oct 2024) and especially ICU 77 (Mar 2025) updated their public headers to use C++17 features as part of their normal API surface —
std::u16string_view,std::enable_if_t,std::is_same_v, andautonon-type template parameters. ICU's own build documentation now states it requires a C++17-capable compiler.charlock_holmes'sextconf.rbdoes not set-std=c++17(or newer) in$CXXFLAGS. Because Ruby'smkmf-generated Makefile typically inherits whateverRbConfig::CONFIG['CXXFLAGS']was set to at Ruby build time, the compiler often ends up using C++11 (or no explicit standard at all), which then can't parse the modern ICU headers.Workaround
Setting the C++ standard explicitly via Bundler works:
Or directly via gem:
Suggested fix
Append
-std=c++17to$CXXFLAGSinext/charlock_holmes/extconf.rb, ideally guarded so it only applies when the compiler is GCC/Clang. Something like:This matches what other gems wrapping modern C++ libraries have already done.
Happy to send a PR if that approach sounds right.