2

There is this project kept in a Git repository, which we build with CMake and Ninja.

We are using globbing expressions/functions to collect all the source files to be compiled. That means that every time a file is added/removed, CMake has to be called to reparse the directories.

We have seen this is bringing some time loss when somebody pulls after somebody has pushed some new file, without modifications to any of the CMake files. I say this last thing because a modification to any of the CMake files would trigger a call to CMake (by Ninja), and everything would be fine.

How can I obtain that CMake is called before/when I start building again my project after pulling? (Note: it does not matter if CMake is run a little bit more than necessary, as long as it is not always)

I am building out of source, furthermore using several build directory where, for example, I test different compilers.

I am exploring some solutions. One using git hooks script, namely post-merge (but how can I guarantee I will retrieve the path to source/CMakeLists.txt to touch it? Can I commit the script so that it runs for everybody? It is not a public project). I don't know if it is relevant; we mainly use Git through a graphic interface (TortoiseGit).

The other possible solution would be using in CMake a custom target dependent on the content of .git\refs\heads directory, but I cannot think of a combination that could really work...

Some references:

  1. 8.3 Customizing Git - Git Hooks
  2. githooks(5) Manual Page

CMake commands: CMake 2.8.11 Documentation

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Antonio
  • 19,451
  • 13
  • 99
  • 197

1 Answers1

1

Putting a post-merge script file in .git/hooks seems to do the trick:

#!/bin/sh
#

touch source/CMakeLists.txt

The execution path is apparently the root directory of the project, which is ideal for this kind of operation. I tested this by calling "pull" in the TartoiseGit context menu from one "random" subfolder of the project. Here are some instructions on how one could test the script.

Drawback: if somebody is modifying the CMakeLists.txt in his editor, with some unsaved modifications, he might lose some work if too quick in answering to the prompt "the file has changed on the disk..."


Then, to make this script part of the repository, I found the following solution that seems to be good for our (non-public) project.

1) Create a folder (e.g. zz_gitHookScripts) for git hook scripts and put the files everybody should be using. Add it to the repository.
2) Add something like this to the CMakeLists.txt, so that the files will be put in the effective directory first time cmake will be run (and, given the above, this will happen the first time we build after pulling, also the first time because CMakeLists.txt gets modified through this edit):

file(GLOB HOOK_SCRIPTS zz_gitHookScripts/*)
if (HOOK_SCRIPTS)
    file(COPY ${HOOK_SCRIPTS} DESTINATION ${CMAKE_SOURCE_DIR}/../.git/hooks) 
endif (HOOK_SCRIPTS)

In case of patches, an equivalent post-applypatch hook might be used.

Drawbacks:

  • it is not triggered in case of stash (a user stashing a change which adds/removes files, must still remember to manually run cmake), or in case of a patch
  • users cannot personalize the hook scripts
  • removing some hook script we don't want to use anymore might be complicated
  • in general all branches will have to share the same hooks

Anyway, like this it's good for our needs.

Community
  • 1
  • 1
Antonio
  • 19,451
  • 13
  • 99
  • 197
  • 1
    Would another drawback is its platform specific? *(suspect this won't work on all platforms?)* – ideasman42 Jun 04 '15 at 15:17
  • @ideasman42 I guess it's ok. It is tested on Windows which doesn't even have touch, the portability is all in the hands of git and its support for shell scripts (and for the touch command). – Antonio Jun 04 '15 at 15:51
  • 1
    Would this run on all git operations? (stashing, changing branches, applying patches) – ideasman42 Jun 04 '15 at 16:54
  • @ideasman42 It works for changing branches. For apply patch, you have to add an additional hook. For stash I have to test, probably not. But stash is something you do locally, and you can learn to run cmake every time you stash as every time you add a file. The point of this hook is to avoid problems when *someone else* adds/removes a file. – Antonio Jun 04 '15 at 22:08
  • 1
    its good you got this working for your own project but this seems a rather unreliable way to solve something CMake wasn't designed for, The developer has to remember which actions cause CMake to re-run, theres always the chance you apply a patch outside of git, or a new dev gets the source and forgets to touch after stashing. Or... who knows, someone may want to use libgit+MSVC... a different environment at least without the same support for shell script hooks. In summary, you propose an unreliable solution that works *sometimes*, as an alternative to listing files - that works *every-time*. – ideasman42 Jun 05 '15 at 00:20
  • @ideasman42 In practice, it works. And it will work in many scenarios. Developers participating in the project need a minimum "education". We avoid bulky cmake files with many people (unwillingly) editing them. – Antonio Jun 05 '15 at 07:14
  • 1
    for your own use probably its *good enough*, but the fact it can fail in common cases such as applying a patch shouldn't be glossed over. It also relies on `git` - which is a drawback in its self, considering over the years projects may to move between VCS systems. - Check all the large projects using CMake, there **is** a best-practice here, and its used for good reason. Under the **Drawbacks** section in this answer, you really should list all the cases which it fails. – ideasman42 Jun 06 '15 at 04:28
  • @ideasman42 The scope of the question was *git* combined with *cmake*, nothing else. Besides, not mentioned so far, listing files has the drawback of potential conflicts on the file containing the list (and potential manual resolution errors), which are not present in the proposed method. Listing files or globbing is, as you know, a [disputed subject](http://stackoverflow.com/q/1027247/2436175). – Antonio Apr 26 '16 at 10:18
  • 1
    @Antonio For a cmake only alternative to your hooks, see my answer on that same [disputed subject](https://stackoverflow.com/questions/1027247/specify-source-files-globally-with-glob/39971448#39971448). It's only drawback I'm aware of is an extra 30+ lines worth of cmake code and an additional "something_changed" file you have to keep in source control. – Glen Knowles Oct 29 '17 at 11:01