I am trying to create and run a small sample application that uses Folly on OS X Yosemite using GCC 4.9.3. Here is 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 sources (1.59.0) and Folly (the last GitHub head) from sources, making sure GCC was used, and now their libraries and headers are available in /usr/local . GCC and other dependencies were installed using MacPorts. I can build the above selection 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 start it, the following error appears:
$ ./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 should work is that /usr/local/lib/libfolly.57.dylib automatically pulls libboost_program_options.dylib from the link at boot time. I see that it is 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 bootloader to complain that it cannot find it ("dyld: library not loaded: libboost_program_options .dylib "). It looks like the bootloader can find it, at least.
I checked the characters 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 character very similar to the one the bootloader complains about. The distorted name has a different suffix.
[ Edit: It is not very easy to see the names unless you scroll them to the right, so here they are again:
nm says the library contains __ZNK5boost15program_options22error_with_option_name23substitute_placeholdersERKNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE- "Missing character" at boot time
__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 assume this is the header file that Folly used when I built it, because it is the only matching occurrence of substitute_placeholders in all /usr/include , /usr/local/include and /opt/local/include . (Note that Folly does not even call this function directly, but it is #include <boost/program_options.hpp> from folly/experimental/ProgramOptions.h and uses other boost::program_options members.)
It seems to me that the longer distorted name - the only one actually exported from libboost_program_options.dylib - is correct, since it includes the std::string argument.
So, what could cause libfolly.57.dylib refer to another (shorter) malformed name?
Other notes:
- I originally installed Boost from MacPorts instead of creating it from sources, and this led to the same error.
- If I build the sample using
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 to the Folly static library instead - the problem goes away and the sample starts.