Hi, On macOS, it seems that libtool's export-symbols-regex option tests the mangled names of C++ symbols against the given regex, rather than the demangled names, when deciding which symbols to export. When tested on other systems, it seems that C++ symbols are exported as expected, that is, by testing the demangled names. Here is a small project that demonstrates the problem: -----configure.ac----- AC_INIT([wat], [0]) AM_INIT_AUTOMAKE([foreign]) AC_PROG_CXX LT_INIT([disable-static]) AC_CONFIG_FILES([Makefile]) AC_OUTPUT -----Makefile.am----- lib_LTLIBRARIES = libwat.la libwat_la_LDFLAGS = $(AM_LDFLAGS) -export-symbols-regex "^[^_]" libwat_la_SOURCES = wat.cpp wat.h bin_PROGRAMS = wat wat_LDADD = libwat.la wat_SOURCES = main.cpp -----wat.cpp----- #include "wat.h" int _private(void) { return 0; } int csymbol(void) { return _private(); } int mangledsymbol(void) { return _private(); } -----wat.h----- #pragma once extern "C" int csymbol(void); int mangledsymbol(void); -----main.cpp----- #include "wat.h" int main(void) { return csymbol() + mangledsymbol(); } The expected behaviour is that the project builds with no errors when executing autoreconf -if && ./configure && make. However, on the affected system (macOS 10.13.6) this is the output of the link step: /bin/sh ./libtool --tag=CXX --mode=link g++ -g -O2 -export-symbols-regex "^[^_]" -o libwat.la -rpath /usr/local/lib wat.lo libtool: link: /usr/bin/nm -B .libs/wat.o | sed -n -e 's/^.*[ ]\([BCDEGRST][BCDEGRST]*\)[ ][ ]*_\([_A-Za-z][_A-Za-z0-9]*\)$/\1 _\2 \2/p' | sed '/ __gnu_lto/d' | /usr/bin/sed 's/.* //' | sort | uniq > .libs/libwat.exp libtool: link: /usr/bin/grep -E -e "^[^_]" ".libs/libwat.exp" > ".libs/libwat.expT" libtool: link: mv -f ".libs/libwat.expT" ".libs/libwat.exp" libtool: link: sed 's|^|_|' < .libs/libwat.exp > .libs/libwat-symbols.expsym libtool: link: g++ -dynamiclib -Wl,-undefined -Wl,dynamic_lookup -o .libs/libwat.0.dylib .libs/wat.o -g -O2 -install_name /usr/local/lib/libwat.0.dylib -compatibility_version 1 -current_version 1.0 -Wl,-single_module -Wl,-exported_symbols_list,.libs/libwat-symbols.expsym libtool: link: (cd ".libs" && rm -f "libwat.dylib" && ln -s "libwat.0.dylib" "libwat.dylib") libtool: link: ( cd ".libs" && rm -f "libwat.la" && ln -s "../libwat.la" " libwat.la" ) /bin/sh ./libtool --tag=CXX --mode=link g++ -g -O2 -o wat main.o libwat.la libtool: link: g++ -g -O2 -o .libs/wat main.o -Wl,-bind_at_load ./.libs/libwat.dylib Undefined symbols for architecture x86_64: "mangledsymbol()", referenced from: _main in main.o ld: symbol(s) not found for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation) make: *** [wat] Error 1 As you can see, mangledsymbol() is not exported, despite not beginning with an underscore and therefore matching the exported-symbols-regex. A workaround, at least for the particular name mangling scheme used by GCC and Clang, is to give ^(_Z\d+)?[^_] as the regex. With this regex, the program builds as expected, demonstrating that the mangled symbol names are tested against the regex. I'd guess that the symbols in libwat.exp should be filtered by demangled name, rather than mangled name. (Although, it looks like the list is generated using nm, so how this happens to work on systems with GNU nm, which also seems to have --no-demangle as the default, I don't know.) Here are the library's symbols according to nm: $ nm .libs/libwat.dylib 0000000000000fb0 t __Z13mangledsymbolv 0000000000000f90 t __Z8_privatev 0000000000000fa0 T _csymbol U dyld_stub_binder $ nm -demangle .libs/libwat.dylib 0000000000000fb0 t mangledsymbol() 0000000000000f90 t _private() 0000000000000fa0 T _csymbol U dyld_stub_binder Version information: $ libtool --version libtool (GNU libtool) 2.4.6 Written by Gordon Matzigkeit, 1996 Copyright (C) 2014 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. $ ld -v @(#)PROGRAM:ld PROJECT:ld64-409.12 BUILD 17:47:51 Sep 25 2018 configured to support archs: armv6 armv7 armv7s arm64 i386 x86_64 x86_64h armv6m armv7k armv7m armv7em arm64e arm64_32 LTO support using: LLVM version 10.0.0, (clang-1000.11.45.5) (static support for 21, runtime is 21) TAPI support using: Apple TAPI version 10.0.0 (tapi-1000.11.8.2) $ nm --version Apple LLVM version 10.0.0 (clang-1000.11.45.5) Optimized build. Default target: x86_64-apple-darwin17.7.0 Host CPU: broadwell Best regards, -- Philip