2

だから私はMakefileを使ってプロジェクトを構築しようとしていますが、一般的にmakefileは比較的新しいです。たくさんの関数をリンクするときに複数の定義エラーが発生しますが、それは私のmakefileが原因であると確信しています。プロジェクトはかなり大きいので投稿できませんが、makefileは下にありますが、明らかに間違っているものはありますか?

+ヘッダーで宣言されたいくつかの関数があり、それらの定義をcppに移動すると、それらの関数がリンカーエラーから削除されました-しかし、すべての関数に対してこれを行うことはできません(編集:複数定義されている残りの関数はそうではありませんヘッダーでは、標準でcpp / ccファイルにあり、「すべてに対してこれを行うことはできません」と言って、すべてがそのようであったことを意味します。申し訳ありませんが、大部分は編集できないコードベースです。コードにエラーはないはずですが、追加せずに別のプロジェクトで正常にビルドされているため(いずれもリンカーエラーを引き起こしていません)、それは私のmakefileである必要があると思いますが、何が間違っているのかわかりません。何か案は?

    # Compiler
    CXX = g++

    # Linker settings
    LDFLAGS = -lGL -lGLU -lXext -lX11        

    # Executable name
    EXEC = SplotchPreviewer

    # Optimizations for compilation
    OPTIMIZE = -std=c++98 -pedantic -Wno-long-long -Wfatal-errors -Wextra -Wall -Wstrict-aliasing=2 -Wundef -Wshadow -Wwrite-strings -Wredundant-decls -Woverloaded-virtual -Wcast-qual -Wcast-align -Wpointer-arith -O2 -g


    # Pre-processor settings
    CPPFLAGS = $(OPTIMIZE) -I. -Icxxsupport -Ic_utils

    # Default Splotch objects
    OBJS_SPLOTCH_DEFAULT =  cxxsupport/error_handling.o reader/mesh_reader.o cxxsupport/mpi_support.o cxxsupport/paramfile.o \
                    cxxsupport/string_utils.o cxxsupport/announce.o reader/gadget_reader.o reader/millenium_reader.o \
                    reader/bin_reader.o reader/tipsy_reader.o splotch/splotchutils.o splotch/scenemaker.o \
                    cxxsupport/walltimer.o c_utils/walltime_c.o booster/mesh_creator.o booster/randomizer.o \
                    booster/p_selector.o booster/m_rotation.o cxxsupport/paramfile.o cxxsupport/error_handling.o \
                     c_utils/walltime_c.o cxxsupport/string_utils.o cxxsupport/announce.o \
                    cxxsupport/walltimer.o

    # Default Previewer objects
    OBJS_PREVIEWER_DEFAULT = main.o previewer/Previewer.o previewer/libs/core/Parameter.o previewer/libs/core/ParticleSimulation.o \
                     previewer/libs/core/WindowManager.o previewer/libs/core/Camera.o previewer/libs/core/ParticleData.o \
                     previewer/libs/core/MathLib.o previewer/libs/core/FileLib.o previewer/libs/events/OnQuitApplicationEvent.o \
                     previewer/libs/events/OnKeyReleaseEvent.o previewer/libs/events/OnKeyPressEvent.o previewer/libs/events/OnExposedEvent.o \
                     previewer/libs/events/OnButtonReleaseEvent.o previewer/libs/events/OnButtonPressEvent.o previewer/libs/core/Texture.o \
                     previewer/libs/animation/AnimationSimulation.o

    #temp force render method
    RENDER_METHOD = FFSDL
    # Current build specific objects
    ifeq ($(RENDER_METHOD),FFSDL)

    OBJS_BUILD_SPECIFIC = previewer/libs/renderers/FF_DrawList.o     previewer/libs/materials/FF_ParticleMaterial.o

    endif


    # All objects for this build
    OBJS = $(OBJS_SPLOTCH_DEFAULT) $(OBJS_PREVIEWER_DEFAULT) $(OBJS_BUILD_SPECIFIC)

    # Rules (note: object files automatically removed when building)

    .SUFFIXES: .o .cc .cxx .cpp

    .cpp.o:
        $(CXX) -c $(CPPFLAGS) -o "$@" "$<"  

    .cc.o:
        $(CXX) -c $(CPPFLAGS) -o "$@" "$<"

    .cxx.o:
        $(CXX) -c $(CPPFLAGS) -o "$@" "$<"


    $(EXEC): $(OBJS)
        $(CXX) $(OBJS) $(LDFLAGS) -o $(EXEC)
        rm $(OBJS)


    clean:
        rm -f $(OBJS)
        rm -f $(EXEC)

私は1つまたは2つの不要なものを切り取ったので、その1つまたは2つのビットはあまり意味がありません(たとえば、1つのメソッドしか使用できないrenderメソッドオプションがあるのはなぜですか)ルールを正しく記述したかどうかについて少しぼんやりしています。これは私の問題の原因になる可能性がありますか?動作しているように見える他のmakefileと同じように見えますが、問題が何であるかはわかりません。誰か考えがありますか?必要に応じて詳細情報を提供できますか?

4

3 に答える 3

7

いくつかの関数をヘッダーで宣言 + 定義し、それらの定義を cpp に移動すると、それらの関数がリンカー エラーから削除されました。

インラインではないように聞こえますが、その場合、プログラムをリンクするときに許可される定義は 1 つだけです。

inline問題を解決するには、ヘッダーの関数定義に追加します。これにより、「1 つの定義規則」が緩和され、すべての定義が同一である限り、これらの関数を複数の翻訳単位で定義できるようになります。

更新:また、あなたの定義にOBJS_SPLOTCH_DEFAULTは重複が含まれています。cxxsupport/paramfile.o繰り返しますが、他にもあるかもしれません。重複を削除する必要があります。このような長いリストをアルファベット順に並べておくことをお勧めします。これにより、検索が容易になり、重複を見つけやすくなります。

于 2012-08-13T18:34:11.380 に答える
1

問題はメイクファイルにはありません。それはここにあります:

いくつかの関数を宣言し、ヘッダーで定義し、それらの定義を cpp に移動すると、リンカー エラーからそれらの関数が削除されましたが、大部分は編集できないコードベースであるため、すべてに対してこれを行うことはできません。

問題は、そのヘッダーを複数のソース ファイルにインクルードすると、関数定義の複数のコピーが取得されることです。これがリンカの不満です。そのため、3 つの選択肢があります。そのコードを使用しないでください (真剣に: 一般的に、それは恐ろしいコーディング方法です)。そのヘッダーを複数のソース ファイルで使用しないでください。または @Mike が提案したように、インラインで追加します。

于 2012-08-13T18:39:03.237 に答える
1

ファイルで定義および宣言された関数がある場合.h、コンパイル オプションまたはinline.

.hこれらのファイルを書き直してルーチンを として宣言できない場合inline、見苦しい解決策は、.hこれらすべてのルーチンを単純に再宣言する (宣言する、気にする、定義しない) 並列を作成することです。すべてのコード#includesは、この並列.hファイルです。

共有コードベースのファイルをまとめた単一の.c/.cppファイルを作成します。#includes.h

.o共有コードベースからの実装をコードベースに公開する結果のシングルをリンクします。

これは醜く、ハックです。私は間違いなく、これよりも@Mikeの答えを使用する人になるでしょう。

于 2012-08-13T18:42:25.850 に答える