Undefined Symbols for Architecture X86_64 - Mavericks (Yosemite, El Capitan...)

Undefined symbols for architecture x86_64 - Mavericks (Yosemite, El Capitan...)

All the issues I had, that were giving

Undefined symbols for architecture x86_64

were due to the fact that some libraries were compiled with libstdc++ and could not be used for code that is compiled/linked with libc++

libc++ is in fact the default new library used by clang since Mavericks, however it is possible to compile with the same clang (no need to install an old gcc) with the classical libstdc++ by using the option

-stdlib=libstdc++


For those who use Boost it is also possible to have boost libraries on mavericks that are compiled/linked with libstdc++ by downloading the source and using (when compiling it) instead of the classical

./b2

the following

./b2 cxxflags="-stdlib=libstdc++" linkflags="-stdlib=libstdc++"


For those using Cmake, you may want to add in the adequate cmake file something similar to:

find_library (LIBSTDCXX NAMES stdc++)

and

add_compile_options(-stdlib=libstdc++)

and

target_link_libraries(${PROJECT_NAME} ${LIBSTDCXX} ${YOUR_OTHER_LIBRARIES))

Undefined symbols for architecture x86_64: Mac OS 10.8

Its a linker flag called *force_load*. So -force_load filename.a would do it.

Why can templates only be implemented in the header file?

Caveat: It is not necessary to put the implementation in the header file, see the alternative solution at the end of this answer.

Anyway, the reason your code is failing is that, when instantiating a template, the compiler creates a new class with the given template argument. For example:

template<typename T>
struct Foo
{
T bar;
void doSomething(T param) {/* do stuff using T */}
};

// somewhere in a .cpp
Foo<int> f;

When reading this line, the compiler will create a new class (let's call it FooInt), which is equivalent to the following:

struct FooInt
{
int bar;
void doSomething(int param) {/* do stuff using int */}
}

Consequently, the compiler needs to have access to the implementation of the methods, to instantiate them with the template argument (in this case int). If these implementations were not in the header, they wouldn't be accessible, and therefore the compiler wouldn't be able to instantiate the template.

A common solution to this is to write the template declaration in a header file, then implement the class in an implementation file (for example .tpp), and include this implementation file at the end of the header.

Foo.h

template <typename T>
struct Foo
{
void doSomething(T param);
};

#include "Foo.tpp"

Foo.tpp

template <typename T>
void Foo<T>::doSomething(T param)
{
//implementation
}

This way, implementation is still separated from declaration, but is accessible to the compiler.

Alternative solution

Another solution is to keep the implementation separated, and explicitly instantiate all the template instances you'll need:

Foo.h

// no implementation
template <typename T> struct Foo { ... };

Foo.cpp

// implementation of Foo's methods

// explicit instantiations
template class Foo<int>;
template class Foo<float>;
// You will only be able to use Foo with int or float

If my explanation isn't clear enough, you can have a look at the C++ Super-FAQ on this subject.

Making .so from .cpp: Undefined symbols for architecture x86_64: Boost.Python MacPorts GCC6 not Clang

Regardless of whether you have GCC/G++ installed correctly, MacPorts always builds its C++ software against libc++ on systems where clang would compile with libc++ as default.

That means that your MacPorts version of Boost is compiled with libc++, which means you cannot use it with GCC/G++ (unless you jump through some extra hoops to use libc++ with GCC).

Despite your guess that your problem is not what you described in the other post you linked, it is exactly that. Your options are:

  • Use clang++
  • Build your own copy of Boost with g++

Unable to `gem install tiny_tds` OS X Mavericks

I solved this problem by explicitly specifying the 64 bit architecture:

$ brew install freetds
$ sudo ARCHFLAGS="-arch x86_64" gem install tiny_tds

The reason is that during the gem building process, mkmf will try to look for 32 bit version of freetds, which is not available. The error message in mkmf.log said:

ld: warning: ignoring file /usr/local/lib/libsybdb.dylib, file was built for x86_64 which is not the architecture being linked (i386): /usr/local/lib/libsybdb.dylib
Undefined symbols for architecture i386:
"_tdsdbopen", referenced from:
_t in conftest-a13287.o
ld: symbol(s) not found for architecture i386


Related Topics



Leave a reply



Submit