架构 x86_64 的未定义符号 - Mavericks (Yosemite, El Capitan...)

如果你中了这个帖子,你可能想直接跳到答案

我今天早上早些时候发了一篇关于我的困惑的帖子

I sent a post about my confusion earlier this morning

机器类型(C++ 库):i386 与 x86_64

但我想我犯了一个不准确的错误.所以我决定举一个我遇到的但我无法理解的情况的例子.

But I guess I did a mistake by being not precise. So I decided to give an example of situations I face and that I can not understand.

第 1 步

我在机器 A 上构建了一个库,这是一个 2 岁的 Mac,OS x 10.7.5(我猜是 64 位;我的猜测是基于您将在下面的附加信息中看到的命令)使用以下文件.

I build a library on machine A, a 2 years old mac with OS x 10.7.5 (that I guess is 64 bits; my guess being based on the commands you will see below in Additional Info) using the following files.

一个头文件 SimpleClass.hpp:

A header SimpleClass.hpp:

#ifndef SIMPLECLASS_HPP
#define SIMPLECLASS_HPP

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

} ;

#endif  /* SIMPLECLASS_HPP */

一个源文件SimpleClass.cpp:

A source file 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 的附加信息:

Additional info on 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

第 2 步

我将 SimpleClass.hpp 和库复制到另一台机器 B,它是一台 5 岁的 mac,我相信是 32 位的 osx 10.6.7.我编写了以下 hello 文件来测试库

I copy SimpleClass.hpp as well as the library to another machine B that is a 5 years old mac with osx 10.6.7 that I believe is 32 bits. And I write the following hello file to test the library

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

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

令人惊讶的是,与图书馆链接没有问题,我得到了.

Surprisingly, no problems at linking with the library and I get.

[~/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 的附加信息:

Additional info on 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.

第 3 步

我在机器 C 上使用相同的头文件和 hello 文件再次复制相同的库,这是一个新的 10.9.2 的 mac,我认为是 64 位.

I copy the same library again with the same header and hello file on Machine C that is a new mac with 10.9.2 that I believe is 64 bits.

令人惊讶的是我有链接问题

Surprisingly I have linking problems

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 的附加信息

Additional Info on 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

我本以为 32 位机器 B 的链接问题而不是 64 位机器 C 的链接问题,但我得到了相反的结果.谁能解释一下我在这里缺少什么?

I would have expected the linking problem with machine B that is 32bits and not with machine C that is 64bits but I got the opposite. Can anyone please explain what I am missing here?

编辑(第 4 步)

在机器 C 上,当我将选项 -stdlib=libstdc++ 添加到 g++ 命令时,未定义符号"错误消失并且可执行文件正常运行.使用选项 -v 运行 g++ 让我注意到默认的 stdliblibc++ 而不是 libstdc++.所以看起来虽然机器 A 和机器 C 都是 64 位,但它们默认不使用相同的 stdlib 导致错误 Undefined symbols for architecture x86_64.

On machine C, when I add to the g++ command the option -stdlib=libstdc++, the "undefined symbols" error disappear and the executable is running correctly. Running g++ with the option -v allowed me to notice the default stdlib was libc++and not libstdc++. So it seems that although the machine A and machine C are both 64 bits they don't use the same stdlib by default which caused the error Undefined symbols for architecture x86_64.

推荐答案

我遇到的所有问题,都给了

All the issues I had, that were giving

x86_64 架构的未定义符号

是由于某些库是使用 libstdc++ 编译的,并且不能用于使用 libc++

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++ 实际上是自 Mavericks 以来 clang 使用的默认新库,但是可以使用与经典 libstdc++ 相同的 clang(无需安装旧 gcc)进行编译,方法是使用选项

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++

对于那些使用 Boost 的人,也可以通过下载源代码并使用(在编译时)而不是经典的方式在 mavericks 上使用通过 libstdc++ 编译/链接的 boost 库

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

以下

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

对于那些使用 Cmake 的人,您可能需要在适当的 cmake 文件中添加类似于:

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

find_library (LIBSTDCXX NAMES stdc++)

add_compile_options(-stdlib=libstdc++)

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

相关文章