Linker error with Boost & C++ on OSX

2019-08-16 16:19发布

问题:

I'm writing a small C++ program using Boost's 'program_options' support. The following code:

boost::program_options::options_description desc("Allowed options");
desc.add_options()
    (".refreshrate", boost::program_options::value< int >()->default_value(50), "Delay between frames")
    (".location",    boost::program_options::value<std::string>(&__Location), "Camera Location")
    (".address",     boost::program_options::value<std::string>(&__Address), "Address of Camera")
    ;
boost::program_options::variables_map vm;
boost::program_options::store(boost::program_options::parse_config_file(ifile, desc, true), vm);
boost::program_options::notify(vm);

Compiles, but won't link. I get cryptic linking errors like:

Linking CXX executable main Undefined symbols for architecture x86_64: "boost::program_options::validation_error::what() const", referenced from: vtable for boost::program_options::invalid_option_value in IEEE1394_Camera.cxx.o vtable for boost::exception_detail::clone_impl > in IEEE1394_Camera.cxx.o vtable for boost::exception_detail::error_info_injector in IEEE1394_Camera.cxx.o vtable for boost::exception_detail::clone_impl > in IEEE1394_Camera.cxx.o vtable for boost::exception_detail::error_info_injector in IEEE1394_Camera.cxx.o "boost::program_options::validation_error::validation_error(boost::program_options::validation_error::kind_t, std::basic_string, std::allocator > const&, std::basic_string, std::allocator > const&)", referenced from: std::basic_string, std::allocator > const& boost::program_options::validators::get_single_string(std::vector, std::allocator >, std::allocator, std::allocator > > > const&, bool) in IEEE1394_Camera.cxx.o (maybe you meant: boost::program_options::validation_error::validation_error(boost::program_options::validation_error::kind_t, std::basic_string, std::allocator > const&, std::basic_string, std::allocator > const&, int)) ld: symbol(s) not found for architecture x86_64 collect2: error: ld returned 1 exit status

However, simply removing the ".refreshrate" option, or changing it to a std::string instead of an int, fixes it.

I'm compiling with CMake, and I've tried Boost 1.49 and Boost 1.5 (compiled myself). I've copmiled Boost with both the darwin (default) and gcc toolchain, and using the built-in gcc4.2 and a Macports installed 4.7 . No luck.

Any ideas?

Update: Here's my full link command (from a 'make VERBOSE=1'):

"/Applications/CMake 2.8-8.app/Contents/bin/cmake" -E cmake_link_script CMakeFiles/main.dir/link.txt --verbose=1 /opt/local/bin/g++-mp-4.7 -Wl,-search_paths_first -Wl,-headerpad_max_install_names CMakeFiles/main.dir/main.cxx.o -o main /Users/rhand/Development/boost-1.50/install/lib/libboost_program_options.a /Users/rhand/Development/boost-1.50/install/lib/libboost_timer.a /Users/rhand/Development/boost-1.50/install/lib/libboost_chrono.a /Users/rhand/Development/boost-1.50/install/lib/libboost_system.a /Users/rhand/Development/boost-1.50/install/lib/libboost_exception.a

回答1:

Ok, I figured this out, although I'm still a bit fuzzy as to the details.

I wiped everything out, went back to the stock gcc4.2 from XCode and rebuilt Boost using this command:

./b2 --prefix=/Users/rhand/Development/boost-1.50/install/ --layout=versioned --build-type=complete variant=release link=shared runtime-link=shared threading=single install

Then, I had to modify some things in my CMake build to get it to link properly:

set(Boost_COMPILER "-xgcc42")

and Set some environment variables:

BOOSTROOT=/Users/rhand/Development/boost-1.50/install/
BOOST_INCLUDEDIR=/Users/rhand/Development/boost-1.50/install/include/boost-1_50/
BOOST_LIBRARYDIR=/Users/rhand/Development/boost-1.50/install/lib

And then, everything works. I'm not exactly sure what the problem was, unless it's something special in specifying a Release build or going with all shared libraries...