[CMake] Unit tests, but not CTest

Michael Hertling mhertling at online.de
Mon May 17 07:28:06 EDT 2010


On 05/16/2010 11:34 PM, Magnus Therning wrote:
> On 14/05/10 22:28, Michael Hertling wrote:
>> On 05/14/2010 08:24 AM, Magnus Therning wrote:
> [...]
>>> Thanks for this analysis, it makes the problem a lot clearer to me.  One
>>> thing it doesn't clarify is how ADD_CUSTOM_COMMAND( TARGET ... POST_BUILD )
>>> could *ever* be useful. [...]
>>
>> ADD_CUSTOM_COMMAND(TARGET ...) enhances the commands associated with the
>> named target, i.e. you can hook into that target's build process:
>>
>> CMAKE_MINIMUM_REQUIRED(VERSION 2.8 FATAL_ERROR)
>>
>> PROJECT(CUSTOM_COMMAND_DEMO C)
>>
>> FILE(WRITE main.c "void main(){}")
>> ADD_EXECUTABLE(exe main.c)
>>
>> ADD_CUSTOM_COMMAND(TARGET exe PRE_BUILD COMMAND echo "Pre build")
>> ADD_CUSTOM_COMMAND(TARGET exe POST_BUILD COMMAND echo "Post build")
>>
>> After cmaking, look at the end of CMakeFiles/exe.dir/build.make:
>>
>> [...]
>> exe: CMakeFiles/exe.dir/main.c.o
>> exe: CMakeFiles/exe.dir/build.make
>> exe: CMakeFiles/exe.dir/link.txt
>>         @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --red
>> --bold "Linking C executable exe"
>>         echo Pre\ build
>>         $(CMAKE_COMMAND) -E cmake_link_script
>> CMakeFiles/exe.dir/link.txt --verbose=$(VERBOSE)
>>         echo Post\ build
>> [...]
>>
>> Thus, ADD_CUSTOM_COMMAND(TARGET ...) doesn't modify the dependencies of the
>> named target but the associated commands. So, it provides a general
>> possibility to have arbitrary commands run when a target is (re)built.
> 
> Ah, sorry, I managed to use the wrong word, "useful" when I really should have
> written "used".  I can see its usefulness, indeed I *wanted* to use it myself.
> However, earlier in this thread it became apparent that
> add_custom_command( OUTPUT foo ... ) can't be used together with
> add_custom_command( TARGET foo POST_BUILD ... ); the latter would *never* be
> executed.  [...]

Yes, because it must be associated with a fully-fledged CMake target,
and such a target is not provided by ADD_CUSTOM_COMMAND(OUTPUT ...).

> [...] It was also apparent that add_custom_target( foo ... ) can't be
> used with add_custom_command( TARGET foo POST_BUILD ...); the latter would
> then *always* be executed.

Yes, regardless if foo has been freshly rebuilt or not because this
target - although fully-fledged - is always considered out of date.

> Now you say that if I use add_executable( foo ... ) then I can use
> add_custom_command( TARGET foo POST_BUILD ... ).  So, what does
> add_executable( ... ) do?

W.r.t. your concern, ADD_EXECUTABLE() defines a target suitable for
ADD_CUSTOM_COMMAND(TARGET ...) to attach further commands to while
ADD_CUSTOM_COMMAND(OUTPUT ...) doesn't, and that's the annoyance.

> I was under the impression that add_executable( ... ) deep down wasn't much
> more than a wrapper around add_custom_command( OUTPUT ... ) (since that is the
> only way I know to get anything built through the CMake scripts). [...]

Without having inspected the source code, I would say that this is
ADD_EXECUTABLE()'s core functionality, but it does much more in
addition. For example, invoke the following CMakeLists.txt:

CMAKE_MINIMUM_REQUIRED(VERSION 2.8 FATAL_ERROR)
PROJECT(TARGETS C)
ADD_CUSTOM_COMMAND(OUTPUT outtgt COMMAND touch outtgt)
FILE(WRITE main.c "void main(){}")
ADD_EXECUTABLE(exetgt main.c outtgt)

Subsequently - if on *nix - run

grep exetgt $(find . -type f)
grep outtgt $(find . -type f)

and you'll see the difference between ADD_EXECUTABLE()'s target
"exetgt" and ADD_CUSTOM_COMMAND(OUTPUT ...)'s target "outtgt".

> [...] However now
> you've made me think that add_executable( ... ) is a bit magical. [...]

Preferably, I'd say ADD_CUSTOM_COMMAND(OUTPUT ...) is more primitive.

> [...] If that's
> the case, then how does one go about adding full support for a language (i.e.
> so that add_executable( ... ) can be used for that language) using nothing but
> CMake scripts?

Up to now, I have not tried to add a language to CMake, yet, but as far
as I understand the mechanism, one should get by with a bunch of CMake
scripts in the modules' directory. Furthermore, it should be generally
possible to still use ADD_EXECUTABLE() et al. for the new language in
the usual way as long as the language's compiler behaves sufficiently
alike a C/C++ compiler. Nevertheless, I'd expect certain limitations.

>>> [...] I'm still to see an example of any buildable target that
>>> such a post-build command can be connected to and only triggered on (re)build.
>>
>> Imagine your add_ocaml_executable() using ADD_EXECUTABLE() instead of
>> ADD_CUSTOM_COMMAND(OUTPUT ...); in this case, you would have a, say,
>> fully-fledged CMake target which additional commands can be attached to by
>> ADD_CUSTOM_COMMAND(TARGET ...), and indeed, that is a suitable place for
>> your automated unit testing. Obviously, CMake's file-level targets defined
>> by ADD_CUSTOM_COMMAND(OUTPUT ...) are not sufficient for this purpose
>> although they appear as usual Make targets if others depend on them, but so,
>> you've to specify the desired commands right in the
>> ADD_CUSTOM_COMMAND(OUTPUT ...). Perhaps, this would be worth a feature
>> request.
> 
> This seems to support my line of reasoning above, i.e. that adding full
> language support for new language (i.e. making it possible to use
> add_executable( ... ) on OCaml sources) isn't possible using CMake scripts
> alone.  Is that correct?

With caution, I would say no, but I don't know OCaml's specifics. Have
you already looked into ${CMAKE_ROOT}/Modules/CMakeAddNewLanguage.txt
and issue 4242? Do they fail your needs? Perhaps, you can obtain more
information about the topic of adding languages to CMake at:

<http://www.cmake.org/Wiki/CMake/Assembler>
<http://websvn.kde.org/?view=revision&revision=1061491>

Note the functions csharp_add_executable() and csharp_add_library().

Regards,

Michael


More information about the CMake mailing list