2012-06-21 8 views
17

私はcmakeをproject/にあるproject/buildのように、ディレクトリ 'build'にビルドしようとしています。スクリプトをラップせずにソースをビルドするには?

私は私が行うことができます知っている:

mkdir build 
cd build 
cmake ../ 

が、それは面倒です。私はそれをスクリプトに入れて呼び出すことができますが、cmake(-G "MSYS Makefiles"のように)に異なる引数を与えるのは不愉快です。そうしないと、このファイルを各プラットフォームで編集する必要があります。

私は、メインのCMakeLists.txtにSET(CMAKE_OUTPUT_DIR build)のようなことを行うことをお勧めします。これが可能であると私に教えてください。もしそうなら、どうですか?あるいは、異なる引数を簡単に指定できるソースビルドメソッドからのいくつかのアウト?

+0

私はあなたと同じプロジェクトアーキテクチャを持っています。私の "ビルド"ディレクトリは常にここにあります。私は人格的に、_cmake .._と入力するのはそれほど大したことではないことに気づいています。 – Offirmo

答えて

26

あなたはcmakeを起動すると、ソースとバイナリのディレクトリを指定するには、文書化されていないcmakeのオプション-H-Bを使用することができます。

cmake -H. -Bbuild -G "MSYS Makefiles" 

これは、現在のフォルダにCMakeLists.txtを探し、buildフォルダを作成します(それならばまだ存在していない)。

+3

良いオプション。しかし、マックスは "それはcmakeに異なる議論を提供するのは不愉快だ"と言った。彼はCMakeListにそれを望んでいる。 – Offirmo

4

私が最近見つけた解決策は、ソース外のビルドコンセプトをMakefileラッパーと組み合わせることです。私のトップレベルのCMakeLists.txtファイルで

、私はソースを防止するために、以下を含むビルド:

if (${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR}) 
    message(FATAL_ERROR "In-source builds not allowed. Please make a new directory (called a build directory) and run CMake from there. You may need to remove CMakeCache.txt.") 
endif() 

をその後、私はトップレベルのMakefileを作成し、次のものがあります。

# ----------------------------------------------------------------------------- 
# CMake project wrapper Makefile ---------------------------------------------- 
# ----------------------------------------------------------------------------- 

SHELL := /bin/bash 
RM := rm -rf 
MKDIR := mkdir -p 

all: ./build/Makefile 
    @ $(MAKE) -C build 

./build/Makefile: 
    @ ($(MKDIR) build > /dev/null) 
    @ (cd build > /dev/null 2>&1 && cmake ..) 

distclean: 
    @ ($(MKDIR) build > /dev/null) 
    @ (cd build > /dev/null 2>&1 && cmake .. > /dev/null 2>&1) 
    @- $(MAKE) --silent -C build clean || true 
    @- $(RM) ./build/Makefile 
    @- $(RM) ./build/src 
    @- $(RM) ./build/test 
    @- $(RM) ./build/CMake* 
    @- $(RM) ./build/cmake.* 
    @- $(RM) ./build/*.cmake 
    @- $(RM) ./build/*.txt 

ifeq ($(findstring distclean,$(MAKECMDGOALS)),) 
    $(MAKECMDGOALS): ./build/Makefile 
    @ $(MAKE) -C build $(MAKECMDGOALS) 
endif 

デフォルトターゲットallは、makeと入力して呼び出し、ターゲット./build/Makefileを呼び出します。

ターゲット./build/Makefileが最初に行うことは、mkdir -pの変数である$(MKDIR)を使用してbuildディレクトリを作成することです。ディレクトリbuildは、アウトソースビルドを実行する場所です。既に存在する可能性があるディレクトリを作成しようとした場合、mkdirが私たちに悲鳴を上げないように、引数-pを提供します。

ターゲット./build/Makefileの2番目のことは、ディレクトリをbuildディレクトリに変更し、cmakeを呼び出すことです。

ターゲットに戻って、$(MAKE) -C buildを呼び出します。は、makeに対して自動的に生成されるMakefile変数です。 make -Cは何もする前にディレクトリを変更します。したがって、$(MAKE) -C buildを使用することは、cd build; makeを実行することと同じです。make allmakeで、このMakefileのラッパーを呼び出して、要約する

がやっと同等です:

mkdir build 
cd build 
cmake .. 
make 

ターゲットdistcleanmake -C build cleanそして、cmake ..を呼び出し、そして最後に、buildディレクトリからすべての内容を削除します。私はこれがまさにあなたがあなたの質問で要求したものだと信じています。

メイクファイルの最後の部分は、ユーザー指定のターゲットがdistcleanであるかどうかを評価します。そうでなければ、呼び出す前にディレクトリをbuildに変更します。これは非常に強力です。たとえば、ユーザーがmake cleanと入力すると、Makefileはこれをcd build; make cleanに相当するものに変換します。

結論として、このMakefileラッパーは、必須のアウトソースビルドCMake構成と組み合わせて、ユーザーがコマンドcmakeと対話する必要がないようにします。この解決法はまた、すべてのCMake出力ファイルをbuildディレクトリから削除する洗練された方法を提供します。

P.S. Makefileでは、接頭辞@を使用してシェルコマンドの出力を抑制し、接頭辞@-を使用してシェルコマンドのエラーを無視します。 distcleanターゲットの一部としてrmを使用すると、ファイルが存在しない場合(すでにコマンドラインを使用してrm -rf buildで削除されているか、最初に生成されたことがない場合)、エラーが返されます。このリターンエラーは、Makefileを強制的に終了させます。これを防ぐためにプレフィックス@-を使用します。すでにファイルが削除されていてもかまいません。私たちはMakefileが残り続けていくことを望んでいます。

メモ:プロジェクトのビルドに可変数のCMake変数を使用すると、このMakefileは機能しないことがあります。たとえば、cmake .. -DSOMEBUILDSUSETHIS:STRING="foo" -DSOMEOTHERBUILDSUSETHISTOO:STRING="bar"です。このMakefileは、cmake ..を入力するか、(Makefileに含めることができる)一貫した数の引数をcmakeで提供することによって、一貫した方法でCMakeを呼び出すことを前提としています。

最後に、クレジットが支払期限であるクレジット。このMakefileラッパーは、C++ Application Project Templateによって提供されるMakefileから適合されました。

この回答は当初の投稿hereです。私はそれもあなたの状況に適用されたと思った。

1

以前の回答に基づいて、私はソース外のビルドを実施するために含めることができる次のモジュールを書きました。ユーザーは怠け者で、単にcmake .を実行すると、彼らは常にFATAL_ERRORが表示されます

  • set(DEFAULT_OUT_OF_SOURCE_FOLDER "cmake_output") 
    
    if (${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR}) 
        message(WARNING "In-source builds not allowed. CMake will now be run with arguments: 
         cmake -H. -B${DEFAULT_OUT_OF_SOURCE_FOLDER} 
    ") 
    
        # Run CMake with out of source flag 
        execute_process(
          COMMAND ${CMAKE_COMMAND} -H. -B${DEFAULT_OUT_OF_SOURCE_FOLDER} 
          WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) 
    
        # Cause fatal error to stop the script from further execution 
        message(FATAL_ERROR "CMake has been ran to create an out of source build. 
    This error prevents CMake from running an in-source build.") 
    endif() 
    

    この作品は、しかし、私はすでに2つの欠点に気づきました。私はCMakeが他の操作をして早期に終了するのを防ぐ別の方法を見つけることができませんでした。

  • cmakeに元のコールに渡された任意のコマンドライン引数は、「アウト・オブ・ソースビルドコール」に渡されることはありません。

このモジュールを改善するための提案は大歓迎です。

関連する問題