環境
- OS
- macOS Monterey バージョン 12.4
- CPU, GPU
- M1
- コンパイラ
- Apple clang version 13.1.6 (clang-1316.0.21.2.5)
トラブル
"Hello" を標準出力するだけの main.cpp を、既定のビルドタスク設定(コンパイラは clang
)でビルドしたところ、下記のエラーが発生しました。
Undefined symbols for architecture arm64:
/* 中略 */
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 {use -v to see invocation}
main.cpp
#include <iostream>
using namespace std;
int main() {
cout << "Hello" << endl;
}
tasks.json
{
"version": "2.0.0",
"tasks": [
{
"type": "process",
"label": "C/C++: clang アクティブなファイルのビルド",
"command": "/usr/bin/clang",
"args": [
"-fdiagnostics-color=always",
"-g",
"${file}",
"-o",
"${fileDirname}/${fileBasenameNoExtension}"
],
"options": {
"cwd": "${fileDirname}"
},
"problemMatcher": [
"$gcc"
],
"group": {
"kind": "build",
"isDefault": true
},
"detail": "コンパイラ: usr/bin/clang"
}
]
}
解決法
コンパイラ(コマンド)を clang
ではなく clang++
にします。
tasks.json の変更点は以下のようになります。(既定の設定)
{
"version": "2.0.0",
"tasks": [
{
"type": "process",
- "label": "C/C++: clang アクティブなファイルのビルド",
+ "label": "C/C++: clang++ アクティブなファイルのビルド",
- "command": "/usr/bin/clang",
+ "command": "/usr/bin/clang++",
"args": [
"-fdiagnostics-color=always",
"-g",
"${file}",
"-o",
"${fileDirname}/${fileBasenameNoExtension}"
],
"options": {
"cwd": "${fileDirname}"
},
"problemMatcher": [
"$gcc"
],
"group": {
"kind": "build",
"isDefault": true
},
- "detail": "コンパイラ: usr/bin/clang"
+ "detail": "コンパイラ: usr/bin/clang++"
}
]
}
余談
clang
コマンドを使った理由
clang
は C のコンパイルコマンドだから C++ のコンパイルに使うのは不適切では?(最初から clang++
使っとけよ)
という声が聞こえてきそうですが、
-
clang
とclang++
の実行ファイルの inode 番号が同じだったので、どっち使っても同じやろ! と考えた -
clang
の方がclang++
よりも美しい(主観)名前で好き
という2点から clang
を採用しました。
clang
にしたことが原因で沼るとは思いもよらなかった……
エラーについて
エラーメッセージにもあるように、リンカー(ld
)がはたらく段階でしくじっています。
つまり、(狭義の)コンパイルは成功していますが、その後のリンクで失敗しています。
詳しい説明は省きますが、clang
は C++ の標準ライブラリのオブジェクトファイルを自動的にリンクしてくれないらしいです。
それゆえ clang++
では出ないエラーが clang
では出てしまうということでした。
コンパイルエラーに関してはインターネット上に情報がたくさんありますが、リンクエラーに関してはあまりなく、解決に苦労しました……
参考資料
解決法はこちらで知りました。「おまけ」の項にあります。
コンパイルとリンクについての説明もこちらに。