2

私が抱えていた問題は解決されました。ソリューションが実際に機能する理由についての説明を求めるために、これを投稿しています。私は以前ここで素晴らしいフィードバックを得ました。

私は非常に単純なビルドシステムを使用したレガシーコードベースを持っています。私のプロジェクトは、カスタマイズ、特に共有ライブラリのビルドのためにそれをAutotoolsに移行することです。メインライブラリはCで記述されていますが、Fortranからリンク可能である必要があり(レガシー目的)、F77でいくつかのテストコードとともに配布されます。著者はソースコードをモジュールに編成しました...

src_module1/
src_module2/
...
testc/
testf77/

彼らlib/libmain.aは、src _ * /ディレクトリにコードをコンパイルし、ranlibを使用してオブジェクトをアーカイブすることにより、ライブラリを構築しました。

私の最初のアプローチは、各src _ * /から個別に共有ライブラリを構築し、これらすべてを1つの共有ライブラリに「リンク」することでした。Autotoolsを使用するsrc_module1/Makefile.amと、

noinst_LTLIBRARIES = libmodule1.la
libmodule1_la_SOURCES = ...

他のモジュールについても同様で、最後にlib/Makefile.am必要なのは次のとおりです。

lib_LTLIBRARIES = libmain.la
libmain_la_SOURCES =
libmain_la_LIBADD = $(top_srcdir)/src_module1/libmodule1.la ...

これは完全に機能しているように見えました。ただし、testc /のコードがコンパイルされ、libmain.laに対してリンクされると、「シンボルが見つかりません」というエラーが発行されました。

これはlibtoolまたは共有ライブラリの問題だと考えて、静的のみをビルドし、基本的にすべてをに変更して.laみました。同じ問題。ただし、今回は、libmain.a自体をリンクしようとすると、「ranlib:ライブラリの警告:libmain.a目次が空です(ライブラリ内のオブジェクトファイルメンバーがグローバルシンボルを定義していません)」というエラーに注意してください。.a_LTLIBRARIES_LIBRARIES

私が見つけた解決策はハックのようです。src _ * /ディレクトリのいずれにもMakefileを作成しませんでしたが、代わりにlib /ディレクトリにのみ使用し、そのMakefile.amには次の行がありました。

lib_LTLIBRARIES = libmain.la
libmain_la_SOURCES = [all sources from all ../src_modules/ ]

これはうまくいきました。testc /でコンパイルされたプログラムは、問題なくlibmain.laに対してリンクされています。「モジュール」の1つは、ライブラリ内の他のC関数をラップするFortranバインディングのセットです。testf77 /のFortranコードでさえ、libmain.laに対して適切にリンクされています。

libtoolが共有ライブラリを構築するとどうなるかを誰かが注意深く説明できますか?または、静的ライブラリを構築する場合でも?複数の静的ライブラリをリンクして1つの静的ライブラリを作成できないのはなぜですか?libtool / ranlibが「ソースから」ライブラリをビルドする場合にのみシンボルが使用できるのはなぜですか?そして、共有/静的ライブラリをインストールする、つまり/ usr / local / libに移動するのはどうですか?---そこで何が起こりますか?静的ライブラリと共有ライブラリに関するウィキペディアの記事は、私にとって十分に詳細ではありません。

私の長年の質問を理解するためのあらゆる努力に感謝します。

4

1 に答える 1

2

あなたが最初に試したことはうまくいくはずです。私は常にこの種のセットアップを使用しています(C ++コンテキストで)。これも文書化されており、Automakeテストスイートの一部です(ただし、Fortranではない可能性があります)。

インストールできないlibtoolライブラリ、つまり、で宣言されたライブラリは、 libtoolコンビニエンスライブラリnoinst_LTLIBRARIESと呼ばれます。それは構築されるものに大きな違いをもたらします。Libtoolが共有ライブラリを構築するように構成されている場合でも、libtoolコンビニエンスライブラリは実際には共有ライブラリではありません。アーカイブに保存されているオブジェクトファイルのセットです(後で共有ライブラリで使用できるようにPICとしてコンパイルされます)。 。このオブジェクトのセットを使用して、たとえば共有ライブラリを構築する場合など、どこでもlibtoolコンビニエンスライブラリを使用できます。 noinst_

複数のlibtoolコンビニエンスライブラリがインストール可能なlibtoolライブラリ(yourなどlibmain.la)にLIBADDされる場合、Libtoolは、各コンビニエンスライブラリのオブジェクトを含むアーカイブを解凍し、それらを最終的なライブラリにリンクする必要があります。

ここで注目に値するトラップがあります。コンビニエンスライブラリから共有ライブラリを構築する場合、_SOURCES変数が空の場合、Automakeは使用するリンカーを認識せず、デフォルトでCリンカーになります。Automakeをだまして特定の言語のリンクルールを使用させたい場合はnodist_EXTRA_..._SOURCES、存在する必要のないソースファイルを宣言できます。(例については、AutomakeマニュアルのLibtoolコンビニエンスライブラリのセクションを参照してください。)

多分それはあなたの問題でしたか?一部のモジュールのソースにFortranファイルがある場合(説明では、これらはCファイルのみであることが示されています)、Fortranリンカーはlibmain.la、そのlibtoolライブラリ用に宣言されたソースファイルにFortranファイルが含まれている場合にのみビルドに使用されます。libmain_la_SOURCESまた、が空の場合はCリンカーが使用されます。

そうでなければ、なぜそれが機能しなかったのか分かりません。

あなたの例には小さなエラーがあります:

libmain_la_LIBADD = $(top_srcdir)/src_module1/libmodule1.la

する必要があります

libmain_la_LIBADD = $(top_builddir)/src_module1/libmodule1.la

ライブラリがソースディレクトリに作成されていないためです。ただし、これは単なるタイプミスであり、VPATHのビルドまたは実行を行わない限り、違いはわかりませんmake distcheck


_LIBRARIESLibtoolなしで使用する2回目の試行は、機能しないと予想されます。
_LIBRARIES静的アーカイブを宣言するためにのみ使用できます。この場合_LIBADD、他の静的アーカイブではなく、オブジェクトファイルのみを含めることができます。アーカイブを解凍してそのオブジェクトを別のアーカイブに再利用することは、移植可能にするのが難しい場合があります。この問題に対するAutomakeの答えは、常に次のとおりです。Libtoolをインストールして使用します_LTLIBRARIES(Libtoolは静的ライブラリのみをビルドするように構成できます)。

于 2011-04-08T15:50:42.540 に答える