[CMake] avoid rebuilding targets depending on generated source files

Michael Hertling mhertling at online.de
Sun Mar 4 03:52:46 EST 2012


On 03/04/2012 01:06 AM, Ajay Panyala wrote:
> Please provide a minimal but complete example for this issue.
> 
> Please find it in the following link
> http://pastie.org/private/pd13u33s9xpfihf2dbzc1q

The following project is a boiled-down version of yours but doesn't
need any programs except for CMake - that's what I actually meant
with "minimal but complete" as I don't have the org.antlr.Tool
Java program:

CMAKE_MINIMUM_REQUIRED(VERSION 2.8 FATAL_ERROR)
PROJECT(P NONE)
SET(CMAKE_VERBOSE_MAKEFILE ON)

SET(GrammarSource ${PROJECT_BINARY_DIR}/src)
FILE(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/src)

ADD_CUSTOM_TARGET(GrammarBuild ALL
    COMMAND ${CMAKE_COMMAND} -E echo "\${X}"
        > ${GrammarSource}/testLexer.h
    COMMAND ${CMAKE_COMMAND} -E echo "\${X}"
        > ${GrammarSource}/testLexer.c
    COMMAND ${CMAKE_COMMAND} -E echo "\${X}"
        > ${GrammarSource}/testParser.h
    COMMAND ${CMAKE_COMMAND} -E echo "\${X}"
        > ${GrammarSource}/testParser.c
    COMMAND ${CMAKE_COMMAND} -E echo "\${X}"
        > ${PROJECT_BINARY_DIR}/test.tokens
)

ADD_CUSTOM_COMMAND(TARGET GrammarBuild POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E copy_if_different
        ${GrammarSource}/testLexer.h
        ${PROJECT_BINARY_DIR}/parser/testLexer.h
    COMMAND ${CMAKE_COMMAND} -E copy_if_different
        ${GrammarSource}/testLexer.c
        ${PROJECT_BINARY_DIR}/parser/testLexer.c
    COMMAND ${CMAKE_COMMAND} -E copy_if_different
        ${GrammarSource}/testParser.h
        ${PROJECT_BINARY_DIR}/parser/testParser.h
    COMMAND ${CMAKE_COMMAND} -E copy_if_different
        ${GrammarSource}/testParser.c
        ${PROJECT_BINARY_DIR}/parser/testParser.c
    COMMAND ${CMAKE_COMMAND} -E copy_if_different
        ${PROJECT_BINARY_DIR}/test.tokens
        ${PROJECT_BINARY_DIR}/parser/test.tokens
)

After configuration, you can run the target by "make X=0" and check the
timestamps by "ls -l --full-time test.tokens parser src". Issuing "make
X=0" again reveals that the copied files aren't rewritten as it happens
after "make X=1". Thus, AFAICS, everything works as expected. Could you
check if the above-noted example also works on your system?

What exactly does not work with your example? You wrote:

>>> I have 4 cmake -E copy_if_different commands, one for each file.
>>> Only the last file is not copied (if similar). [...]

Does this mean that the last file out of four - in fact, your example
handles five files - is not copied *although* the source file and the
destination file are different, i.e. similar but not equal?

You wrote further:

>>> [...] The others are copied
>>> even if they are the same.
>>>
>>> I verfied that they are the same with a diff.

Does this mean that source files are copied *although* they are equal
to their respective destination file? How do you determine that they
have been copied? Do you check the timestamps? With --full-time?

Regards,

Michael

PS: Does org.antlr.Tool write to the source tree? If so: Don't do that.

> On Sat, Mar 3, 2012 at 3:54 PM, Michael Hertling <mhertling at online.de>wrote:
> 
>> On 03/04/2012 12:14 AM, Ajay Panyala wrote:
>>> No, it wouldn't; check it out:
>>>
>>> % touch a
>>> % rm -f b
>>> % ls b
>>> ls: cannot access b: No such file or directory
>>> % cmake -E copy_if_different a b
>>> % ls b
>>> b
>>> % cksum a b
>>> 4294967295 0 a
>>> 4294967295 0 b
>>>
>>> It works with one file, but I have 4 files that are generated.
>>> I have 4 cmake -E copy_if_different commands, one for each file.
>>> Only the last file is not copied (if similar). The others are copied
>>> even if they are the same.
>>>
>>> I verfied that they are the same with a diff.
>>>
>>> Any idea what might be happening here ?
>>
>> Please provide a minimal but complete example for this issue.
>>
>> Regards,
>>
>> Michael
>>
>>> On Sat, Mar 3, 2012 at 2:47 PM, Michael Hertling <mhertling at online.de
>>> wrote:
>>>
>>>> On 03/03/2012 10:36 PM, Ajay Panyala wrote:
>>>>> Try "cmake -E copy_if_different ..."
>>>>>
>>>>> cmake -E copy_if_different build/test1.c build/tests/test1.c
>>>>>
>>>>> That would work when make is run atleast once.
>>>>> When running make for the 1st time test1.c was never
>>>>> copied to build/tests before. So I would be comparing a file with
>>>>> another non-existant file and that would result in an error halting
>>>>> the make process.
>>>>
>>>> No, it wouldn't; check it out:
>>>>
>>>> % touch a
>>>> % rm -f b
>>>> % ls b
>>>> ls: cannot access b: No such file or directory
>>>> % cmake -E copy_if_different a b
>>>> % ls b
>>>> b
>>>> % cksum a b
>>>> 4294967295 0 a
>>>> 4294967295 0 b
>>>>
>>>> Regards,
>>>>
>>>> Michael
>>>>
>>>>> On Sat, Mar 3, 2012 at 1:20 PM, Hendrik Sattler <
>> post at hendrik-sattler.de
>>>>> wrote:
>>>>>
>>>>>> Am Samstag, 3. März 2012, 21:41:49 schrieb Ajay Panyala:
>>>>>>> I have a custom target which runs a command to generate
>>>>>>> a C source file say test1.c
>>>>>>>
>>>>>>> ADD_CUSTOM_TARGET(TestGen ALL
>>>>>>> COMMAND genExec ${PROJECT_SOURCE_DIR}/Main.java
>>>>>>> DEPENDS ${PROJECT_SOURCE_DIR}/Main.java
>>>>>>> )
>>>>>>>
>>>>>>> And I have a custom command that moves the generated *test1.c *
>>>>>>> to a new directory inside the build directory.
>>>>>>>
>>>>>>> ADD_CUSTOM_COMMAND(
>>>>>>> TARGET TestGen
>>>>>>> POST_BUILD
>>>>>>> COMMAND mv
>>>>>>> ARGS ${PROJECT_BINARY_DIR}/test1.c ${PROJECT_BINARY_DIR}/tests/
>>>>>>> )
>>>>>>>
>>>>>>> Each time I run make, the custom target is run (since custom targets
>>>> are
>>>>>>> always
>>>>>>> out-of-date). But I want to avoid moving the new test1.c generated
>> each
>>>>>>> time if build/test1.c is the same as build/tests/test1.c since there
>>>> are
>>>>>>> other targets
>>>>>>> like add_executable and add_library later in the CMakelists file that
>>>> are
>>>>>>>  re-built
>>>>>>> each time since they depend on test1.c
>>>>>>
>>>>>> Try "cmake -E copy_if_different ..."
>>>>>>
>>>>>> HS


More information about the CMake mailing list