2

I am rather new to CMake, starting off for the first time with a larger project consisting of many subprojects.

For particular reasons (described below for the curious) I already have a set of include files that contain info about the source files needed for each CMake target (lib or exe) – and, for now, I prefer to (re)use these files (reason also described below)

Writing a function to parse these files and add their content as source files to the targets was a surprisingly easy task.

But – now the Problem: Obviously I want to have each targets CMakeLists.txt depend on the particular include file, that generates the list of source files, so that changes on the include file will be detected as if it were changes to CMakeLists.txt itself, but I simply can’t find any references on how to accomplish that.

N.B.: I found AddFileDependencies but that is for adding dependencies on source files, not the CMakeLists.txt. However, CMake itself can figure out dependencies to included .cmake file somehow, so I figured, it should be possible to do somehow.

Background for the curious:
For this project (quite a number of libraries used by quite a number of executable targets, all organized as subprojects) I was using QMake (without actually using Qt itself) for setting up makefiles. Doing so I was able to use Qt Creator while still being able to generate Visual Studio Solution/Project files automagically. We’re also still in progress of evaluating different IDEs and the choice has not been made yet. But the most important reason to use a generator like QMake / CMake was not being forced to set up the VS files for all these subprojects manually.

Although I needed to trick QMake sometimes to do what I wanted to, things went quite well - even for the VS solution - except for one thing: Visual Studio messes up dependencies on Flex/Bison and other files using custom build rules. It keeps recompiling the Flex/Bison/other files saying „command line changed“ – which I gave up trying to fix.

For this reason I thougt, I’d try CMake as a generator instead, which looks very promising so far – although not having builtin precompiled header support in CMake is somewhat ridiculous these days (off topic, I know).

Since Qt Creators CMake support is by far not as good as the support for QMake projects, I firgured, using the approach of parsing the .pri files containing the source file list would enable me using QMake and CMake side by side – especially since the remaining project settings are rather less complicated than on most open source projects.

skybow
  • 131
  • 1
  • 7
  • If you want executable being recompiled when its direct or indirect include file is changed, then it is doing automatically by CMake (at least, for C and C++ languages). – Tsyvarev Jul 21 '15 at 19:16

2 Answers2

1

There's a nice trick which does exactly what you need. It's based on the idea I found in the git-revision module of @rpavlik see this so question

This is the overall idea:

  • Create a dummy timestamp file
  • Add a custom command which touches the timestamp whenever the input .pri file changes
  • include the timestamp file in your CMakeLists.txt

A possible implementation:

set(input_pri_file <path-to-the-input-pri-file>)
set(timestamp_file ${CMAKE_CURRENT_BINARY_DIR}/timestamp.cmake)

add_custom_command(
    OUTPUT ${timestamp_file}
    COMMAND ${CMAKE_COMMAND} -E touch ${timestamp_file}
    MAIN_DEPENDENCY ${input_pri_file}
    VERBATIM
    COMMENT "Updating timestamp.cmake"
)

if(NOT EXISTS "${timestamp_file}")
    file(WRITE ${timestamp_file} "") # create initial empty file
endif()
include(${timestamp_file})

# create the file list from input_pri_file
....
# use the file list
add_executable(main ${filelist})

Here's what happens when the .pri file changes:

  • the change triggers the execution of the custom command
  • which updates the timestamp
  • because the CMakeLists includes the timestamp it is dependent on it
  • so updating the timestamp triggers a re-configuration of the CMakeLists.txt
Community
  • 1
  • 1
tamas.kenez
  • 7,301
  • 4
  • 24
  • 34
1

I use the configure_file() if I have some input that should retrigger CMake's configuration process. See e.g. How to make CMake reconfiguration depend on custom file? and configure_file()'s unit test

So in your case it would look something like:

configure_file(SomeInput.pri ${CMAKE_CURRENT_BINARY_DIR}/SomeInput.pri)

Then you use ${CMAKE_CURRENT_BINARY_DIR}/SomeInput.pri to generate the sources. Just make sure you do not add COPYONLY, because then configuration won't retrigger on changes of SomeInput.pri.

EDIT: Alternatively use - a relative new addition - the CMAKE_CONFIGURE_DEPENDS directory property.

Florian
  • 39,996
  • 9
  • 133
  • 149