How to link in std C++ library on Mac OS X Mavericks? - c++

I'm porting an application to OS X Darwin and am getting link errors with missing symbols like:
std::__1::basic_string<char, std::__1::char_traits<char>,
std::__1::allocator<char> >::find_last_of(char const*,
unsigned long,
unsigned long) const
operator delete[](void*)
typeinfo for std::runtime_error
std::set_unexpected(void (*)())
std::exception::~exception()
[...]
I expect these should come from libstdc++ but I don't see how to link that in using clang.
Here is my attempted link line and the resulting failure:
clang -std=c++11 -stdlib=libc++ -m64 -o ARCH.darwin_1310_i86/release/myExec ARCH.darwin_1310_i86/release/myExec.o ../../src/netcomm/ARCH.darwin_1310_i86/release/libmyExec.a ../../src/common/ARCH.darwin_1310_i86/release/libcommon.a -L../zlib -lz -L../Botan -lbotan-1.10 -lboost_thread-mt
Undefined symbols for architecture x86_64:
"std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::find_last_of(char const*, unsigned long, unsigned long) const", referenced from:
[...]
But this did not work, I'm not finding any examples of how to link it in correctly.

You need to add -lc++ to the link line like this:
clang -std=c++11 -stdlib=libc++ -lc++ -m64 -o ARCH.darwin_1310_i86/release/myExec ARCH.darwin_1310_i86/release/myExec.o ../../src/netcomm/ARCH.darwin_1310_i86/release/libmyExec.a ../../src/common/ARCH.darwin_1310_i86/release/libcommon.a -L../zlib -lz -L../Botan -lbotan-1.10 -lboost_thread-mt
After adding that, the missing symbols go away.

Using the CLang++ compiler on my MacBook Pro OS X Mavericks 9.2, within NetBeans 7.4, I have
-std=c++11 -stdlib=libc++ -Wall
I am sure that I obtained the libc++ from installing the latest Xcode Command Line Tools for Mavericks. On my system, the dynamic libc++ libraries are located in the /usr/lib directory.
Start Edit
I have just tried a basic, "Hello, World," run from Xcode, making sure the LLVM 5.0 (CLang++) compiler settings within the .xcodeproj are configured for:
C++ Language Dialect C++11 [-std=c++11]
C++ Standard Library libc++ (LLVM C++ Standard library with C++11 support)
C Language Dialect c11
All works as expected.
End Edit

Related

Why can cc compile a c++ program?

I have a makefile for macOS and Linux, which contains the following command:
cc -std=c++14 foo.cpp bar.cpp
And it compiles fine. foo.cpp and bar.cpp are, as the name suggests C++ files and it contains C++11 syntax. The compilation works fine.
Now if I include <fstream> I get hundred of linker errors. I am wondering, why that is?
Undefined symbols for architecture x86_64:
"std::__1::locale::has_facet(std::__1::locale::id&) const", referenced from:
bool std::__1::has_facet<std::__1::codecvt<char, char, __mbstate_t> >(std::__1::locale const&) in DiceInvaders-6f5dd4.o
"std::__1::locale::use_facet(std::__1::locale::id&) const", referenced from:
...
Afaik, cc links to the c compiler, and I would assume due to it's auto detection it compiles it with the C++ compiler. But why does it fail with an additional C++ include?
Is there any counterpart of cc for c++ on a system? If I use g++, I would assume that command is available, and what if the user actually wanted to compile it with his compiler of preference (as in cc)?
Edit: Is $(CXX) a good replacement for cc?
Most probably cc on your system is a symlink to gcc executable. Assuming that is true:
The difference between gcc and g++, quoting the man page, is:
g++ is a program that calls GCC and automatically specifies linking against the C++ library.
So when you invoke gcc it does not link against c++ library. You can link standard c++ library manually:
gcc -lstdc++ 1.cpp
Is there any counterpart of cc for c++ on a system?
The cc command is just a convention that most system follow. It's not standardized, at least I haven't heard where, the utility c99 is standarized by posix. On my linux system with archlinux distribution with the gcc package there is also installed symlink /usr/bin/c++ to g++.

shared_timed_mutex not available on OS X 10.11.2?

I'm trying to play around with the new shared_timed_mutex structures from C++ 14 on OS X 10.11.2 using Eclipse CDT 4.5.0. Xcode is 7.2. I'm using GCC C++ with the following options:
-O0 -g3 -Wall -c -fmessage-length=0 -std=c++14
Her's what I get:
Invoking: MacOS X C++ Linker
g++ -o "MyProject" ./src/main.o
Undefined symbols for architecture x86_64:
"std::__1::shared_timed_mutex::shared_timed_mutex()", referenced from:
HashMap<int, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::hash<int> >::HashMap() 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)
Here's my clang version info:
Apple LLVM version 7.0.2 (clang-700.1.81)
Target: x86_64-apple-darwin15.2.0
Thread model: posix
I've searched my way through the web and found a couple of recommendations, for example this one on Reddit:
https://www.reddit.com/r/cpp_questions/comments/3ejfkr/is_c14s_stdshared_timed_mutex_available_on_os_x/?
This is very close to my problem, I've tried the suggestions, but I´m hoping, that I won´t have to do the manual libc++ download, but could stick with the standard libs shipped with my system.
Thank you!
For the past two years (as I write this) Apple has updated the libc++ headers for their tools releases, but not the libc++ sources. And libc++ implements std::shared_time_mutex both in <shared_mutex> and in shared_mutex.cpp.
According to Apple dev presentation the shared_timed_mutex will be available starting with macOS 10.12. See page 52

Trouble compiling c++ program on Mac OSX 10.9 with opencv

I'm trying to compile a C++ program on Mac OSX 10.9 via the command line (and clang) that uses opencv (version 2.4.12) and am running into some problems.
I'm trying to compile the program by running the following in Terminal:
clang --std=c++11 -stdlib=libc++ test.cpp -L/usr/local/Cellar/opencv/2.4.12/lib -lopencv_core.2.4.12 -lopencv_ml.2.4.12 -lopencv_video.2.4.12 -lopencv_ml -lopencv_video -lc++
However I'm getting the following error:
Undefined symbols for architecture x86_64:
"cv::namedWindow(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int)", referenced from:
Along with a string of other opencv functions that can't be found.
Upon doing some additional research, I found out that the problem might be associated with using libc++ instead of libstdc++ as the library. I tried switching to libstdc++ and was stuck with the following error.
fatal error: 'array' file not found
#include <array>
I researched that error and found out that for the Mac, it was because of using libstdc++ instead of libc++. Essentially, I'm kind of stuck in a loop and need some help compiling this program. Any thoughts?

Using -std=c++0x with gfortran

I have large program which uses C, C++, and Fortran. I've always found it easiest to get this to link properly using the "gfortran" front end, even though my main is C. gfortran knows about a lot of Fortran special stuff that needs to be linked in.
Now, however, I need to include unordered_map, which with my compiler (gcc 4.4.1 on Mac OS X 10.7.5) seems to require the -std=c++0x option. I discovered and verified that by compiling a small test program with C++ only.
But if I use the -std=c++0x option with gfortran, that produces a huge number of link errors starting with:
Undefined symbols for architecture i386:
"std::basic_string<char, std::char_traits<char>, std::allocator<char> >::data() const", referenced from:
Meanwhile, if I go back to my large program, and replace the gfortran with g++ or gcc, I also get a huge number of link errors, starting with:
Undefined symbols for architecture i386:
"__gfortran_compare_string", referenced from:
I now link using g++ with the -lgfortran switch, and that lets me use -std=c++0x and doesn't leave me with undefined c++ or fortran symbols.

Linker errors when using boost serialization

I am using boost serialization. I compiled with: -L/opt/local/lib -lboost_serialization -stdlib=libc++, but got several (ungooglable) errors:
Undefined symbols for architecture x86_64:
"boost::archive::text_oarchive_impl::save(std::__1::basic_string, std::__1::allocator > const&)", referenced from:
void boost::archive::save_access::save_primitive, std::__1::allocator > >(boost::archive::text_oarchive&, std::__1::basic_string, std::__1::allocator > const&) in main.o
"boost::archive::basic_text_oprimitive > >::~basic_text_oprimitive()", referenced from:
boost::archive::text_oarchive_impl::~text_oarchive_impl() in main.o
"boost::archive::text_oarchive_impl::text_oarchive_impl(std::__1::basic_ostream >&, unsigned int)", referenced from:
boost::archive::text_oarchive::text_oarchive(std::__1::basic_ostream >&, unsigned int) in main.o
ld: symbol(s) not found for architecture x86_64
I am serializing an std::vector<std::string>:
boost::archive::text_oarchive oa(std::cout);
oa << tasks;
Is there a problem with my installation of boost?
The boost libraries are universal binaries containing both 32-bit and 64-bit machine code (so that's not the problem I guess):
$ file libboost_serialization.dylib
libboost_serialization.dylib: Mach-O universal binary with 2 architectures
libboost_serialization.dylib (for architecture i386): Mach-O dynamically linked shared library i386
libboost_serialization.dylib (for architecture x86_64): Mach-O 64-bit dynamically linked shared library x86_64
I installed boost using sudo port install boost +universal on Mac OS X 10.7.
I could reproduce the problem using the following code:
#include "boost/archive/text_oarchive.hpp"
#include "boost/serialization/vector.hpp"
#include <vector>
#include <string>
int main()
{
std::vector<std::string> tasks;
boost::archive::text_oarchive oa(std::cout);
oa << tasks;
}
This compiles and links without problems when using g++ or clang++ with their respective default flags and linking with -lboost_serialization. However, when using clang++ with libc++ linking fails with essentially the error messages quote (I have Boost installed at /opt/boost):
clang++ -c -stdlib=libc++ -I/opt/boost -W -Wall -ansi serialize.cpp
clang++ -o serialize.tsk -L/opt/boost/stage/lib -stdlib=libc++ serialize.o -lboost_serialization
Based on this I assumed that a build with -stdlib=libc++ wants to have its own Boost build and build one using based on the Boost installation guide:
tar jxvf ~/Downloads/boost_1_48_0.tar.bz2
cd boost_1_48_0/tools/build/v2
# change the build rules to use -stdlib=libc++:
mv tools/clang-darwin.jam tools/clang-darwin.jam.orig
sed -e 's/CONFIG_COMMAND)"/CONFIG_COMMAND)" -stdlib=libc++/' < tools/clang-darwin.jam.orig > tools/clang-darwin.jam
./boostrap.sh
sudo ./b2 install --prefix=/opt/boost-clang
cd ../../..
/opt/boost-clang/bin/b2 --build-dir=/opt/tmp toolset=clang stage
sudo /opt/boost-clang/bin/b2 --build-dir=/opt/tmp toolset=clang install --prefix=/opt/boost-clang
The edits I made to clang-darwin.jam are almost certainly not those intended but they seem to do the trick: I don't know much about "bjam" and I just tried to find an appropriate location to apply the change. Some step of the installation use sudo to install things into protected directories. Obviously, you can install into some other directory where you have write permissions as well. I just installed things on my machine in a way preventing me from accidentally messing it up.
However, with this installation in place I could successfully build the program:
/opt/llvm/bin/clang++ -stdlib=libc++ -W -Wall -ansi -I/opt/boost-clang -c -o serialize.o serialize.cpp
/opt/llvm/bin/clang++ -stdlib=libc++ -L/opt/boost-clang/lib serialize.o -lboost_serialization -o serialize.tsk
It looks like your boost libraries may be 32 bit.
That's a problem you wouldn't notice until you tried to use one of the few boost utils that are not header-only.