2012-03-18 2 views
1

プラットフォーム固有のコードを条件付きでコンパイルした後に、リンクエラーが発生しました(multiple definition)。CMakeでリンクエラーを取得する

私のプロジェクトは、このようにレイアウトされています。私は、オペレーティングシステムを検出し、定義するためにCMakeのでイントロスペクションを設定

#if defined(LIBRARY_PLATFORM_LINUX) 
    #include "native/impl.linux.c" 
#elsif defined(LIBRARY_PLATFORM_WIN32) 
    #include "native/impl.win32.c" 
#endif 

general.cファイルの先頭に

/ 
|__+ include/ 
| |__+ native/ 
| | |__ impl.h 
| | 
| |__ general.h 
| 
|__+ src/ 
    |__+ native/ 
    | |__ impl.linux.c 
    | |__ impl.win32.c 
    | 
    |__ general.c 

対応する定数。これが問題を引き起こしているもので、どうやら

file(GLOB_RECURSE LIBRARY_SOURCE_FILES "${PROJECT_SOURCE_DIR}/src/*.c") 

:事は、私はすべてのディレクトリに1つのCMakeLists.txtファイルを維持したくなかったので、私は単純にすべての.cファイルas suggested in this answerをグロビングされています。コード#include dをgeneral.cにコンパイルしているように見え、個々のファイルはsrc/native/impl.*.cです。

CMakeFiles/lib.dir/src/native/impl.linux.c.o: In function `declared_in_impl_h': 
impl.linux.c:(.text+0x0): multiple definition of `declared_in_impl_h' 
CMakeFiles/lib.dir/src/general.c.o:general.c:(.text+0x0): first defined here 

この状況をどのように解消できますか?

+0

'impl。*'ファイルに異なる拡張子を使用してください。 –

答えて

2

この種のクロスプラットフォームの状況のベストプラクティスは、Linux用とWindows用の2つのライブラリを作成し、条件付きインクルードを行うことを中止することです。各プラットフォームは関連するライブラリのみをコンパイルしてリンクします。

cmakeでこれを行うには、グロビングを止めて各ファイルをインクルードすることをお勧めします。 が混乱し、再コンパイルする必要があることに気付かない状況がいくつかあります。あなたは、変化しないレガシーコードがその問題を持たないという議論をすることができます。

本当にこれらのことを避けたいのであれば、私はインクルードされたコードをcファイルの代わりにヘッダに入れます。あなたは本当に人々がそれが通常のヘッダーのように使用すべき何かのために混乱を取得しないようにインクルードガードが欲しいわけではありません。このような行動を警告するために、ファイルに複数のコメントを入れてください。

+0

私はそれを考慮していませんでした。ここで言及すると、別々のライブラリがより効率的に聞こえます。してください、あなたは精巧にできますか?実装自体を同じプロジェクト内の共有ライブラリにすることは合理的ですか?彼らは静的にリンクされるべきですか? –

+0

@MatheusMoreira Hehe、効率的ではありません。それぞれのファイルは1つの特定のことを行いますので、何が起こっているかについて混乱が少なくなります。通常は、それぞれの実装を独自のライブラリに格納し、cmakeにはどちらか一方のみを含めるようにします。静的な部分は通常動かない部分ですが、実際には関係ありません。あなたが思うものは、プロジェクトにとって最も理にかなっています。 –

+0

@MatheusMoreira私はC++の人ですから、Cのベストプラクティスには過剰売却があるかもしれません。私はCでトリッキーなことがある状況を見ることができました。 –