[CMake] How to use add_custom_command correctly

Martin Kupke martin.kupke at novero.com
Fri Sep 30 07:01:11 EDT 2011


On 29.09.11 01:46, Michael Hertling wrote:
> On 09/28/2011 01:45 PM, Martin Kupke wrote:
>> Now it seems to be solved, the generator is called and the generated
>> sources / headers are then compiled and linked into a library.
>>
>> My changes are in the
>>
>> D:/project/Discovery/Generated/Driver/CMakeLists.txt
>>
>> just adding a add_custom_target( MyGeneratedSources ALL DEPENDS
>> ${all_generated_srcs} ${all_generated_hdrs} )
>>
>> Additionally I added in the root CMakeLists.txt
>> add_dependencies( ${MY_PROJECT} MyGeneratedSources )
>>
>> This works fine.
> Just two additional remarks:
>
> - For ADD_CUSTOM_COMMAND(OUTPUT ...), it's documented explicitly
> that relative paths after the OUTPUT clause will be interpreted
> with respect to the current binary directory, so you may leave
> out the leading ${CMAKE_CURRENT_BINARY_DIRECTORY} and specify
> relative paths here. However, for the DEPENDS clause, there
> is no such documentation.
That wasn't my problem, because I didn't work with relative paths.
But still good to know from where the relative path has to be seen, 
thanks for the info!
> - A custom command's OUTPUTs must be mentioned as other targets'
> prerequisites, i.e. as source files in ADD_EXECUTABLE/LIBRARY()
> or after the DEPENDS clause of ADD_CUSTOM_TARGET() in the same
> CMakeLists.txt file. Otherwise, the rule for the then unused
> OUTPUT is dropped, and it will never be generated. Thus, for
> generated sources/headers, there should be no need for an
> additional custom target as a custom command's anchor.
This info with the ADD_CUSTOM_TARGET is the most important thing.
Thanks for your answers.

Regards,
Martin
> Regards,
>
> Michael
>
>> On 28.09.11 13:34, Rolf Eike Beer wrote:
>>>> On 27.09.11 18:24, Michael Wild wrote:
>>>>> On 09/27/2011 05:59 PM, Martin Kupke wrote:
>>>>>> Hi,
>>>>>>
>>>>>> in my project there is a subfolder which SHALL contain sources to
>>>>>> generate a library. The problem is that at startup of the project there
>>>>>> are no source files existing, because they will be generated by a code
>>>>>> generator. This means within the build process the code generator needs
>>>>>> to be called first, then generates the output files in the subfolder
>>>>>> and
>>>>>> then a library shall be generated from that source files (this are
>>>>>> standard .c and .h files). If I start the code generator by hand to
>>>>>> generate the source files and remove the custom command, then the
>>>>>> compilation is successful, but I want the code generator to be started
>>>>>> every time the configuration file for the code generator has changed.
>>>>>>
>>>>>> In my sample below
>>>>>> * the driver.c would be one of the files which the code generator would
>>>>>> generate
>>>>>> * the variable CodeGen is the executable tool (the code generator
>>>>>> himself)
>>>>>> * the variable CodeGenParam contains the parameters which are passed to
>>>>>> be able to generate without any user interaction
>>>>>> * the variable CodeGenConfig is the input file for the code generator
>>>>>>
>>>>>> This subfolder contains its own CMakeLists.txt with the following
>>>>>> settings:
>>>>>> ##################### snip #####################
>>>>>> project(CANstack C)
>>>>>>
>>>>>> add_custom_command( OUTPUT driver.c
>>>>>>                                               COMMAND ${CodeGen}
>>>>>> ${CodeGenParam}
>>>>>>                                               DEPENDS ${CodeGenConfig} )
>>>>>> )
>>>>>>
>>>>>> file(GLOB CANstack_srcs "*.c")
>>>>>> file(GLOB CANstack_hdrs "*.h")
>>>>>>
>>>>>> set(lib_name "CANstack")
>>>>>> add_library(${lib_name} STATIC ${CANstack_srcs} ${CANstack_hdrs})
>>>>>>
>>>>>> ##################### snap #####################
>>>>>>
>>>>>> I don't get it work that the custom command is called and the source
>>>>>> files from the code generator are produced.
>>>>>>
>>>>> A few issues here:
>>>>>
>>>>> - Never generate output in the source tree, only in the binary tree.
>>>>> - Always use absolute paths with add_custom_command().
>>>> I use the absolute paths
>>>>> - Always list *all* outputs after the OUTPUT argument, otherwise CMake
>>>>> won't know that they are generated sources.
>>>> I added the list of *all* files which shall be generated
>>>>> - Never use file(GLOB ...). It is evil. And breaks in your case. Just
>>>>> don't.
>>>> I don't use the file(GLOB ...) anymore in this CMakeLists.txt
>>>>> Michael
>>>>>
>>>> In case the generated output files already exist and the dependency file
>>>> ${CodeGenConfig} has been touched, then the output will be generated.
>>>>
>>>> Typically there is from beginning of the project no source file
>>>> existing, because the generator needs to be run first. If the output
>>>> files are not existing, then I get an error message from CMake:
>>>>
>>>> ##################### snip #####################
>>>>
>>>> CMake Error at Generated/CarIF_Appl/CANstack/CMakeLists.txt:31
>>>> (add_library):
>>>>      Cannot find source file:
>>>>
>>>>        D:/project/Discovery/Generated/Driver/uart.c
>>>>
>>>>      Tried extensions .c .C .c++ .cc .cpp .cxx .m .M .mm .h .hh .h++ .hm
>>>> .hpp
>>>>      .hxx .in .txx
>>>>
>>>> ##################### snap #####################
>>>>
>>>> How do I have to instruct CMake to run the code generator first, so that
>>>> the library can be build of that sources?
>>> Can you paste the relevant snippet from your new CMakeLists.txt?
>>>
>>> You can try this first and see if it helps:
>>>
>>> add_custom_command( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/driver.c
>>>                  COMMAND ${CodeGen} {CodeGenParam}
>>>                  DEPENDS ${CodeGenConfig} )
>>>
>>> add_executable(myexe ${CMAKE_CURRENT_BINARY_DIR}/driver.c)
>>>
>>> Of course you must tell the CodeGen where to put the result, preferably by
>>> passing "${CMAKE_CURRENT_BINARY_DIR}/driver.c" as argument (with the
>>> quotes, to make paths with spaces work right). If the generator can't
>>> handle this you can try to set WORKING_DIRECTORY to
>>> ${CMAKE_CURRENT_BINARY_DIR}, passing all other file arguments with
>>> absolute paths then.
>>>
>>> Eike
> --
>
> 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

-- 

------------------------------------------------------------------------

*martin kupke*

can diagnostics engineer | senior software developer

*m*:+49.151.5511.3632| *e*:martin.kupke at novero.com 
<mailto:martin.kupke at novero.com>

skype:martin.kupke_novero | w:www.novero.com <http://www.novero.com>

novero GmbH
meesmannstr.103 | 44807 Bochum | germany


novero gmbh | parsevalstr. 7 a | 40468 düsseldorf | germany | 
amtsgericht düsseldorf | hrb 58283 | umsatzsteueridentifikationsnummer: 
de 814973142 | geschäftsführender gesellschafter: razvan olosu



More information about the CMake mailing list