The real problem
I want to apply project level source code formatting to all modified files
Current approach
Use add_custom_target
in my top-level CMakeLists.txt
file to call a script that applies formatting rules to all files the SCM tool reports as modified:
add_custom_target(Name ALL ${PROJECT_SOURCE_DIR}/../cmake/format_files.bash
)
This rule is before any add_subdirectory
calls, because reformatting should take place before all compilation.
Per the documentation:
ALL
Indicate that this target should be added to the default build target so that it will be run every time (the command cannot be called
ALL
).
When CMake
itself runs (like any modification to the CMakeLists.txt
files), all is good.
The Symptom
Suppose I perform some spacing-related modification to file Foo.hh
(my rules replace tabs with spaces, for example). My build is likely to include something like this:
Scanning dependencies of target Foo
make[2]: Warning: File `projects/foo/src/Foo.hh' has modification time 8.7 s in the future
...
make[2]: warning: Clock skew detected. Your build may be incomplete.
I'm pretty sure it's the source formatting script that somehow runs after dependency scanning (or something like that), modifies Foo.hh
, and creates the illusion of clock skew.
What I think the question is
What is the right way to force my build process to assert project standards for source code style prior to building, without potentially creating dependency problems?
Is there a better way to introduce formatting to the build process?
Red Herrings
At first, I thought I was dealing with a true clock skew problem; my development environment is on a VMware VM, and we have had some issues with time in the past, but now I'm 99% sure that all the VMs are using host time. Furthermore, a simple test like this (in the same filesystem as my builds) proves there is no intrinsic clock skew:
$ date ; touch foo ; ls --time-style=+%H:%M:%S -l foo ; date
Thu Jan 17 12:48:59 MST 2019
-rw-rw-r--. 1 1001 1001 0 12:48:59 foo
Thu Jan 17 12:48:59 MST 2019
A key facet of the source code formatting process is that there is no deterministic way to know which files might be modified in the script and which will not. Files that comply with project standards are not touched.
For completeness, here is the script:
#!/bin/bash
# This script is intended to format any modified files to project standards
# Change to the project root
cd $(dirname $0)/..
outfile=format.log
file_list=$( git status --short --untracked-files=all src \
| awk '/^( M|\?\?) .*\.(cpp|hh)/ {print $2}' )
# If we haven't changed any files, exit gracefully
[[ -z $file_list ]] && exit 0
# Format the current working set
echo >> ${outfile}
date '+%Y-%m-%dT%H:%M:%S.%N: ' >> ${outfile}
astyle --project $file_list >>${outfile} 2>&1
This script appends to an output file (I'll probably remove that at some point) that looks like this:
2019-01-17T18:54:20.641765133:
Unchanged src/Foo.cpp
Formatted src/Foo.hh
Unchanged src/Bar.cpp