[CMake] building tests

Marcel Loose loose at astron.nl
Thu Jul 8 07:22:46 EDT 2010


On Thu, 2010-07-08 at 16:30 +0800, Paul Harris wrote:
> 
> 
> On 8 July 2010 16:27, Marcel Loose <loose at astron.nl> wrote:
>         
>         On Thu, 2010-07-08 at 11:12 +0800, Paul Harris wrote:
>         >
>         >
>         > On 7 July 2010 23:38, Marcel Loose <loose at astron.nl> wrote:
>         >
>         >         On Wed, 2010-07-07 at 17:05 +0200, Michael Wild
>         wrote:
>         >         > On 7. Jul, 2010, at 16:01 , Paul Harris wrote:
>         >         >
>         >         > > Hi all,
>         >         > >
>         >         > > I have looked and can't find the answer, so I
>         turn to the
>         >         list.
>         >         > >
>         >         > > I have a CMakeLists.txt and a subdirectory
>         called utils,
>         >         which also
>         >         has its
>         >         > > own CMakeLists.txt
>         >         > >
>         >         > > In the parent CML.txt, I have something like:
>         >         > >
>         >         > > ENABLE_TESTING()
>         >         > > add_subdirectory(utils)
>         >         > >
>         >         > > In my utils CML.txt, I have
>         >         > >
>         >         > > ADD_EXECUTABLE(unit_1 units/unit_1.cpp)
>         >         > > ADD_TEST( unit_1
>         ${EXECUTABLE_OUTPUT_PATH}/unit_1 )
>         >         > >
>         >         >
>         >         > Simplify this to
>         >         >
>         >         > ADD_TEST(unit_1 unit_1)
>         >         >
>         >         > CMake will figure out by itself that unit_1 is a
>         target and
>         >         invoke the
>         >         executable correctly (your code would break for
>         >         multi-configuration IDE
>         >         generators).
>         >         >
>         >         > As for the dependencies, I agree that it would be
>         nice if
>         >         the "test"
>         >         target depended on the executables. But what is
>         wrong with
>         >         "make all
>         >         test" (apart from the fact that it possibly compiles
>         more than
>         >         you
>         >         actually need to run the test)? You could also wrap
>         the
>         >         add_executable
>         >         call in a custom function which creates a custom
>         target (say
>         >         test_exes)
>         >         and makes it depend on all the executables:
>         >         >
>         >         > function(add_test_executable name)
>         >         >   if(NOT TARGET ${name})
>         >         >     add_custom_target(test_exes)
>         >         >    endif()
>         >         >    add_executable(${name} ${ARGN})
>         >         >    add_dependencies(test_exes ${name})
>         >         > endfunction()
>         >         >
>         >         > Then you can do "make test_exes test".
>         >         >
>         >         > HTH
>         >         >
>         >         > Michael
>         >
>         >
>         >         You can further reduce the number of targets that
>         get
>         >         (re)build by going
>         >         into the directory '${CMAKE_BINARY_DIR}/utils' and
>         invoke
>         >         'make' there.
>         >
>         >         You could also define a 'check' target that will
>         build and run
>         >         all your
>         >         test programs. See
>         >         http://www.cmake.org/Wiki/CMakeEmulateMakeCheck
>         >
>         >         Best regards,
>         >         Marcel Loose.
>         >
>         >
>         > Thanks Marcel, I combined the solution in the wiki with what
>         was
>         > discussed in my last email, and I ended up with
>         >
>         > set (CMAKE_TEST_COMMAND "ctest")
>         >
>         > function (add_unit_test name)
>         >    if(NOT TARGET ${name})
>         >       add_custom_target (check COMMAND
>         ${CMAKE_TEST_COMMAND})
>         >    endif()
>         >    add_executable(${name} ${ARGN})
>         >    # or ADD_EXECUTABLE(${name} ${ARGN} EXCLUDE_FROM_ALL)
>         >    #    if you want it to be skipped when building 'all'
>         >    add_test(${name} ${EXECUTABLE_OUTPUT_PATH}/${name})
>         >    add_dependencies(check ${name})
>         > endfunction()
>         >
>         >
>         >
>         > however, I have discovered (with message()) that
>         ${CMAKE_TEST_COMMAND}
>         > is *empty* - its something I had to set(), which is not
>         mentioned in
>         > the wiki page you mentioned.  It IS kind-of-mentioned in
>         "Cmake
>         > Scripting of CTest" but not explicitly enough to catch the
>         eye.
>         >
>         > I've edited the wiki page, please check that my edits make
>         sense.
>         >
>         > Thanks
>         > Paul
>         
>         Hi Paul,
>         
>         
>         While re-reading you add_unit_test function above I was
>         wondering
>         whether this will actually work. The snippet
>         
>          if(NOT TARGET ${name})
>            add_custom_target (check COMMAND ${CMAKE_TEST_COMMAND})
>          endif()
>         
>         strikes me as odd. This will cause multiple definitions of the
>         'check'
>         target, which is not allowed, unless you set a policy (don't
>         know by
>         heart which one exactly). Anyway, multiple definitions of the
>         same
>         target are only supported by Unix Makefiles; I don't think you
>         want to
>         restrict yourself unnecessarily.
>         
>         
> 
> this was suggested by Michael in this email thread.
> I thought it might be better to move the add_custom_target to before
> the function - ie always declare it once only.   I guess the idea of
> the test is to only register the target once.
> 
> 
Hmm,

Maybe I missed that mail -- I couldn't find it in my mailbox -- but my
guess is that Michael wrote something like:

if(NOT TARGET check)
  add_custom_target (check COMMAND ${CMAKE_TEST_COMMAND})
endif()

You can put that snippet in a macro like my_add_test(), which would then
look something like this:

macro(my_add_test _name)
  if(NOT TARGET check)
    add_custom_target (check COMMAND ${CMAKE_TEST_COMMAND})
  endif()
  add_executable(${_name} ${ARGN})
  add_test(${_name} ${_name})
  add_dependencies(check ${_name})
endmacro(my_add_test)

Of course there's nothing wrong with declaring the custom target 'check'
once (that's the way I do it too). Be sure you do that before the first
call to add_dependencies(), though, otherwise you'll get a CMake error.

Best regards,
Marcel Loose.



More information about the CMake mailing list