12

I'm trying to use homebrew to download and build packages like boost, ceres-solver, stuff like that. What happens is that I will try and compile code, without any special flags (g++ foo.cpp -o foo -I /usr/local/... and I've tried clang++ too) and I get this error consistently:

Undefined symbols for architecture x86_64:
  ...
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

So I looked around and the solution is to use the -stdlib=libstdc++ flag. I tried it, and now it gives me errors related to the fact that apple ships an old version of the libstdc++, doesn't get fixed by invoking -std=c++11 or -std=c++14. It throws up objections to C++11 syntax like the shared_ptr:

/usr/local/include/ceres/internal/port.h:62:12: error: no member named
      'shared_ptr' in namespace 'std'
using std::shared_ptr;
      ~~~~~^
...
/usr/local/include/ceres/solver.h:629:15: error: expected member name or ';'
      after declaration specifiers
    shared_ptr<ParameterBlockOrdering> inner_iteration_ordering;
    ~~~~~~~~~~^
5 errors generated.

I'd rather not edit the library source code if I don't have to, I'd hope the devs have done a pretty good job?

Is there a way to build libraries (with or without homebrew) that will give the correct linking? Currently I just brew install <package> am I missing something obvious? Or am I screwing something up when I compile the code itself?

I'm on Mac OS X 10.10.5, and brew --config gives this:

HOMEBREW_VERSION: 0.9.5
ORIGIN: https://github.com/Homebrew/homebrew
HEAD: 03ad27453de01adc29cbf941bd29a2dfb54a9960
Last commit: 69 minutes ago
HOMEBREW_PREFIX: /usr/local
HOMEBREW_REPOSITORY: /usr/local
HOMEBREW_CELLAR: /usr/local/Cellar
HOMEBREW_BOTTLE_DOMAIN: https://homebrew.bintray.com
CPU: 8-core 64-bit ivybridge
OS X: 10.10.5-x86_64
Xcode: 6.4
CLT: 6.4.0.0.1.1435007323
Clang: 6.1 build 602
X11: N/A
System Ruby: 2.0.0-p481
Perl: /usr/bin/perl
Python: /usr/local/bin/python => /Library/Frameworks/Python.framework/Versions/2.7/bin/python2.7
Ruby: /usr/bin/ruby
Java: N/A

Running $arch gives: i386

and $clang++ -v gives:

Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn)
Target: x86_64-apple-darwin14.5.0
Thread model: posix

I should add that I've tried cleaning out my computer in case there was an old version or something mucking things up. Everything I've seen says this error is caused by improper linking at build time, but it seems like brew does most of that properly, at least as far as I can tell? Everything installs and builds fine.

I've installed gcc using brew and tried to compile the library using the g++-5 and the gcc-5 command to avoid clang and I get the same problem when I try to pass the -std=c++11 flag at compile time - g++-5 foo.cpp -o foo -I /usr/local/bar -std=c++11. None of these work.

I should also emphasize that these happen when I try to compile and run the example scripts that come with, for example, boost, not even my own scripts. I'm just sort of hoping that the libraries are at least mostly correct.

I've also looked at a lot of similar questions here, many are unanswered and the ones that have solutions, well, I've tried many of the solutions and they don't help either. I've tried -lstdc++.6, I've tried -stdlib=libstdc++. The -l doesn't change anything, the -stdlib causes the issues I described above.

Any help I can get would be great, I've been working on this for weeks now and it's driving me nuts.

Quick Edit for clarity:

So when I input:

$g++ cerestest.cpp -o ceres -I /usr/local/include/eigen3

or

$clang++ cerestest.cpp -o ceres -I /usr/local/include/eigen3

I get:

Undefined symbols for architecture x86_64:
  "ceres::Solve(ceres::Solver::Options const&, ceres::Problem*, ceres::Solver::Summary*)", referenced from:
      _main in cerestest-ef733e.o
  "ceres::Solver::Summary::Summary()", referenced from:
      _main in cerestest-ef733e.o
  "ceres::Problem::AddResidualBlock(ceres::CostFunction*, ceres::LossFunction*, double*)", referenced from:
      _main in cerestest-ef733e.o
  "ceres::Problem::Problem()", referenced from:
      _main in cerestest-ef733e.o
  "ceres::Problem::~Problem()", referenced from:
      _main in cerestest-ef733e.o
  "google::LogMessage::stream()", referenced from:
      ceres::AutoDiffCostFunction<CostFunctor, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0>::AutoDiffCostFunction(CostFunctor*) in cerestest-ef733e.o
      ceres::internal::AutoDiff<CostFunctor, double, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0>::Differentiate(CostFunctor const&, double const* const*, int, double*, double**) in cerestest-ef733e.o
      void ceres::internal::Make1stOrderPerturbation<ceres::Jet<double, 1>, double, 1>(int, double const*, ceres::Jet<double, 1>*) in cerestest-ef733e.o
      void ceres::internal::Take0thOrderPart<ceres::Jet<double, 1>, double*>(int, ceres::Jet<double, 1> const*, double*) in cerestest-ef733e.o
      void ceres::internal::Take1stOrderPart<ceres::Jet<double, 1>, double, 0, 1>(int, ceres::Jet<double, 1> const*, double*) in cerestest-ef733e.o
  "google::LogMessageFatal::LogMessageFatal(char const*, int)", referenced from:
      void ceres::internal::Make1stOrderPerturbation<ceres::Jet<double, 1>, double, 1>(int, double const*, ceres::Jet<double, 1>*) in cerestest-ef733e.o
      void ceres::internal::Take0thOrderPart<ceres::Jet<double, 1>, double*>(int, ceres::Jet<double, 1> const*, double*) in cerestest-ef733e.o
      void ceres::internal::Take1stOrderPart<ceres::Jet<double, 1>, double, 0, 1>(int, ceres::Jet<double, 1> const*, double*) in cerestest-ef733e.o
  "google::LogMessageFatal::LogMessageFatal(char const*, int, google::CheckOpString const&)", referenced from:
      ceres::AutoDiffCostFunction<CostFunctor, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0>::AutoDiffCostFunction(CostFunctor*) in cerestest-ef733e.o
      ceres::internal::AutoDiff<CostFunctor, double, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0>::Differentiate(CostFunctor const&, double const* const*, int, double*, double**) in cerestest-ef733e.o
  "google::LogMessageFatal::~LogMessageFatal()", referenced from:
      ceres::AutoDiffCostFunction<CostFunctor, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0>::AutoDiffCostFunction(CostFunctor*) in cerestest-ef733e.o
      ceres::internal::AutoDiff<CostFunctor, double, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0>::Differentiate(CostFunctor const&, double const* const*, int, double*, double**) in cerestest-ef733e.o
      void ceres::internal::Make1stOrderPerturbation<ceres::Jet<double, 1>, double, 1>(int, double const*, ceres::Jet<double, 1>*) in cerestest-ef733e.o
      void ceres::internal::Take0thOrderPart<ceres::Jet<double, 1>, double*>(int, ceres::Jet<double, 1> const*, double*) in cerestest-ef733e.o
      void ceres::internal::Take1stOrderPart<ceres::Jet<double, 1>, double, 0, 1>(int, ceres::Jet<double, 1> const*, double*) in cerestest-ef733e.o
  "google::InitGoogleLogging(char const*)", referenced from:
      _main in cerestest-ef733e.o
  "google::base::CheckOpMessageBuilder::ForVar2()", referenced from:
      std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >* google::MakeCheckOpString<int, int>(int const&, int const&, char const*) in cerestest-ef733e.o
      std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >* google::MakeCheckOpString<int, ceres::DimensionType>(int const&, ceres::DimensionType const&, char const*) in cerestest-ef733e.o
  "google::base::CheckOpMessageBuilder::NewString()", referenced from:
      std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >* google::MakeCheckOpString<int, int>(int const&, int const&, char const*) in cerestest-ef733e.o
      std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >* google::MakeCheckOpString<int, ceres::DimensionType>(int const&, ceres::DimensionType const&, char const*) in cerestest-ef733e.o
  "google::base::CheckOpMessageBuilder::CheckOpMessageBuilder(char const*)", referenced from:
      std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >* google::MakeCheckOpString<int, int>(int const&, int const&, char const*) in cerestest-ef733e.o
      std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >* google::MakeCheckOpString<int, ceres::DimensionType>(int const&, ceres::DimensionType const&, char const*) in cerestest-ef733e.o
  "google::base::CheckOpMessageBuilder::~CheckOpMessageBuilder()", referenced from:
      std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >* google::MakeCheckOpString<int, int>(int const&, int const&, char const*) in cerestest-ef733e.o
      std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >* google::MakeCheckOpString<int, ceres::DimensionType>(int const&, ceres::DimensionType const&, char const*) in cerestest-ef733e.o
  "ceres::Solver::Summary::BriefReport() const", referenced from:
      _main in cerestest-ef733e.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

And this is not just ceres, similar errors occur for boost also.

bzcheeseman
  • 231
  • 1
  • 2
  • 9
  • 1
    Use libc++ not libstdc++. If you show the actual missing symbol messages it'd be easier to see what's going on too :) IIRC libstdc++ is an older GNU version of the library. libc++ should work for most stuff now. And maybe show the exact steps to produce the problem? – JCx Sep 06 '15 at 15:54
  • 1
    Added above, thanks :) The only reason I used libstdc++ is because it actually gave me a different error, I thought it might be helpful for figuring out what's wrong. – bzcheeseman Sep 06 '15 at 16:05
  • try typing `which g++` and `which clang++`. it sounds likely that your paths are messed up and you aren't actually running the programs you think you are. if you want to specify exactly what binary to run, you can use `./` syntax in bash and specify the full path to the binary – Chris Beck Sep 06 '15 at 16:28
  • Normally, with a library, you have to first tell the compiler where the header files are as you have done with `-I ...` and then tell the linker where the libraries are also with `-l`, e.g. `-lpng -ljpeg` or using something like `pkgconfig`. That is `dash lower-case ell` rather than `dash upper case i`. – Mark Setchell Sep 06 '15 at 16:39
  • 1
    So I actually uninstalled gcc after it didn't help so `which g++` and `which clang++` both give me `/usr/bin/g++` and `/usr/bin/clang++` respectively. Also tried adding the `-L /usr/local/lib`, same error. If I use `-lceres -lglog` it works, but will I have to use that with every library, or is there a path that I can edit? – bzcheeseman Sep 06 '15 at 16:45
  • 1
    Very exciting that it finally works though, @MarkSetchell – bzcheeseman Sep 06 '15 at 16:50
  • Normally, you put all that stuff in a `Makefile` and just type `make` and it applies all the flags and libraries and options. – Mark Setchell Sep 06 '15 at 16:55
  • Brilliant. I'll keep testing a little bit, make sure this works for all the libraries and then post an answer when I'm sure it works universally. So far no problems. – bzcheeseman Sep 06 '15 at 17:01

1 Answers1

11

Thanks to Mark Setchell:

Keeping an eye on /usr/local/lib is important when using homebrew, the linking libraries need to be specified.

The final code that worked was this:

g++ cerestest.cpp -o ceres -lglog -lceres -I /usr/local/include

The same answer seems to work for the boost libraries, as well as all the others I've tried (Qt included, so far).

bzcheeseman
  • 231
  • 1
  • 2
  • 9