編集:
この投稿に該当する場合は、回答に直接ジャンプできます
今朝早く混乱について投稿しました
マシンタイプ(C++ライブラリ):i386 vs x86_64
しかし、私は正確ではないことによって間違いを犯したと思います。そこで、私が直面している状況と理解できない状況の例を挙げることにしました。
ステップ1
OS x 10.7.5を搭載した2年前のMacであるマシンAでライブラリを構築します(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とライブラリを、32ビットだと思うosx 10.6.7の5年前のMacである別のマシンBにコピーします。そして、ライブラリをテストするために次のhelloファイルを作成します
#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の同じヘッダーとhelloファイルを使用して同じライブラリを再度コピーします。これは、64ビットであると考えられる10.9.2の新しいMacです。
驚くべきことに、リンクの問題があります
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
私は、32ビットのマシンBと64ビットのマシンCではなく、リンクの問題を予期していましたが、逆になりました。誰も私がここで欠けているものを説明できますか?
編集(ステップ4)
マシンCでは、g++
コマンドにオプション-stdlib=libstdc++
を追加すると、「未定義のシンボル」エラーが消え、実行可能ファイルが正しく実行されます。オプション-vを指定してg ++を実行すると、デフォルトのstdlib
がlibc++
ではなくlibstdc++
であることに気付きました。したがって、マシンAとマシンCはどちらも64ビットですが、デフォルトでは同じstdlib
を使用せず、エラーUndefined symbols for architecture x86_64
を引き起こしたようです。
私が持っていたすべての問題、それは与えていました
_Undefined symbols for architecture x86_64
_
一部のライブラリはlibstdc ++でコンパイルされ、libc ++でコンパイル/リンクされたコードには使用できなかったためです
libc ++は、実際にはMavericksであるためclangで使用されるデフォルトの新しいライブラリですが、オプションを使用することにより、従来のlibstdc ++で同じclang(古いgccをインストールする必要はありません)でコンパイルすることが可能です
_-stdlib=libstdc++
_
Boostを使用する場合、ソースをダウンロードし、(コンパイル時に)クラシックの代わりに
_./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))
私はちょっと怠け者で、これを読むつもりはありませんので、気軽に投票してください...
あなたは太った32/64ビットライブラリを構築しようとしていると思います...
これを行うにはいくつかの方法があります。1つは32ビットで明示的にビルドし、64ビットでは明示的にビルドする場合です... lipo
を使用してそれらを結合します。
名目上のC++コードが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
または、一般的に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