[CMake] adding a custom command with the file name as a target

Michael Hertling mhertling at online.de
Fri Mar 11 21:32:31 EST 2011


On 03/11/2011 09:41 PM, Jim Newsome wrote:
> That doesn't quite work either. I get some errors about circular
> dependencies. Strangely, doing it this way hello.bin _does_ get built,

Yes, I can see these messages - not errors - too, but obviously, they
don't prevent the hello.bin file from being generated. Perhaps, this
works by accident, so one should play safe and get rid of them. One
approach is to put the hello.bin file in a directory where it does
not collide with the equally named custom target:

file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/objbin)
add_executable (hello hello.c)
add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/objbin/hello.bin
                   COMMAND ...
                   DEPENDS hello
                   COMMENT "objcopying hello to hello.bin")
add_custom_target(hello.bin ALL
                  DEPENDS ${CMAKE_BINARY_DIR}/objbin/hello.bin)

However, IMO, the most proper solution is to rename the custom target,
say "objbin" instead of "hello.bin", so it doesn't match a file's or
directory's name anymore. At the latest, when you need to apply the
objcopy utility to another file, this becomes appropriate anyway.

> but it gets built every time, even if 'hello' hasn't changed.

This seems to be a side effect of the custom target colliding with a
file of the same name. Try again with an intermediate directory or a
renamed custom target as suggested; the unnecessary regenerations of
the hello.bin file should go away along with the messages about the
circular dependencies.

Regards,

Michael

PS: If you use CMake 2.8.4, you should refer to the "hello" executable
    in the custom command's COMMAND clause by a "generator expression".

> On Fri, Mar 11, 2011 at 2:30 PM, Michael Hertling <mhertling at online.de> wrote:
>> On 03/11/2011 08:00 PM, David Cole wrote:
>>> On Fri, Mar 11, 2011 at 12:05 PM, Jim Newsome <jnewsome at cmu.edu> wrote:
>>>> Unfortunately it seems that the target needs to have a different name
>>>> from its dependencies. When building I get:
>>>> make[2]: Circular CMakeFiles/hello.bin <- hello.bin dependency dropped.
>>>>
>>>> Another workaround I thought of is to change the output filename to,
>>>> e.g., _hello.bin and have a command in the target to move _hello.bin
>>>> to hello.bin. Unfortunately this forces _hello.bin to be regenerated
>>>> every time. I suppose I could work around _that_ by copying instead of
>>>> moving, but that's getting fairly ugly.
>>>>
>>>> On Fri, Mar 11, 2011 at 11:56 AM, Tyler <tyler at cryptio.net> wrote:
>>>>> The target in the Makefile is created with the add_custom_target()
>>>>> call. So just change yours to:
>>>>>
>>>>> add_custom_target(hello.bin ALL DEPENDS hello.bin)
>>>>>
>>>>> hth,
>>>>> tyler
>>>>>
>>>>> On Fri, Mar 11, 2011 at 7:58 AM, Jim Newsome <jnewsome at cmu.edu> wrote:
>>>>>> I'd like to do something like add_custom_command, with the output file
>>>>>> name as a target in the generated makefile. Is there an elegant way of
>>>>>> doing this?
>>>>>>
>>>>>> The closest I've come is:
>>>>>> add_executable (hello hello.c)
>>>>>> add_custom_command(OUTPUT hello.bin
>>>>>>                    COMMAND objcopy --output-format=binary hello hello.bin
>>>>>>                   DEPENDS hello
>>>>>>                   COMMENT "objcopying hello to hello.bin")
>>>>>> add_custom_target(bin ALL DEPENDS hello.bin)
>>>>>>
>>>>>> However, the target name in the generated makefile is 'bin' rather
>>>>>> than 'hello.bin'. Is there a way to make 'hello.bin' itself a target
>>>>>> in the generated makefile?
>>>>>
>>>> _______________________________________________
>>>> Powered by www.kitware.com
>>>>
>>>> Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html
>>>>
>>>> Please keep messages on-topic and check the CMake FAQ at: http://www.cmake.org/Wiki/CMake_FAQ
>>>>
>>>> Follow this link to subscribe/unsubscribe:
>>>> http://www.cmake.org/mailman/listinfo/cmake
>>>>
>>>
>>> How about making the *named output* of your custom command simply be a
>>> sentinel file (with a different name) that just happens to produce the
>>> real file (with the same name as the target)...?
>>>
>>> Something like this:
>>>
>>> add_executable (hello hello.c)
>>> add_custom_command(OUTPUT hello.bin.sentinel
>>>                   COMMAND objcopy --output-format=binary hello hello.bin
>>>                   COMMAND ${CMAKE_COMMAND} -E touch hello.bin.sentinel
>>>                   DEPENDS hello
>>>                   COMMENT "objcopying hello to hello.bin")
>>> add_custom_target(hello.bin ALL DEPENDS hello.bin.sentinel)
>>>
>>> Does that work?
>>
>> No, you won't have a dependency of the hello.bin custom target on the
>> hello.bin file, i.e. if the latter is removed, it won't be rebuilt.
>> Instead, use absolute paths for the custom target's dependencies:
>>
>> add_executable (hello hello.c)
>> add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/hello.bin
>>                   COMMAND <hello-to-${CMAKE_BINARY_DIR}/hello.bin>
>>                   DEPENDS hello
>>                   COMMENT "objcopying hello to hello.bin")
>> add_custom_target(hello.bin ALL DEPENDS ${CMAKE_BINARY_DIR}/hello.bin)
>>                  ^^^^^^^^^             ^^^^^^^^^^^^^^^^^^^
>>
>> Apparently, that's sufficient to distinguish the hello.bin custom
>> target from the equally named output file of the custom command.
>>
>> Regards,
>>
>> Michael


More information about the CMake mailing list