Подтвердить что ты не робот

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.

4b9b3361

Ответ 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