2016-04-18 8 views
3

ビルドプロセスの一部をテストに合格させようとしています。cmake:ビルドプロセスの一部を正常にテストします。

ここではadd_custom_commandを使用してテストをPOST_BUILDステップとして実行します。

function(register_test NAME) 

    add_test(${NAME} ${NAME}) 

    # make the test run as part of the build process 
    add_custom_command(TARGET ${NAME} POST_BUILD COMMAND ${NAME}) 

endfunction() 

このアプローチの問題は、ターゲットがを構築するときテストにのみ実行されていることである。

$ make 
[ 50%] Built target lib1 
Linking CXX executable ../../Debug/bin/lib1_test 
Running 1 test case... 
main.cpp(8): fatal error: in "lib1_test": 
    critical check lib1() == "lib1" has failed [error != lib1] 

*** 1 failure is detected in the test module "Master Test Suite" 

make[2]: *** [lib1/test/lib1_test] Error 201 
make[1]: *** [lib1/test/CMakeFiles/lib1_test.dir/all] Error 2 
make: *** [all] Error 2 

ターゲットはする必要がない場合ビルドされると、テストは実行されず、ビルドがパスします。ここで

私は変更しないで、ただ

$ make 
[ 50%] Built target lib1 
[100%] Built target lib1_test 

ビルドプロセスを再実行しlib1_testが実際に実行された場合は、テストは失敗します。

$ ./lib1/test/lib1_test 
Running 1 test case... 
main.cpp(8): fatal error: in "lib1_test": 
    critical check lib1() == "lib1" has failed [error != lib1] 

*** 1 failure is detected in the test module "Master Test Suite" 

lib1_testに依存lib1_test.passedターゲットを作ることになり、これを行うには良い方法

は、テストを実行し、テストが合格した場合にのみ作成されます。

を私はlib1_testに依存ターゲットlib1_test.passedを作成するadd_custom_targetを使用してみましたが、成功した場合、ファイルlib1_test.passed作成します:

add_custom_target(${NAME}.passed 
    DEPENDS ${NAME} 
    COMMAND ${NAME} 
    COMMAND ${CMAKE_COMMAND} -E touch ${NAME}.passed) 

を2人の不足がありますが、私が試してみました何

私が現在達成しているもの:

  • テストの実行は通常のビルドプロセスの一部ではありません。
    つまり、makeではありません。 "build"lib1_test.passedです。
    私は明示的にmake lib1_test.passed
  • make lib1_test.passedは関係なく、常にlib1_test.passedlib1_test1

質問よりも新しいかどうかの、lib1_testを実行します述べることがあります。

がどのようにテストの一部の実行を行うことができます失敗したテストは常に再実行されます。

+1

をあなたの願いを取得しない、あなたも 'lib1_test'を実行したいです変更されていない場合は?異なる入力データを取得するか、変更されていない場合はなぜ再実行する必要があるのですか? – fghj

+0

これと反対ではありません - 'lib1_test'を' make'の一部として実行し、 'make'をもう一度入力すると**テストは実行されません。しかし、失敗した場合は、 'make'をもう一度入力すると**テストを再実行する必要があります。 –

+0

次に、バイナリファイル 'lib1_test'に依存する' add_custom_target'が必要で、失敗した場合はこのバイナリ(実行ファイル)ファイルを削除してください。 – fghj

答えて

2

ここで私はこれまで何を得ているのですか?実装はかなり素早く汚れていますが、それでも動作します。あなたのニーズを満たしているかどうかを確認してください。

CMakeLists.txt:

lib.c:

#include "lib.h" 

#include <time.h> 

int lib_func() { 
    return time(NULL) % 2; 
} 

lib.h:

#pragma once 

int lib_func(); 

テスト完全を期すため

cmake_minimum_required(VERSION 2.8.12) 

project(test) 

enable_testing() 

set(lib1_SRC lib.c) 

add_library(lib1 ${lib1_SRC}) 

set(test_SRC test.c) 

add_executable(libtest ${test_SRC}) 
target_link_libraries(libtest lib1) 

add_test(NAME libtest COMMAND libtest) 

add_custom_command(
    OUTPUT _libtest_completed 
    COMMAND ctest -C $<CONFIGURATION> --output-on-failure 
    COMMAND cmake -E touch _libtest_completed 
    DEPENDS libtest 
) 

add_custom_target(
    libtest_force ALL 
    DEPENDS _libtest_completed 
) 

ソースファイル.c:

#include "lib.h" 

int main() { 
    return lib_func(); 
} 

残念ながら、私たちは手動で夕日を実行する必要が原因CMake bugtestターゲットに直接依存することは不可能です。

+0

'lib1'をビルドするときに' libtest_force'をビルドする方法はありますか?つまり、 'make lib1'と入力すると' lib1'、 'libtest'と' libtest_force'がビルドされます(テストが実行されます)。 –

+0

3つは「トップターゲット」なので、 'add_dependencies'を使うことができます。しかし、私は循環依存を避けるだろう、それは解決よりも多くの問題をもたらす。 – user3159253

+0

私は多かれ少なかれ動作するものを考え出しました。もしあなたが望むなら、[私の答え](http://stackoverflow.com/a/36702886/955273)[私の質問](http://stackoverflow.com/questions/36701286/cmake-replicate- boost-builds-build-everything-in-jamfile-behavior/36702886)、もしあればコメントしてください。ありがとう! –

0

@ user3159253に示されているように、ビルド環境で問題のターゲットを再度ビルドする必要があるかどうかを確認するための出力ファイル(タイムスタンプ付き)が必要です。したがって、実行可能ファイルが正常にビルドされた場合、それを実行するための後続の呼び出しが失敗したとしても、再度ビルドされません。

ターゲットを1つしか設定できないソリューションを追加したいと考えました。また、テスト実行可能な出力の名前を変更し、それを実行します - 成功した場合 - 「合格」としてソートのそれをマークするために元の名前に再び名前を変更:

function(register_test NAME) 

    add_test(NAME ${NAME} COMMAND ${NAME}) 

    set(TMP "$<TARGET_FILE_DIR:${NAME}>/tmp_$<TARGET_FILE_NAME:${NAME}>") 
    set(ORG "$<TARGET_FILE:${NAME}>") 

    # make the test run as part of the build process 
    add_custom_command(
     TARGET ${NAME} 
     POST_BUILD 
     COMMAND ${CMAKE_COMMAND} -E rename "${ORG}" "${TMP}" 
     COMMAND ${TMP} 
     COMMAND ${CMAKE_COMMAND} -E rename "${TMP}" "${ORG}" 
    ) 

endfunction()