【发布时间】:2010-11-07 11:35:51
【问题描述】:
我有一个包含两个函数的 c++ 程序文件。如果我单独更改第一个函数,为什么必须重新编译它们? 是否有任何构建系统可以单独重新编译第一个并将其放回同一个目标文件中? 这可能吗?一个功能的指令不应该依赖于另一个功能吗? 由于gmake重新编译了整个文件,所以需要很多时间,这不能避免吗?将第二个函数放在单独的文件中不是一个好主意,因为它涉及创建不必要的文件,而这是不必要的。
【问题讨论】:
我有一个包含两个函数的 c++ 程序文件。如果我单独更改第一个函数,为什么必须重新编译它们? 是否有任何构建系统可以单独重新编译第一个并将其放回同一个目标文件中? 这可能吗?一个功能的指令不应该依赖于另一个功能吗? 由于gmake重新编译了整个文件,所以需要很多时间,这不能避免吗?将第二个函数放在单独的文件中不是一个好主意,因为它涉及创建不必要的文件,而这是不必要的。
【问题讨论】:
如果第二个函数很长或需要更多时间来编译,请将其放在单独的文件中。这就是人们分离源文件的原因。据我所知,它必须编译整个文件,因为源代码的微小变化会导致输出文件发生重大变化,因为函数不会相互链接。
【讨论】:
我怀疑使用任何编程语言都可以只编译源文件的一部分。编译是在每个文件的基础上完成的。
【讨论】:
在大多数情况下,确定给定源文件的哪些语义部分已更改并因此需要重新编译的分析可能会超过编译本身的成本。
构建系统通过分析源文件之间的依赖关系获得了巨大的成功,因为文件 I/O(尤其是包含文件)的成本是整个编译成本的很大一部分。一旦您决定重新编译给定的源文件,您可能只会通过忽略文件中未更改的部分来实现微小的加速,即使计算哪些部分是零成本也是如此。
【讨论】:
我知道的所有 C++ 构建系统都在翻译单元(文件)级别而不是函数级别上工作。虽然理论上它应该是可能的,当你考虑预处理器时它应该是复杂的,例如
#define ANSWER 42
void foo()
{
#undef ANSWER
#define ANSWER 41
}
int bar()
{
return ANSWER;
}
尽管这是一个糟糕的代码,但任何符合标准的编译器/构建系统都应该支持它。如您所见,更改foo(重新定义ANSWER)会影响bar。
【讨论】:
将第二个函数放在一个单独的文件中是一个好主意,如果你想避免这个“问题”,是必要的。如果你的函数太大以至于重新编译一个文件所花费的时间很明显,那么这个文件可能太大了,无论如何都应该分解。
【讨论】:
问题不在于 gmake,而在于编译器。如果您更改一个函数,您可能别无选择,只能重新编译其他函数。例如:
a调用函数b,而你改变了函数b,你需要确保a仍然正确调用b,以防b的签名改变。李>
b在内存中的a和c之间,现在b增长到不再适合它,你可能不得不移动a或c,这也涉及重新编译以生成正确的偏移量。b不再在同一个地方,你需要编译它的调用者a指向正确的函数。可能有更多更好的情况需要这样做。
【讨论】: