makefileに付属していない限り、サンプルCコードを実行するのは難しいです。
私はしばしば本当に素晴らしいことをしていると言われるコードを含むCファイルを見つけますが、gcc main.c
最初の基本的なコンパイルの試みでは失敗します。
main.c:(.text+0x1f): undefined reference to `XListInputDevices'
clang-3.7: error: linker command failed with exit code 1 (use -v to see invocation)
- または同様です。
-lX11
これは、正しいリンカーフラグ(たとえば、-lXext
または)が欠落していることを意味します-lpthread
。
しかし、どれ?
私が現在この問題を処理する方法は次のとおりです。関数を含むライブラリヘッダーの検索、Githubの検索を使用して同じヘッダーを取得した別のプログラムを見つけ、makefileを開き、リンカーフラグを見つけて、それを私のコンパイルコマンドにコピーし、コンパイルされている最小のセットが見つかるまでフラグを削除し続けました。
非効率的で退屈でより良い方法があると思います。
答え1
問題は、ソースファイルを調べて、使用するリンカフラグを決定する方法です。以下の例は Debian 用です。ここで注目すべき関連項目はヘッダファイルです。
したがって、ヘッダファイルを含むCソースファイルがあるとします。
#include <X11/extensions/XInput.h>.
XInput.h
たとえばapt-file
、このヘッダーファイルがインストールされているパッケージに含まれていることがわかっている場合は、検索することもできます。例えばdpkg -S
dlocate
apt-file search XInput.h
libxi-dev: /usr/include/X11/extensions/XInput.h
これは、ヘッダファイルがlibxiの開発パッケージ(Cライブラリの場合は開発パッケージ(通常libname-dev
または形式libname-devel
)にヘッダファイルが含まれている)に属するため、-lxi
リンカフラグを使用する必要があることを示します。
同様のアプローチが、パッケージ管理システムを使用するすべての展開に適用されます。
答え2
問題の核心:ヘッダファイルとライブラリ名
問題の核心が公開されました。質問自体の下のコメント:
XListInputDevicesの場合、適切なインクルード行はです
#include <X11/extensions/XInput.h>
。私は考えています-lSomethingフラグに基づいて必要なものはどうすればわかりますか?
-lXi
この質問に正しく答えるには、libXi.so
との違いを理解する必要がありますXInput.h
。XInput.h
これはヘッドファイルそして-l
ターゲットファイルを見つけます。 gccの使い方に関するRed Hatドキュメントによると、セクション16.1、
ライブラリは特別なファイル名規則を使用します。 fooというライブラリはlibfoo.soまたはlibfoo.aファイルとして存在する必要があります。 GCCのリンク入力オプションは自動的にこの規則を理解しますが、出力オプションはそうではありません。
ヘッダーとライブラリの両方が必須であり、関連していますが、同じではありません(引用する):
...ヘッダを#includeすると、コンパイラは呼び出した関数のコードをprogram.oに挿入しません。ただそれへの参照を挿入するだけです。
前述のように、ヘッダーとリンカーはヘッダーが関数やその他の項目の宣言(または一般用語で説明)を格納しますが、ライブラリーは実際のオブジェクト(引用する)またはこれらの関数のコンパイル済みバージョン。この回答からわかるように、:
- タイトルは電話できる電話番号です...
- ...図書館はあなたが近づくことができる本当の人です!
ヘッダとライブラリはどのように連携するのですか?これはすべてアプリケーションを構築するために必要なステップです。まず、機能とインターフェースの説明を収集します(別名。コンパイル済み)次に作成するコードは次のとおりです。接続済み実際のインターフェイスと機能を実装するライブラリ。
図書館自体しなければならない埋め込みヘッダにコンパイル(引用する)図書館へ。実際に例を見るとわかります。単純な静的ライブラリの作成方法。
したがって、あなたの質問に対する答えは次のとおりです。ヘッダーとライブラリ名の間に保証された関係はありません。(または、少なくともこれまでは見つかりませんでした。また参照してください。この参照)。そして、それらをどのように一致させるかを見つけることは、パッケージまたはソースコードに何があるのかを理解する問題です。
実際には、次のようにしてこれを証明できます。
$ echo '#include<errno.h> int main(){return 0;}' | gcc -S -lc
これはlibcに対してコンパイルしていますが、libcの一部であるヘッダー名が異なることを示します。
これを示す別の例は#include <math.h>
の一部ですが、libc
実際の実装はにあるのでコンパイルされたlibm.so.6
コードを見ることができるということですgcc -lm
。
$ apt-file find /lib/x86_64-linux-gnu/libm.so.6
libc6: /lib/x86_64-linux-gnu/libm.so.6
関連する.soまたは.aライブラリファイルを探す
多くの謎は文書を通して解決することができます。一度見ようgcc
リンクオプションに関するドキュメント(参考までに太字は私が強調したものです):
- 図書館
-l ライブラリ
リンク時にlibraryという名前のライブラリを検索してください。 (ライブラリを別々のパラメータとして使用する2番目のオプションは、POSIX互換のみのためであるため推奨されません。)
-l オプションはGCCによってリンカーに直接渡される。正確な詳細についてはリンカのドキュメントをご覧ください。以下の一般的な説明はGNUリンカに適用されます。
いいですね。gcc
実際にはライブラリ自体を見つけることではありません。これがリンカーの役割です。しかし、読んでみましょう。
リンカーの検索標準ディレクトリ一覧図書館用。検索されたディレクトリには、複数の標準システムディレクトリと-Lで指定されたディレクトリが含まれます。
したがって、標準ディレクトリのリストがあります。そうですね、範囲が狭くなりました。このリストはどのように入手できますか?一方通行 そのうちの1つがまさに使い方ですが、ldconfig -v
ユーザーが親切に説明してください。トロトリウム
ただし、gcc
ドキュメントでは次のように詳細に説明します。
静的ライブラリは、liblibrary.aに似たファイル名を持つオブジェクトファイルのアーカイブです。一部のターゲットは通常、liblibrary.soに似た名前の共有ライブラリもサポートしています。静的ライブラリと共有ライブラリの両方が見つかると、-staticオプションを使用しない限り、リンカは最初に共有ライブラリをリンクします。
コマンドでこのオプションを作成する場所はさまざまです。リンカは、指定された順序でライブラリとオブジェクトファイルを検索して処理します。したがって、「foo.o -lz bar.o」は、foo.o ファイルの後、bar.o の前でライブラリ「z」を検索します。 bar.oが "z"の関数を参照している場合、その関数はロードされない可能性があります。
つまり、実際に指示し、次にgcc
行うld
ことはファイルを見つけることですlibxi.so
(したがって共有オブジェクトの拡張)またはlibxi.a
標準パスのリストにあります。私たちは何かを保存しましたが、/opt
リンカーld
がそれについて知らない場合は、何でも渡しても-l
機能しません。
libwhatever.so
許可された答えは、そのライブラリの偽装のDebianパッケージ名に対応するライブラリの偽装のDebianパッケージ名を持つことによってそれを暗示するようです。しかし、私はこのような小さな詳細がなければ、私の不必要なニーズに合ったDebianパッケージングについて十分に知っているので、これを確認または拒否することはできません。私が知っているすべてはld
aptがキャッシュの再構築を引き起こす可能性がある。
ld
実際、これらのすべてのディレクトリがキャッシュにあることを認識することも重要です/etc/ld.so.cache
。したがって、ディレクトリがキャッシュから削除されると、リンカはライブラリが存在するかどうかを知りません。
もちろん、上記のすべての理論を例に基づいてテストしたい場合は、libxi-devel
次のようにします。
$ dpkg-query -L libxi-dev | grep -i '.so'
/usr/share/man/man3/XIDefineCursor.3.gz
/usr/lib/x86_64-linux-gnu/libXi.so
/usr/share/man/man3/XIUndefineCursor.3.gz
次に、検索ディレクトリのリストにldconfig
あることを確認してください/usr/lib/x86_64-linux-gnu
。それは次のとおりです。
$ ldconfig -p | grep libXi.so
libXi.so.6 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libXi.so.6
libXi.so.6 (libc6) => /usr/lib/i386-linux-gnu/libXi.so.6
libXi.so (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libXi.so
.h
今、このファイルも役に立たないのでしょうか?という質問が提起されます。いいえ、gcc
明らかにコンパイル時に存在する必要があります(インクルードgcc
パスが実際に確認され、一部のライブラリはヘッダファイルのみにすることができます。)
$ mv /usr/include/X11/extensions/XInput.h /tmp
$ echo '#include <X11/extensions/XInput.h> void main(){return 0;}' | gcc -lXi -E -
# 1 "<stdin>"
# 1 "<built-in>"
# 1 "<command-line>"
# 31 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 32 "<command-line>" 2
# 1 "<stdin>"
<stdin>:1:36: warning: extra tokens at end of #include directive
<stdin>:1:10: fatal error: X11/extensions/XInput.h: No such file or directory
compilation terminated.
答え3
これは、他のディストリビューションに対応するツールを収集するために使用されるコミュニティウィキです。破力の方法。自由に編集できますが、検索ができるようにアルファベット順に並べておいてください。
アーチ
pkgfile
リポジトリで使用され、extra
ヘッダーファイル名を引数として渡します。
例:
$ pkgfile XInput.h
extra/libxi
extra/nx-headers
ダーバン
(そしてDebian ベースのすべて使用dpkg
)
apt-file search
ヘッダーファイル名は覆われたように。
ルート図
warl0ckの他の質問で述べたようにpfl
、パッケージを使用するプログラムe-file
、またはPortageファイルリストのWebベース検索。