[CMake] Generate sources (smartly :-))

Guillaume Maudoux (Layus) layus.on at gmail.com
Mon Dec 21 10:11:53 EST 2015


Hi,

I am generating files with some executable called "generator" built with
cmake.

Apparently I am unable to avoid the generator being built even when the
generated files are up to date.
IIRC, EXCLUDE_FROM_ALL should do just that: avoid a target being build
if not strictly needed.

I have reproduced the issue in a small project :

$ tree
.
├── build/...
├── CMakeLists.txt
├── generator
│   ├── CMakeLists.txt
│   └── generator.cc
└── step1
    └── CMakeLists.txt

$ tail -n +0 **/*
==> CMakeLists.txt <==
cmake_minimum_required(VERSION 3.4)

add_subdirectory(generator EXCLUDE_FROM_ALL)
add_subdirectory(step1)

==> generator/CMakeLists.txt <==
add_executable(generator EXCLUDE_FROM_ALL generator.cc)

==> generator/generator.cc <==
#include <iostream>
#include <fstream>
using namespace std;

int main(int argc, char** argv) {
    ofstream myfile;
    myfile.open (argv[1]);
    myfile << "Writing this to a file." << endl;
    myfile << argv[2] << endl;
    myfile.close();
    return 0;
}

==> step1/CMakeLists.txt <==
add_custom_command(
    OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/task1.txt
    COMMAND ${CMAKE_CURRENT_BINARY_DIR}/../generator/generator
${CMAKE_CURRENT_BINARY_DIR}/task1.txt none
    WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
    DEPENDS generator
    VERBATIM)

add_custom_target(task1 ALL
    DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/task1.txt
    VERBATIM)

$ cd build
$ cmake ..
$ touch step1/task1.txt # Simulate import of generated files.
$ make
[ !!! still builds generator, but it is not needed as task1.txt is up to
date ]

I am really annoyed by this issue, as it defeats the advantage of
caching generated files.

Is there something I am missing in my usage of EXCLUDE_FROM_ALL ?

Thx,

Guillaume.


Le 18/12/15 20:53, Layus a écrit :
> On 16/12/15 17:53, Mark Stijnman wrote:
>> On Wed, Dec 16, 2015 at 2:29 PM, Layus <layus.on at gmail.com
>> <mailto:layus.on at gmail.com>> wrote:
>>
>>     Hi,
>>
>>     I am looking for a way to share an archive of a partially
>>     compiled project to speedup compilation time and configuration
>>     hassle for the users.
>>
>>     I have a project that works in two steps.
>>     First a source generator is built (based on clang) and generates
>>     some extra source files based on the existing source files.
>>     Then the normal compilation process takes places, building the
>>     application from both original and generated sources.
>>
>> <snip>
>>  
>>
>>     Now, is it possible to distribute a source archive with the
>>     generated sources, in such a way that any user unpacking the
>>     archive and running cmake would not have to generate the extra
>>     sources ?
>>
>>     This would be useful because
>>     i) the project is tricky to configure and
>>     ii) the generated sources are not dependent on the user config,
>>     so building the generator is just useless computation time on the
>>     user.
>>
>>     The ideal scheme would be something like
>>
>>         [developper]
>>         $ cmake -DCLANG=config
>>         $ make generate
>>         $ make package_source
>>
>>         [user]
>>         $ unpack
>>         $ cmake -DUSER=config
>>         $ make # builds only the application, reusing the shipped
>>     generated sources.
>>         $ make install
>>
>>     ... but when the user runs cmake, he overwrites the generated
>>     Makefiles and the extra sources are generated again.
>>
>>     Any idea ?
>>
>>     layus.
>>
>>     -- 
>>
>>
>> I'd probably just make it such that the CMake script automatically
>> detects the presence of the generated files, and if they don't exist,
>> generate them. For example: 
>> 1. Set a variable GENERATED_FOLDER to
>> ${CMAKE_CURRENT_SOURCE_DIR}/generated
>> 2. If ${GENERATED_FOLDER} doesn't exist, set it to
>> ${CMAKE_CURRENT_BINARY_DIR}/generated instead, and set up the targets
>> that will generate the files in that folder. 
>> 3. Simply use the ${GENERATED_FOLDER} variable to add the generated
>> files to your application. 
>> 4. Set up the package_source target so that it packages the files
>> from ${GENERATED_FOLDER} to a folder called "generated" (such that if
>> a user unpacks from there, they will end up in
>> ${CMAKE_CURRENT_SOURCE_DIR}/generated), and you're done. 
>> 5. Recommended: add a check for the existence of target "generate",
>> and if so, set it as a dependency for your application and
>> package_source.
>>
>> This way, you don't need to remember what switches to use, or when to
>> use "make generate". If you need to make it possible for a user to
>> force generation, you can alter step 2 to also run when a command
>> line option is supplied.
>>
>> Hope that helps,
>>
>> Best regards Mark
>
> Works like a charm.
>
> (See https://github.com/layus/mozart2/tree/cache_generated_code)
>
> Thanks !
>

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://public.kitware.com/pipermail/cmake/attachments/20151221/bb9aa59e/attachment.html>


More information about the CMake mailing list