I'm trying to build & run a small sample application that uses Folly on OS X Yosemite using GCC 4.9.3. Here's the source code:
#include <folly/AtomicHashMap.h>
int main() {
folly::AtomicHashMap<int, int> map(256);
map.insert(std::make_pair(1, 1));
return 0;
}
I built and installed both Boost (1.59.0) and Folly (latest GitHub head) from sources, making sure GCC was used, and now their libs and headers are available in /usr/local
. GCC and other dependencies were installed using MacPorts. I can build the above sample successfully using the following command line:
$ g++-mp-4.9 main.cpp -std=c++11 -I/usr/local/include -L/opt/local/lib -lfolly -lglog
However, when I try to run it, there's the following error:
$ ./a.out
dyld: Symbol not found: __ZNK5boost15program_options22error_with_option_name23substitute_placeholdersERKSs
Referenced from: /usr/local/lib/libfolly.57.dylib
Expected in: flat namespace
in /usr/local/lib/libfolly.57.dylib
Trace/BPT trap: 5
From what I understand, the way this is supposed to work is that /usr/local/lib/libfolly.57.dylib
automatically pulls in libboost_program_options.dylib
by reference at load time. I can see it listed as a dependency when I run otool -L
:
$ otool -L /usr/local/lib/libfolly.57.dylib
/usr/local/lib/libfolly.57.dylib:
/usr/local/lib/libfolly.57.dylib (compatibility version 58.0.0, current version 58.0.0)
libboost_context.dylib (compatibility version 0.0.0, current version 0.0.0)
libboost_program_options.dylib (compatibility version 0.0.0, current version 0.0.0)
...
libboost_program_options.dylib
is located in /usr/local/lib
, and if I rename it to something else, running ./a.out
causes the loader to complain about not being able to find it instead ("dyld: Library not loaded: libboost_program_options.dylib"). So it seems that the loader is able to find it, at least.
I checked the symbols exported by this library using nm -gU
:
$ nm -gU /usr/local/lib/libboost_program_options.dylib | grep program_options
...
0000000000023560 T __ZNK5boost15program_options22error_with_option_name23substitute_placeholdersERKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE
...
So there is a symbol very similar to the one that the loader complains is missing. The mangled name just has a different suffix.
[Edit: It's not very easy to see the names unless you scroll to the right, so here they are again:
nm
says the library contains __ZNK5boost15program_options22error_with_option_name23substitute_placeholdersERKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE
__ZNK5boost15program_options22error_with_option_name23substitute_placeholdersERKSs
.]I found the corresponding declaration in /usr/local/include/boost/program_options/errors.hpp
:
namespace boost { namespace program_options {
...
class BOOST_PROGRAM_OPTIONS_DECL error_with_option_name : public error {
...
protected:
...
virtual void substitute_placeholders(const std::string& error_template) const;
I presume this is the header file that Folly used when I built it because it's the only matching occurrence of substitute_placeholders
in all of /usr/include
, /usr/local/include
and /opt/local/include
. (Note that Folly doesn't even call this function directly, but it does #include <boost/program_options.hpp>
from folly/experimental/ProgramOptions.h
and use other members of boost::program_options
.)
It seems to me that the longer mangled name -- the only that's actually exported from libboost_program_options.dylib
-- is the correct one, since it includes the std::string
argument.
So what could possibly cause libfolly.57.dylib
to reference a different (shorter) mangled name instead?
Other notes:
g++-mp-4.9 main.cpp -std=c++11 -I/usr/local/include -L/opt/local/lib /usr/local/lib/libfolly.a -lglog
-- in other words, just link with Folly's static library instead -- the problem goes away, and the sample runs.Using c++filt (or http://demangler.com) to demangle the two symbols, the symbol in the boost library has a std::__1::basic_string
prefix, while the one which is missing in folly has std::string
. Some googling indicates that the __1
subnamespace is used by libc++ (clang's C++ standard library) to avoid conflicts with libstdc++ (GNU's). This indicates that boost was compiled using clang and libc++, which is default on OS X, while folly was compiled with libstdc++ (either by using g++ or specifying different flags to clang).
Since the two libraries don't have a compatible ABI, just fixing the symbol name won't help you, so your solution will have to involve recompiling either so that they both are sharing the same standard library implementation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With