真正的问题
我想将项目级源代码格式应用于所有修改后的文件
当前方法
在我的顶级add_custom_target
文件中使用CMakeLists.txt
调用一个脚本,该脚本将格式设置规则应用于SCM工具报告已修改的所有文件:
add_custom_target(Name ALL ${PROJECT_SOURCE_DIR}/../cmake/format_files.bash
)
此规则在任何add_subdirectory
调用之前,因为重新格式化应在 all 编译之前进行。
ALL
指示应将此目标添加到默认的构建目标,以便每次都可以运行该命令(该命令不能称为
ALL
)。
CMake
本身运行时(就像对CMakeLists.txt
文件所做的任何修改一样),一切都很好。
症状
假设我对文件Foo.hh
进行了一些与间距相关的修改(例如,我的规则将制表符替换为空格)。我的构建可能包含以下内容:
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.
我很确定这是源格式脚本,它在依赖项扫描(或类似方法)之后以某种方式在之后运行,修改了Foo.hh
,并产生了时钟偏移的错觉。
我认为的问题是
强制我的构建过程在构建之前为源代码样式声明项目标准而又不会潜在地产生依赖关系问题的正确方法是什么?
是否有更好的方法将格式引入构建过程?
红色鲱鱼
起初,我以为我正在处理一个真正的clock skew问题。我的开发环境是在VMware VM上,过去我们在时间上存在一些问题,但是现在我99%确信所有VM都在使用主机时间。此外,像这样的简单测试(在与我的版本相同的文件系统中)证明没有固有的时钟偏差:
$ 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
源代码格式化过程的一个关键方面是,没有确定性的方式可以知道哪些文件可能在脚本中被修改而哪些文件不会被修改。不会触碰符合项目标准的文件。
为完整起见,以下是脚本:
#!/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
此脚本将附加到如下所示的输出文件(有时可能会删除它):
2019-01-17T18:54:20.641765133:
Unchanged src/Foo.cpp
Formatted src/Foo.hh
Unchanged src/Bar.cpp