只是添加一些文档就会触发重新编译:有解决方案吗?

3
有时,当我查阅头文件时,我想在(doxygen)文档中添加一些小东西。这可能是关于某个函数参数使用的快速注释,或者只是修正了一个小错误。
但是然后我想:哦不,那会在下一次make调用时触发重新编译!对于某些基本头文件,整个项目都会重新编译,这可能需要很长时间。所以,算了吧!
有解决这个困境的方法吗?是否有方法可以在头文件之外直接记录函数/类的文档说明?或者是否有(打算)智能化的make工具,它会注意到仅更改了某些注释,但不需要重新编译?
6个回答

6
您可以使用ccache来缩短编译时间,可能需要设置CCACHE_UNIFY环境选项。
ccache会对预处理器输出进行哈希处理,如果没有检测到更改,则使用先前编译的对象。
关于CCACHE_UNIFY的手册部分

CCACHE_UNIFY

如果设置环境变量CCACHE_UNIFY,则在编译时未使用-g时,ccache将使用C/C++统一程序来哈希预处理器输出。统一程序比普通哈希慢,因此设置此环境变量会稍微降低速度,但这意味着ccache可以利用仅重新格式化源代码时不重新编译的优势。请注意,使用CCACHE_UNIFY会更改哈希,因此在未设置CCACHE_UNIFY时无法使用已缓存的使用CCACHE_UNIFY设置和反之亦然。默认情况下关闭统一程序的原因是它可能会在编译器警告消息中提供不正确的行号信息。


我认为这不会起作用。至少在使用gcc预处理器时,当您添加一行新的注释时,预处理器会删除所有内容,但保留额外的新行。也就是说,在预处理之后文件将不再相同,ccache将重新编译该文件。我不知道这种预处理器行为是否标准。 - David Rodríguez - dribeas
CCACHE_UNIFY 选项可以解决这个问题,但会牺牲一些速度。我会在我的答案中添加详细信息。 - Hasturkun

3
如何检查(你肯定有版本控制,对吧?)代码库的另一份拷贝,并存放在不同的目录中,专门用于这些编辑操作?
它可以是一个单独的分支,也可以不是。当你需要进行这些小改动时,只需在此处进行修改。你可以直接提交它们:现在它们已经在一个安全的地方,并且不会干扰你的实际开发工作。每隔一段时间,比如一周一次,如果你的构建时间确实很长,你可以将这些更改合并到你正在开发的项目中。只要在一个目录中编写文档,在另一个目录中编写代码,合并冲突应该很少发生。

2

为什么不直接使用touch命令将文件修改时间改回到make不会认为它被更改的时间点呢?

正如onebyone所建议的,您可以将其包装成一个简单的脚本。


2
我会用 "touch -r file.h timestamp" 命令来实现这个功能...编辑 file.h 文件...重新生成文档(但不包括代码)..."touch -r timestamp file.h" 命令。 - Steve Jessop
1
“触碰”方法还可以,但可能存在漏洞:如果您实际上在该标题中进行了代码更改,但忘记了呢? - Frank
这就是为什么在更改文档时要保存和恢复时间戳的原因。这样,如果您以前修改过文件,则该先前的修改仍然可见。只有当您意外更改文档和代码同时时,才会出现您所暗示的问题。这就是忽略更改的代价,所以不要这样做。 - Steve Jessop

1

make 严格按照文件时间戳工作,绝对没有扩展它的计划。make 用于许多除了 C 以外的事情,并且不知道文件内容。如果 make 必须分析更改,您的构建可能会变得更慢。

您可以将文档保留在 .c 文件中,而不是头文件中,这将限制需要重新编译的范围。我承认个人上喜欢在头文件中记录“接口”函数,但从 doxygen 的角度来看,这并不重要。

如另一个人所建议的那样,您可以通过使用“touch”来回溯文件。

doxygen 允许您在外部文件中放置注释,但这通常是不可取的解决方案; doxygen 的整个目的之一就是使文档与源代码保持紧密联系。

否则,我建议您修复编译速度... 您真的不应该害怕它们。


Qt实际上确实是这样做的,所有文档都包含在实现文件中而不是头文件中。我也几乎赞同这种做法,大部分工作发生在实现文件中而不是头文件中。 - Harald Scheirich
我通常遵循这样的规则:接口在头文件中记录,实现特定的注释在实现文件中。 - Frank
@Harold - 那在代码大部分是内联或模板的情况下会变得尴尬吗? - Duck
@Duck - 这是一个很好的观点。C++的确会让你把一些实现放在头文件中,这就让事情变得复杂了。我想你会感到困扰。 - Chris Arguin
@Duck - 我想查看一些模板类,但我这里没有源代码,找不到任何内联文档。该文档可能在单独的文件中... - Harald Scheirich

0

只需要进行更改并接受重新编译即可。当开发人员害怕编译时,很难拥有一个功能齐全的开发环境;也许您需要考虑使用分布式网格编译系统来减少编译时间?


-2

我的解决方案是在Makefile中不将头文件包含为依赖项... 因此对头文件的更改不会触发“make”重新编译。

当然,缺点是如果我进行影响内存布局的更改(例如向类添加成员变量),我需要记住手动编辑受影响的.cpp文件(或者如果很难确定哪个cpp文件受影响,则执行“make clean;make”),这可能有点容易出错... 但通常对我而言有效。


4
除了容易出现错误外,这种方法在规模较大的项目中根本无法扩展,因为你不知道有多少实现文件包含了头文件。而且,如果你一直执行“make all”,那么使用这种方案的初衷就被打败了。 - Newton Falls
-1:我同意Newton Falls的观点。你提出的解决方案不具有可扩展性,并且存在非常高的错误滋生潜力。我看到你在回答中明确指出了这一事实,但在我看来,这绝对是不良实践,因此应该避免。 - Stefano Borini
我同意这并不适用于每个人。但对于我的工作来说,我更喜欢这种方式,因为(和原帖作者一样)我发现在修复注释中的拼写错误后,却发现必须重新编译所有内容真的很烦人。理想情况下,我们需要一个能够识别C/C++代码的版本控制工具,它能够跟踪头文件的哪些部分发生了变化,并利用这些信息来触发必要的重建。至少,它应该能够检测到文件中只有注释发生了变化,并在这种情况下不触发重建。 - Jeremy Friesner

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接