Undefined символы для архитектуры x86_64 - Mavericks (Yosemite, El Capitan...)
EDIT:
Если вы попадете на этот пост, вы можете перейти непосредственно к ответу
Я отправил сообщение о моем замешательстве сегодня утром.
тип машины (С++ librairies): i386 vs x86_64
Но я предполагаю, что ошибся, не будучи точным. Поэтому я решил привести пример ситуаций, с которыми сталкиваюсь, и что я не могу понять.
ШАГ 1
Я создаю библиотеку на компьютере A, 2-летнем mac с OS x 10.7.5 (я думаю, это 64 бита, я полагаю, что на основе команд, которые вы увидите ниже в дополнительной информации), используя следующие файлы.
Заголовок SimpleClass.hpp:
#ifndef SIMPLECLASS_HPP
#define SIMPLECLASS_HPP
class SimpleClass
{
public:
SimpleClass();
SimpleClass(const SimpleClass& orig);
virtual ~SimpleClass();
private:
} ;
#endif /* SIMPLECLASS_HPP */
Исходный файл SimpleClass.cpp:
#include "SimpleClass.h"
#include <iostream>
SimpleClass::SimpleClass()
{
std::cout << "A new instance of Simple Class was created" << std::endl;
}
SimpleClass::SimpleClass(const SimpleClass& orig)
{
}
SimpleClass::~SimpleClass()
{
}
Я создаю библиотеку, используя
~/cpp_test$ clang++ -c -o SC.o -I SimpleClass.hpp SimpleClass.cpp
~/cpp_test$ ar rcs libtest_sc.a SC.o
Дополнительная информация о машине A:
~/cpp_test$ clang++ --version
Apple LLVM version 4.2 (clang-425.0.28) (based on LLVM 3.2svn)
Target: x86_64-apple-darwin11.4.2
~/cpp_test$ uname -m
x86_64
~/cpp_test$ uname -p
i386
~/cpp_test$ lipo -info libtest_sc.a
input file libtest_sc.a is not a fat file
Non-fat file: libtest_sc.a is architecture: x86_64
ШАГ 2
Я копирую SimpleClass.hpp, а также библиотеку на другой компьютер B, который является 5-летним mac с osx 10.6.7, который, я считаю, 32 бит. И я пишу следующий файл приветствия, чтобы протестировать библиотеку
#include <iostream>
#include "SimpleClass.hpp"
int main()
{
std::cout << "Hello World!" << std::endl;
SimpleClass testObj;
return 0;
}
Удивительно, но никаких проблем при подключении к библиотеке я не получаю.
[~/Downloads/Gmail-9]$ g++ -o hello -L. -ltest_sc hello.cpp
[~/Downloads/Gmail-9]$ ./hello
Hello World!
A new instance of Simple Class was created
Дополнительная информация о машине B:
[~/Downloads/Gmail-9]$ uname -m
i386
[~/Downloads/Gmail-9]$ uname -p
i386
[~/Downloads/Gmail-9]$ g++ --version
i686-apple-darwin10-g++-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5666) (dot 3)
Copyright (C) 2007 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
ШАГ 3
Я снова копирую одну и ту же библиотеку с тем же заголовком и приветственным файлом на компьютере C, который является новым mac с 10.9.2, который, по моему мнению, является 64-разрядным.
Удивительно, что у меня проблемы со связью
MacBook-Pro:testcpp$ g++ -o hello -L. -ltest_sc hello.cpp
Undefined symbols for architecture x86_64:
"std::ostream::operator<<(std::ostream& (*)(std::ostream&))", referenced from:
SimpleClass::SimpleClass() in libtest_sc.a(SC.o)
"std::ios_base::Init::Init()", referenced from:
___cxx_global_var_init in libtest_sc.a(SC.o)
"std::ios_base::Init::~Init()", referenced from:
___cxx_global_var_init in libtest_sc.a(SC.o)
"std::cout", referenced from:
SimpleClass::SimpleClass() in libtest_sc.a(SC.o)
"std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&)", referenced from:
SimpleClass::SimpleClass() in libtest_sc.a(SC.o)
"std::basic_ostream<char, std::char_traits<char> >& std::operator<<<std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)", referenced from:
SimpleClass::SimpleClass() in libtest_sc.a(SC.o)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Дополнительная информация на машине C
g++ --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn)
Target: x86_64-apple-darwin13.1.0
Thread model: posix
MacBook-Pro:testcpp$ uname -m
x86_64
MacBook-Pro:testcpp$ uname -p
i386
Я ожидал, что проблема связывания с машиной B будет 32 бита, а не с машиной C, которая является 64 бит, но я получил противоположное. Может кто-нибудь объяснить, что мне здесь не хватает?
ИЗМЕНИТЬ (ШАГ 4)
На машине C, когда я добавляю к команде g++
параметр -stdlib=libstdc++
, ошибка "undefined" исчезает, и исполняемый файл работает правильно. Запуск g++ с опцией -v позволил мне заметить, что по умолчанию stdlib
был libc++
, а не libstdc++
. Таким образом, кажется, что хотя машина A и машина C являются 64 битами, они по умолчанию не используют те же stdlib
, которые вызвали ошибку Undefined symbols for architecture x86_64
.
Ответы
Ответ 1
Все проблемы, которые у меня были, которые давали
Undefined symbols for architecture x86_64
были связаны с тем, что некоторые библиотеки были скомпилированы с помощью libstdС++ и не могли быть использованы для кода, который скомпилирован/связан с libС++
libС++ фактически является новой библиотекой по умолчанию, используемой clang с Mavericks, однако ее можно скомпилировать с тем же clang (не нужно устанавливать старый gcc) с классическим libstdС++, используя опция
-stdlib=libstdc++
Для тех, кто использует Boost, также возможно иметь более мощные библиотеки для mavericks, которые скомпилированы/связаны с libstdС++ путем загрузки источника и использования (при компиляции) вместо классического
./b2
следующее
./b2 cxxflags="-stdlib=libstdc++" linkflags="-stdlib=libstdc++"
Для тех, кто использует Cmake, вы можете добавить в соответствующий файл cmake нечто похожее на:
find_library (LIBSTDCXX NAMES stdc++)
и
add_compile_options(-stdlib=libstdc++)
и
target_link_libraries(${PROJECT_NAME} ${LIBSTDCXX} ${YOUR_OTHER_LIBRARIES))
Ответ 2
Я вроде ленив и не буду читать это, поэтому не стесняйтесь проголосовать...
Я думаю, вы пытаетесь построить жирную библиотеку с 32/64 бит...
у вас есть несколько способов сделать это: один, если выстроить явно с 32-битным и явно с 64-битным... затем используйте lipo
для их объединения.
считать номинальный код С++ хранится в main.cpp
то
grady$ clang++ main.cpp -m64 -o64.out
grady$ file 64.out
64.out: Mach-O 64-bit executable x86_64
grady$ clang++ main.cpp -m32 -o32.out
grady$ file 32.out
32.out: Mach-O executable i386
grady$ lipo -arch i386 32.out -arch x86_64 64.out -create -output fat.out
grady$ file fat.out
fat.out: Mach-O universal binary with 2 architectures
fat.out (for architecture i386): Mach-O executable i386
fat.out (for architecture x86_64): Mach-O 64-bit executable x86_64
или вы можете обычно использовать некоторые ярлыки с яблочными инструментами:
grady$ clang++ main.cpp -arch i386 -arch x86_64 -ofat2.out
grady$ file fat2.out
fat2.out: Mach-O universal binary with 2 architectures
fat2.out (for architecture i386): Mach-O executable i386
fat2.out (for architecture x86_64): Mach-O 64-bit executable x86_64