3

makeautotools (このプロジェクトではまだ使用していません)に関する私の知識は、長期間にわたる多くのグーグルと実験にもかかわらず、せいぜい初歩的なものです。私は以下のようなソース階層を持っており、可能な限りシームレスに構築する方法を見つけようとしています。

アプリケーションは、app/srcの下のさまざまなサブフォルダーにソースを持つメインアプリケーションで構成されています。これらは、そのフォルダーのルートにあるそれぞれのMakefileを使用して構築されます。

次に、それぞれが独自のMakefileを持つapp/toolsの下の異なるフォルダーに常駐する他の複数のユーティリティがあります。

app/src/module1/file1.cpp
app/src/module1/file1.hpp
app/src/module2/file2.cpp
app/src/module2/file2.hpp
app/src/module3/file3.cpp
app/src/module3/file3.hpp
app/src/main.cpp
app/src/main.hpp
app/src/Makefile
app/tools/util1/file1.cpp
app/tools/util1/file1.hpp
app/tools/util1/Makefile
app/tools/util2/file2.cpp
app/tools/util2/file2.hpp
app/tools/util2/Makefile

私にとっての問題は、これらのツールの一部がapp / srcソースフォルダー内のソースファイルに依存しているが、前処理マクロEXTERNAL_TOOLが有効になっていることです。そのため、メインアプリとさまざまなユーティリティのコンパイルから生成されたオブジェクトファイルには互換性がありません。

現在、プロジェクトの各部分をビルドするには、その間にあるソースツリーをクリーンアップする必要があります。これは苦痛であり、確かに私が最終的に望んでいることではありません。これを解決するための最善の方法は何でしょうか?私が実践できなかったアイデアは次のとおりです。

  1. プロジェクトの各部分に個別のビルドディレクトリ
  2. 外部ツールを構築するとき、メインアプリのソースツリーでオブジェクトファイルに何らかの方法でタグを付けます(util.file1.o?)

make/autotoolsをマスターするのに必要な時間と忍耐力があるかどうかはわかりません。他のビルドツール(scons?cmake?)の1つで、この種のタスクを簡単に実行できるでしょうか?もしそうなら、どれですか?

更新:これは私が今持っているものです

SOURCES := util1.cpp util2.cpp util3.cpp \
    ../../src/module1/file1.cpp \
    ../../src/module1/file2.cpp \
    ../../src/module1/file3.cpp \
    ../../src/module2/file4.cpp \
    ../../src/module3/file5.cpp \
    ../../src/module3/file6.cpp \
    ../../src/module4/file7.cpp \
    ../../src/module4/file8.cpp \
    ../../src/module3/file9.cpp \
    ../../src/module4/file10.cpp \
    ../../src/module5/file11.cpp \
    ../../src/module3/file12.cpp \
    ../../src/module1/file13.cpp \
    ../../src/module3/file14.cpp \
    ../../src/module3/file15.cpp

OBJECTS = $(join $(addsuffix .util/, $(dir $(SOURCES))), $(notdir $(SOURCES:.cpp=.o)))

.PHONY: all mkdir
all: util
util: $(OBJECTS)
    $(CXX) $(CXXFLAGS) $(OBJECTS) $(LIBS) -o util

$(OBJECTS): | mkdir
    $(CXX) -c $(CXXFLAGS) -o $@ $(patsubst %.o,%.cpp,$(subst .util/,,$@))

mkdir:
    @mkdir -p $(sort $(dir $(OBJECTS)))

clean:
    -@rm -f $(OBJECTS) util
    -@rmdir $(sort $(dir $(OBJECTS))) 2>/dev/null

私はこれを大規模なグーグルSOブラウジングの後に思いついた。これは機能しているように見えますが、この部分は特に良いとは思えません(ちょっとしたハックのように感じます):

$(OBJECTS): | mkdir
    $(CXX) -c $(CXXFLAGS) -o $@ $(patsubst %.o,%.cpp,$(subst .util/,,$@))

特に、以前にソースからオブジェクトのリストを作成し、接尾辞を追加しているという事実にはあまり熱心ではありませんが、ここでは逆のことをしているだけです。私はそれを他の方法で機能させることができなかったようです。

4

2 に答える 2

5

CMakeにはコマンドがadd_definitionsありremove_definitionsます。それらを使用して、プロジェクトのさまざまな部分のマクロを定義できます。

# building tools #
add_definitions(-DEXTERNAL_TOOL)
add_subdirectory($TOOL1$ $BUILD_DIR$)
add_subdirectory($TOOL2$ $BUILD_DIR$)
...

# building main app #
remove_definitions(-DEXTERNAL_TOOL)
add_executable(...)
于 2013-02-07T08:21:00.340 に答える
3

これは、SCons を使用するとかなり簡単に実行できます。さまざまなプリプロセッサ マクロでビルドされたオブジェクトのビルド ディレクトリ階層が必ず必要になります。SCons 用語では、このようなビルド ディレクトリを作成することを variant_dir と呼びます。次の SCons 階層ビルド構造をお勧めします。

app/SConstruct
app/src/module1/file1.cpp
app/src/module1/file1.hpp
app/src/module2/file2.cpp
app/src/module2/file2.hpp
app/src/module3/file3.cpp
app/src/module3/file3.hpp
app/src/main.cpp
app/src/main.hpp
app/src/SConscript_modules
app/src/SConscript_main
app/tools/util1/file1.cpp
app/tools/util1/file1.hpp
app/tools/util2/file2.cpp
app/tools/util2/file2.hpp
app/tools/SConscript
app/build/main/
app/build/target1/modules/
app/build/target2/modules/
app/build/tools/utils/

異なるプリプロセッサ マクロを使用して同じソース ファイルをビルドできるようにするには、いくつかの異なる環境で同じファイルをビルドする必要があります。これらの環境は、src/module SConscript スクリプトで設定するか、ルート SConstruct から設定して渡すことができます。src/module SCons スクリプトをモジュール化し、プリプロセッサ マクロを認識しない (不可知論的) ため、2 番目のオプションを好みます。

これは、異なる環境を作成し、サブディレクトリのビルド スクリプトを調整するルート ビルド スクリプトです。

アプリ/SConstruct

defines1 = ['MACRO1']
defines2 = ['MACRO2']

env1 = Environment(CPPDEFINES = defines1)
env2 = Environment(CPPDEFINES = defines2)

includePaths = [
  'src/module1',
  'src/module2',
  'src/module3',
]
env1.Append(CPPPATH = includePaths)
env2.Append(CPPPATH = includePaths)

# Build different versions of the module libs
SConscript('src/SConscript_modules',
           variant_dir = '#build/target1/modules',
           exports = {'env':env1},
           duplicate=0)
SConscript('src/SConscript_modules',
           variant_dir = '#build/target2/modules',
           exports = {'env':env2},
           duplicate=0)

# Build main with env1
SConscript('src/SConscript_main',
           variant_dir = '#build/main',
           exports = {'env':env2},
           duplicate=0)

# Build tools with env2
SConscript('tools/SConscript',
           variant_dir = '#build/utils',
           exports = {'env':env2},
           duplicate=0)

これはメイン app/src/SConscript_main のビルド スクリプトです。

Import('env')

sourceFiles = ['main.cpp']
# If you want to modify the env here, Clone() it first, otherwise
# the changes will be visible to all other SConscripts
env.Program(target = 'main', source = sourceFiles)

これはモジュール libs のビルド スクリプトです。毎回異なる環境 app/src/SConscript_modules で 2 回呼び出されます。

Import('env')

module1SourceFiles = ['file1.cpp']
module2SourceFiles = ['file2.cpp']
module3SourceFiles = ['file3.cpp']

# If you want to modify the env here, Clone() it first, otherwise
# the changes will be visible to all other SConscripts
env.Library(target = 'module1', source = module1SourceFiles)
env.Library(target = 'module2', source = module2SourceFiles)
env.Library(target = 'module3', source = module3SourceFiles)
于 2013-02-07T10:02:55.237 に答える