0

プロジェクトの Makefile を作成しています。Makefile の次の構造があります。

./Makefile
./classification/Makefile
./misc/Makefile
./APP/Makefile
./qr/libs/Makefile

再帰を行っていmakeます。各ディレクトリには、共有ライブラリを生成する Makefile があります。そのため、./classificationフォルダー内で を生成classification.soし、他のディレクトリに移動します。一般に、それらは次の構造を持っています。

include ../standard_defs.mk

xCFLAGS=$(CFLAGS) -fPIC

SOURCES=help.cpp
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=misc.so

xxDET=detection/$(EXECUTABLE)
export xxDET;

all: $(SOURCES) $(EXECUTABLE)

$(EXECUTABLE): $(OBJECTS) 
    $(CC) $(OBJECTS) -shared -o $@


.cpp.o:
    $(CC) $(xCFLAGS) $< -c

clean:
    rm -f $(OBJECTS) $(EXECUTABLE)

メインの Makefile ( ./Makefile) は次のような構造になっています。

CFLAGS=`pkg-config opencv --cflags`
LDFLAGS=`pkg-config opencv --libs`

include standard_defs.mk

SOURCES=DataFormatDetResult.cpp  InputDataFiles.cpp  InputImage.cpp \
    InputManager.cpp  main.cpp  maths.cpp  misc.cpp

OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=featureExtractor

all: $(LIBS) $(SOURCES) $(EXECUTABLE) 

$(EXECUTABLE): $(OBJECTS)
    make -C misc
    make -C qr/libs
    make -C classification
    make -C APP
    $(CC) $(CFLAGS) $(OBJECTS) -o $@ $(LDFLAGS) misc/misc.so qr/libs/ap.so classification/classification.so APP/app.so

.cpp.o:
    $(CC) $(CFLAGS) $< -c

clean:
    make -C misc clean
    make -C qr/libs clean
    make -C APP clean
    make -C classification clean
    rm -f *.o $(EXECUTABLE)

エラー

メインの Makefile をコンパイルしようとすると、次のリンク エラーが発生しました。

classification/classification.so: undefined reference to `Help::InsertHelpType(std::basic_string<char, std::char_traits<char>, std::allocator<char> >)'
classification/classification.so: undefined reference to `Help::Help()'
collect2: ld returned 1 exit status
make: ** [featureExtractor] Erro 1

misc.soクラスが含まれており、最終的なコンパイルでは見つからないHelpようです。classification.soただし、実行するmake -C ./classification/と、エラーは発生しません。

質問1

このリンクの問題を解決するにはどうすればよいですか?

失敗したソリューション

にリンクしようとしましたが、これmisc.soclassification.soで行っています./classification/Makefile:

$(EXECUTABLE): $(OBJECTS)
    $(CC) $(OBJECTS) -shared -o $@ $(LDFLAGS) ../misc/misc.so

しかし、うまくいきませんでした。私が得たのは新しい警告だけでした

/usr/bin/ld: warning: ../misc/misc.so, needed by classification/classification.so, not found (try using -rpath or -rpath-link)

質問2

このプロジェクトに Makefile を作成するより良い方法はありますか?


EDIT 1:を実行するエラーなしmake -C ./classification/で生成され./classification/classification.so次に、で実行makeすると./、同じエラーが発生します。


編集2:私が走ったときnm --format sysv misc.so | grep Help、私は持っています:

$ nm --format sysv misc.so | grep Help
HelpTypes           |0000000000205120|   D  |            OBJECT|0000000000000038|     |.data
_ZN11HelpControl9PrintHelpEv|0000000000002180|   T  |              FUNC|000000000000082e|     |.text
_ZN11HelpControlC1Ev|00000000000029b0|   T  |              FUNC|0000000000000187|     |.text
_ZN11HelpControlC2Ev|00000000000029b0|   T  |              FUNC|0000000000000187|     |.text
_ZN4Help14InsertHelpTypeESs|0000000000001ac0|   T  |              FUNC|0000000000000126|     |.text
_ZN4Help9PrintHelpEi|0000000000001bf0|   T  |              FUNC|000000000000020d|     |.text
_ZN4HelpC1Ev        |0000000000001e00|   T  |              FUNC|000000000000021a|     |.text
_ZN4HelpC2Ev        |0000000000001e00|   T  |              FUNC|000000000000021a|     |.text
_ZN4HelpD1Ev        |0000000000003090|   W  |              FUNC|000000000000039b|     |.text
_ZN4HelpD2Ev        |0000000000003090|   W  |              FUNC|000000000000039b|     |.text
_ZNSt8_Rb_treeISsSt4pairIKSs4HelpESt10_Select1stIS3_ESt4lessISsESaIS3_EE8_M_eraseEPSt13_Rb_tree_nodeIS3_E|0000000000003430|   W  |              FUNC|0000000000000526|     |.text
4

2 に答える 2

2

再帰的な Makefile を取り除くようにしてください。多少一般的ですが、再帰的な make は本質的に壊れています。それらが一般的である主な理由は、automake と autoconf がある場合にビルドされるものだからです。しかし、autoconf と automake は両方とも、再帰的な make 構造を正しくするために多大な努力を払っており、これらのツールなしで再帰的な make 構造を正しく理解している人はまだ見たことがありません。

たとえば、Cmake が再帰的な makefile を使用する方法など、再帰的な make が本質的に壊れていない用途はごくわずかです。ただし、これらの makefile は自動化されたツールによってビルドされるため、これも手動で正しく行うのは困難です。

編集:これは記事の短い要約です。

再帰的なmakefileの主な問題は、makeが正しい順序で何かを構築するために必要な完全な依存関係グラフを構築できないことです。再帰的な make はもともと、複数のプロジェクトを一度にビルドする必要がある場合を想定しており、それらの間に依存関係はありません。再帰構造全体に依存関係がある限り、make は順序を修正するのを非常に困難にします。最良の場合、システムは構築可能ですが、一部のファイルを編集した後に再構築しようとするとシステムが壊れてしまいます。アプリケーションの一部が編集前にソースからコンパイルされたライブラリに対してリンクされ、別の部分が編集後にソースからコンパイルされたライブラリに対してリンクされたために、再帰的なメイクが台無しになる多くのケースを見てきました。make clean && make.

それ以外の場合、再帰的な make によってビルドが完全に台無しになる可能性があります。これは、そもそもターゲットが完全に間違った順序で実行された場合に当てはまります。これは、通常のビルドが不可能であることを意味します。あなたの例は、それらのケースの1つのようです。あまり詳しく調べていませんが、make は依存関係を完全には認識していないため、必要なすべてのライブラリを正しくビルドしていないようです。

ほとんどの場合、再帰的 make を使用すると、並列 make は完全に不可能になります。少なくとも、確実に使用できる手動の再帰的な make 構造をまだ見ていませんmake -j X

次の 2 つの解決策があります。

  • autotools や cmake などのいずれかのツールで makefile を作成します。ただし、これにはもう 1 つのツールを学習する必要があります。また、これらのツールの使いやすさについても非常に議論されています (少なくとも autotools の場合)。

  • make が完全な依存関係グラフを導出できる 1 つの makefile を提供することで、再帰的な構造を取り除きます。複数のライブラリと自動ソース検出を使用しても、実際には単一のファイルでこれを行う人を見たことがありますが、私はそうしないので、お勧めできません。さらに良いのは、サブディレクトリごとに 1 つずつ、複数のファイルを用意includeし、それらをディレクトリ ツリーのルートにある大きなファイルに結合するために使用することです。この方法では、make はツリーのルートでのみ呼び出すことができますが、依存関係の完全なセットは常に認識されます。この方法は、記事でも推奨されています。

于 2012-06-15T16:56:13.907 に答える
1

エラーを再現するのに十分な情報が提供されていないため、これには数回の反復が必要になる場合があります。

では、クラスmisc/をテストする方法が必要です。Helpまだ持っていない場合は、その目的のために簡単なコードを次のように記述しますmisc/

//test_help.cpp
#include "help.h"

int main()
{
  Help H;

  return(0);
}

それを試してみてください:

make test_help.o help.o
g++ test_help.o help.o -o test_help
./test_help

次に、ライブラリを使用します。

make misc.so
g++ test_help.o misc.so -o test_help
./test_help

次にtest_help.cpp、上のディレクトリに移動して、そこから試します。

make test_help.o
g++ test_help.o misc/misc.so -o test_help
./test_help

次に、ルールをメインの Makefile に追加します。

test_help: test_help.o
    make -C misc
    $(CC) $(CFLAGS) $< -o $@ misc/misc.so
    ./$@

と試してみてくださいmake clean ; make test_help

于 2012-06-16T14:24:49.570 に答える