web-dev-qa-db-fra.com

Symboles non définis pour l'architecture x86_64 - Mavericks (Yosemite, El Capitan ...)

MODIFIER : 

Si vous tombez sur ce post, vous voudrez peut-être passer directement à la réponse


J'ai envoyé un message sur ma confusion plus tôt ce matin

type de machine (librairies C++): i386 vs x86_64

Mais je suppose que j'ai commis une erreur en n'étant pas précis. J'ai donc décidé de donner un exemple des situations auxquelles je suis confronté et que je ne peux pas comprendre.

ÉTAPE 1

Je construis une bibliothèque sur la machine A, un Mac âgé de 2 ans avec OS x 10.7.5 (je suppose, 64 bits; mon estimation étant basée sur les commandes que vous verrez ci-dessous dans Informations supplémentaires) en utilisant les fichiers suivants.

Un en-tête SimpleClass.hpp:

#ifndef SIMPLECLASS_HPP
#define SIMPLECLASS_HPP

class SimpleClass
{
public:
  SimpleClass();
  SimpleClass(const SimpleClass& orig);
  virtual ~SimpleClass();
private:

} ;

#endif  /* SIMPLECLASS_HPP */

Un fichier source 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()
{
}

Je crée la bibliothèque en utilisant 

~/cpp_test$ clang++ -c -o SC.o -I SimpleClass.hpp SimpleClass.cpp

~/cpp_test$ ar rcs libtest_sc.a SC.o

Informations supplémentaires sur la machine 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

ÉTAPE 2

Je copie SimpleClass.hpp, ainsi que la bibliothèque, sur une autre machine B datant de 5 ans et ayant osx 10.6.7 qui, à mon avis, fait 32 bits. Et j'écris le fichier hello suivant pour tester la bibliothèque

#include <iostream>
#include "SimpleClass.hpp"

int main()
{
  std::cout << "Hello World!" << std::endl;
  SimpleClass testObj;
  return 0;
} 

Étonnamment, pas de problèmes de liaison avec la bibliothèque et je reçois.

[~/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

Informations supplémentaires sur la machine 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.

ÉTAPE 3

Je copie à nouveau la même bibliothèque avec le même en-tête et le même fichier hello sur la machine C, qui est un nouveau Mac avec 10.9.2 qui, à mon avis, fait 64 bits.

Étonnamment j'ai des problèmes de liens

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)

Informations supplémentaires sur la machine 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

Je me serais attendu au problème de liaison avec la machine B qui est 32bits et pas avec la machine C qui est 64bits mais j'ai eu le contraire. Quelqu'un peut-il s'il vous plaît expliquer ce que je manque ici?

EDIT (ÉTAPE 4)

Sur la machine C, lorsque j'ajoute à l'option g++ à la commande -stdlib=libstdc++, l'erreur "symboles non définis" disparaît et le fichier exécutable s'exécute correctement. L'exécution de g ++ avec l'option -v m'a permis de remarquer que la variable par défaut stdlib était libc++et non libstdc++. Il semble donc que, bien que la machine A et la machine C aient toutes deux 64 bits, elles n'utilisent pas la même variable stdlib qui a provoqué l'erreur Undefined symbols for architecture x86_64.

17
Issam T.

Je suis un peu paresseux et je ne vais pas lire ceci, alors n'hésitez pas à voter pour le bas ...

Je pense que vous essayez de construire une grosse bibliothèque 32/64 bits ...

vous avez deux façons de le faire, une si construire explicitement avec 32 bits et explicitement avec 64 bits ... puis utilisez lipo pour les combiner.

considérer que le code C++ nominal est stocké dans main.cpp

puis:

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

ou vous pouvez généralement utiliser certains raccourcis avec les outils Apple:

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
0
Grady Player