web-dev-qa-db-ja.com

g ++がLIBRARY_PATH /../ lib64を検索するのはなぜですか?これはどこに文書化されていますか?

私の_LIBRARY_PATH_環境変数には、カスタムディレクトリ_/cs/public/lib/pkg/opencv/lib_があります。

しかし、_g++ --print-search-dirs_を使用すると、代わりに次のようになります。

_libraries: =
/cs/public/lib/pkg/opencv/lib/x86_64-suse-linux/4.6/:
/cs/public/lib/pkg/opencv/lib/../lib64/:
/usr/lib64/gcc/x86_64-suse-linux/4.6/:
/usr/lib64/gcc/x86_64-suse-linux/4.6/../../../../x86_64-suse-linux/lib/x86_64-suse-linux/4.6/:
/usr/lib64/gcc/x86_64-suse-linux/4.6/../../../../x86_64-suse-linux/lib/../lib64/:
/usr/lib64/gcc/x86_64-suse-linux/4.6/../../../x86_64-suse-linux/4.6/:
/usr/lib64/gcc/x86_64-suse-linux/4.6/../../../../lib64/:
/lib/x86_64-suse-linux/4.6/:
/lib/../lib64/:
/usr/lib/x86_64-suse-linux/4.6/:
/usr/lib/../lib64/:
/cs/public/lib/pkg/opencv/lib/:
/usr/lib64/gcc/x86_64-suse-linux/4.6/../../../../x86_64-suse-linux/lib/:
/usr/lib64/gcc/x86_64-suse-linux/4.6/../../../:
/lib/:
/usr/lib/
_

G ++がこれらの選択肢や他のシステムの場所全体を調べるのはなぜですかbefore _LIBRARY_PATH_変数で明示的に指定したもの、そしてこれはどこに文書化されていますか?

LIBRARY_PATHやLIBRARY_PATH /../ lib64などの前にシステムのデフォルトが検索されたかどうかはわかりますが、g ++はLIBRARY_PATH /../ lib64、システムパス、LIBRARY_PATHの順に配置します。この注文はどこに文書化されていますか?

私のg ++​​バージョンはg++ (SUSE Linux) 4.6.2です

私のOSはopenSUSE 12.1 (x86_64)です

24
user334856

同様の質問がここで行われました: g ++は/lib/../lib/を検索し、次に/ lib /を検索します

これらの恐ろしい検索パスは、コンパイラ自体がビルドしたとき、たとえば構成フェーズ中に、少なくとも部分的に決定されます。 GCCの複数のコピーをインストールし、それぞれがgcc --print-search-dirsに対して異なる結果を与える可能性があるため、環境変数を超えていることは明らかです。また、g++ --print-search-dirsgcc --print-search-dirsの結果が異なることに注意すると、g ++ラッパーも検索パスに影響を与えていることがわかります。構成/ビルドの時差に加えて、GCCは自身の実行可能ファイルが存在するパスを確実に認識しており、そのパスのサブディレクトリを検索します。この錬金術の多くは、GCCのドキュメントに記載されています。
http://gcc.gnu.org/onlinedocs/gcc-4.7.1/gcc/Directory-Options.html#Directory-Options
http://gcc.gnu.org/onlinedocs/gcc-4.7.1/gcc/Environment-Variables.html#Environment-Variables

私の知る限り、GCCの独自のコピーをコンパイルせずにできる最も強力なことは、-Lオプションを使用してカスタムライブラリを指定することです。私がこれを言う理由は、-Lが前に検索されるためです。 LIBRARY_PATH(環境変数に関する上記のリンクを参照)。許容範囲を広げるために、.bashrcファイルに-Lオプションを含むg ++のエイリアスを追加できます。

明確な答えが必要な場合は、GCCソースコードのコピーをダウンロードするのが1つの方法です。たとえば、gcc.cには、次の非常に示唆に富むコメントが表示されます。

/* Build a list of search directories from PATHS.
   PREFIX is a string to prepend to the list.
   If CHECK_DIR_P is true we ensure the directory exists.
   If DO_MULTI is true, multilib paths are output first, then
   non-multilib paths.
   This is used mostly by putenv_from_prefixes so we use `collect_obstack'.
   It is also used by the --print-search-dirs flag.  */

ただし、コメントに続く機能はあまり明白ではありません。

10

これは、動作中のmultilibです。これは、単一のマシン上に複数のアーキテクチャ用のライブラリ(コンパイルおよびビルドツールチェーン全体)を含めることを可能にするメカニズムです。 このWiki は、「multilibサフィックスは、GCCによってライブラリが検索されたすべてのディレクトリに追加され、-Lオプションを介してリンカーに渡されます。リンカー自体はmultilibに関する特別な知識を持たず、続行します。 -Lパスにライブラリが見つからない場合は、デフォルトの検索ディレクトリを参照します。1回のコンパイルで複数の直交ABI変更オプションを使用する場合は、複数のmultilibサフィックスを連続して使用できます。」.

したがって、上記の説明によれば、アーキテクチャマーカー文字列またはそのさまざまなバリアントは、デフォルトパスとカスタムパスを区別しないため、コンパイラが受け取る各ライブラリ検索パスに追加されます。カスタムパスが最初の行にありますが、他のパスと同じ「拡張」プロセスが実行されます。

I386互換性を処理する必要があるため、現在、ほとんどのx64ディストリビューションでmultilibメカニズムがデフォルトで使用されているようです。これは、実際には、ほとんどのインストールを意味します。

7

この回答は、GCCとClangの両方の検索パスの動作を要約しようとしています。

GCC

パスを含める:次の形式のコマンドラインの場合:

CPLUS_INCLUDE_PATH=EDIR g++ -IIDIR -isystemSDIR

次のディレクトリのリストは、#include <...>の検索パスとして使用されます。

IDIR                                           # '-I' directories.
SDIR                                           # '-isystem' directories.
EDIR                                           # *_INCLUDE_PATH directories.
GCCDIR/include/c++/GCCVER                      # libstdc++ directory (C++).
GCCDIR/include/c++/GCCVER/GCCARCH              # libstdc++ directory (C++).
GCCDIR/include/c++/GCCVER/backward             # libstdc++ directory (C++).
GCCDIR/lib/gcc/GCCARCH/GCCVER/include          # GCC Arch-specific directory.
/usr/local/include/GCCARCH                     # Local Arch-specific include directory.
/usr/local/include                             # Local include directory.
GCCDIR/include                                 # GCC include directory.
GCCDIR/lib/gcc/GCCARCH/GCCVER/include-fixed    # GCC include-fixed directory.
/usr/include/GCCARCH                           # System include Arch-specific directory.
/usr/include                                   # System include directory.

ライブラリパス:次の形式のコマンドラインの場合:

LIBRARY_PATH=EDIR gcc -BBDIR -LLDIR

次の引数がリンカーに渡されます。

-LLDIR                                         # '-L' directories.
-LBDIR                                         # '-B' directories.
-LEDIR/../libXX                                # Multilib directories from LIBRARY_PATH.
-LGCCDIR/lib/gcc/GCCARCH/GCCVER                # GCC Arch-specific library directory.
-LGCCDIR/libXX                                 # GCC multilib library directory.
-L/libXX                                       # System multilib library directory.
-L/usr/libXX                                   # System multilib library directory. 
-LEDIR                                         # LIBRARY_PATH directories.
-LGCCDIR/lib                                   # Other GCC libraries.

Clang

パスを含める:次の形式のコマンドラインの場合:

CPLUS_INCLUDE_PATH=EDIR clang++ --gcc-toolchain=GCCDIR -BBDIR -IIDIR -isystemSDIR

次のディレクトリのリストは、#include <...>の検索パスとして使用されます。

IDIR                                           # '-I' directories.
SDIR                                           # '-isystem' directories.
EDIR                                           # *_INCLUDE_PATH directories.
 # If -stdlib=libstdc++ is used:
   GCCDIR/include/c++/GCCVER                   # libstdc++ directory from the selected GCC toolchain (C++).
   GCCDIR/include/c++/GCCVER/GCCARCH           # libstdc++ directory from the selected GCC toolchain (C++).
   GCCDIR/include/c++/GCCVER/backward          # libstdc++ directory from the selected GCC toolchain (C++).
 # If -stdlib=libc++ is used:
   CLANGDIR/include/c++/v1                     # libc++ directory (C++).
/usr/local/include                             # Local include directory.
CLANGDIR/lib/clang/CLANGVER/include            # Clang include directory.
/include                                       # System include directory.
/usr/include                                   # System include directory.

ライブラリパス:次の形式のコマンドラインの場合:

LIBRARY_PATH=EDIR clang --gcc-toolchain=GCCDIR -BBDIR -LLDIR    

次の引数がリンカーに渡されます。

-LLDIR                                         # '-L' directories.
-LGCCDIR/lib/gcc/GCCARCH/GCCVER                # GCC Arch-specific library directory.
-LGCCDIR/libXX                                 # GCC multilib library directory.
-L/libXX                                       # System multilib library directory.
-L/usr/libXX                                   # System multilib library directory.
-LGCCDIR/lib                                   # Other GCC libraries.
-LCLANGDIR/lib                                 # Clang libraries.
-L/lib                                         # System library directory.
-L/usr/lib                                     # System library directory.
-LEDIR                                         # LIBRARY_PATH directories.

概要

インクルードの検索パスは、GCCとClangの両方でほぼ同じです。どちらの場合もCフロントエンドが使用されている場合、C++固有のパスは省略されます。ライブラリ検索パスは、GCCとClangの間で大幅に異なります。特に、GCCフロントエンドでの-Bディレクトリの存在とLIBRARY_PATHの奇妙な操作です。

ライブラリの検索パスは、CフロントエンドとC++フロントエンドの両方で同じです。他のライブラリ検索パスは、リンカー自体によって導入されます。次の抜粋は、GNU BinutilsのVanillaリンカースクリプトからのものです。

# Multilib library directories.
SEARCH_DIR("BINUTILSDIR/BINUTILSARCH/libXX");
SEARCH_DIR("BINUTILSDIR/libXX");
SEARCH_DIR("/usr/local/libXX");
SEARCH_DIR("/libXX");
SEARCH_DIR("/usr/libXX");
# Traditional library directories.
SEARCH_DIR("BINUTILSDIR/BINUTILSARCH/lib");
SEARCH_DIR("BINUTILSDIR/lib");
SEARCH_DIR("/usr/local/lib");
SEARCH_DIR("/lib");
SEARCH_DIR("/usr/lib");

また、ライブラリの依存関係ではなく内部で検索されることに注意する必要があります。上記のディレクトリ。これらは、リンカに渡された-rpathおよび-rpath-linkオプションのみに依存します。そうでない場合、デフォルトのシステムライブラリパスから解決されます。したがって、正しいライブラリがリンクされていることを保証するために、-L引数と-rpath-link引数の両方を生成すると便利な場合があります。

最後に、特別なファイル(CRTオブジェクトなど)は-Bディレクトリでのみ検索されます。 Clangでは、選択したGCCツールチェーン内で特別なファイルも検索されます。その他の要因(仕様ファイル、ディストリビューション固有の構成)により、上記の一部またはすべてが変更される場合があります。

1
alecov

私はまったく同じ問題を抱えています:

Fedora 17, gcc 4.7 and gcc 4.3
CentOS 6.3, gcc 4.4
Unubuntu 12, gcc 4.6

したがって、これはほとんどのgccバージョンで問題になっているようです。おそらく、この奇妙な振る舞いは、少なくとも this によれば、gcc4.2で最初に現れました。

スペックを複製して遊んでみました。プラットフォームに応じて、*multilib仕様を使用して特定の文字列を追加しているようです。たとえば、私の元のspacは次のようになりました。

*multilib:
. !m64 !m32;64:../lib64 m64 !m32;32:../lib !m64 m32;

64:../lib6464:../libに変更すると、../lib64の代わりにgccが../libを追加しました。しかし、*multilibやその他の仕様の意味を完全に解読することはできませんでした。

1