C++ 架构 x86_64 的未定义符号 - 小牛队(优胜美地、埃尔卡皮坦...)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25020140/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 11:13:34  来源:igfitidea点击:

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

c++macoslinkerstatic-libraries32bit-64bit

提问by Issam T.

EDIT :

编辑 :

If you fall on this post, you may want to jump directly to the answer

如果你落在这个帖子上,你可能想直接跳到答案



I sent a post about my confusion earlier this morning

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

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

机器类型(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.

但我想我犯了一个不精确的错误。所以我决定举一个我所面临的我无法理解的情况的例子。

STEP 1

第1步

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.

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

A header SimpleClass.hpp:

标头 SimpleClass.hpp:

#ifndef SIMPLECLASS_HPP
#define SIMPLECLASS_HPP

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

} ;

#endif  /* SIMPLECLASS_HPP */

A source file SimpleClass.cpp:

一个源文件 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()
{
}

I create the library using

我创建库使用

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

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

Additional info on machine A:

关于机器 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

STEP 2

第2步

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

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

#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

Additional info on Machine B:

关于机器 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.

STEP 3

第 3 步

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.

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

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)

Additional Info on Machine C

关于机器 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

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?

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

EDIT (STEP 4)

编辑(第 4 步)

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 stdlibwas 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 stdlibby default which caused the error Undefined symbols for architecture x86_64.

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

回答by Issam T.

All the issues I had, that were giving

我遇到的所有问题

Undefined symbols for architecture x86_64

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

是因为一些库是用libstdc++编译的,不能用于用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

libc++ 实际上是自Mavericks以来由 clang 使用的默认新库,但是可以使用相同的 clang(无需安装旧的 gcc)与经典的 libstdc++ 一起编译通过使用选项

-stdlib=libstdc++

-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

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

./b2

./b2

the following

下列

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

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



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

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

find_library (LIBSTDCXX NAMES stdc++)

find_library (LIBSTDCXX NAMES stdc++)

and

add_compile_options(-stdlib=libstdc++)

add_compile_options(-stdlib=libstdc++)

and

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

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

回答by Grady Player

I am sort of lazy and not going to read this, so feel free to vote down...

我有点懒惰,不打算读这个,所以请随意投反对票......

I think you are trying build a fat 32/64 bit library...

我认为您正在尝试构建一个胖 32/64 位库...

you have a couple of ways to do this, one if to build explicitly with 32-bit and explicitly with 64-bit... then use lipoto combine them.

你有几种方法可以做到这一点,一种是用 32 位显式构建,然后用 64 位显式构建……然后使用lipo组合它们。

consider nominal C++ code is stored in main.cpp

考虑名义上的 C++ 代码存储在 main.cpp

then:

然后:

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

or you can generally use some shortcuts with apple tools:

或者你通常可以在苹果工具中使用一些快捷方式:

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