回答
它不应该是顺序依赖的。唯一相关的步骤如下:
- 每个编译单元包括它依赖的内容,应该单独编译。这意味着,首先,每个CPP文件包含它所依赖的所有标题;其次,每个头文件应该包含它所需要的内容,以便它可以编译,即使它是第一个被编译的。
- 链接步骤将所有编译的目标代码放在一起并生成最终的二进制文件。
这取决于环境。一般来说,“编译器”一次只能在单个源文件上工作;您使用更高级的工具来引导它并计算正确的构建顺序。
此类工具的示例可以是make,ant,CMake,SCons,Eclipse和Visual Studio。基本检查通常是源代码文件的修改日期,以及定义各种输出文件如何依赖于输入的内置和自定义规则。
无关。发布确切的问题。编译顺序是非确定性和任意的,并且不会影响项目的可编译性。
事实上,甚至可能没有编译分配的编译命令。如果它发生在不同的机器上,你不能说在b.cpp之前或之后编译a.cpp。 – MSalters 2009-12-15 11:18:57
它不应该的问题它开始哪个文件,所有文件都被编译
编译器编译中不应该有所作为,正如其他人指出的顺序后,链接器解析外部引用。
从编译器的角度来看,当您编译一个带有#include
的文件时,包含的文件会插入正在编译的文件中#include
所在的位置,并在必要时进行递归。
正如其他人所指出的那样,从概念上讲,从哪个文件开始并不重要。但是,从具有最多依赖性的文件开始使用最近编辑的文件(假定编辑了多个文件)可能很有用。某些环境(如Code :: Blocks)实际上允许您对源文件进行加权,以使您能够控制编译顺序。
我能想到的唯一的“包含依赖”问题是递归包含。对于其修复通常与#ifdef
#ifndef INCLUDED_THEFILENAME_H
#define INCLUDED_THEFILENAME_H
/* content goes here *
#endif
守着,但你最好在你所遇到的问题的阐述。
请注意,名称__THEFILENAME_H在用户编写的C++代码中是非法的。 – 2009-12-14 13:14:12
uhm ...对于宏?好吧,无论如何,这个名字是无关紧要的。 – 2009-12-14 13:21:58
@ hacker:即使是宏,你仍然不应该有前导下划线。对于一个宏来说,大写就足够了,当你有'_H''结尾时,它就是一个包含守卫的充分惯例。 – quamrana 2009-12-14 13:27:06
其他人已经表示,订单不应该有所作为。
你可能没有意识到的是编译器编译每.cpp
或.cc
文件。它确实不是编译头文件。而且通常情况下,您只有#include
头文件,而永不.cpp
文件,所以顺序无关紧要。每个.cpp
文件都是独立处理的。它包含许多标题,但这些标题永远不会单独编译,而且它的确不是而是通常还包含其他.cpp
文件。
它不编译头文件?如果一个类在头文件中包含所有的代码,并且没有cpp文件呢? – clamp 2009-12-14 15:11:37
Jalf的含义(甚至在后面的段落中提到)是编译器通常不会自己编译头文件*。相反,它通过编译包含它的.cpp文件隐式编译头文件,从这个意义上讲,头文件经常被编译*多次*,每个包含它的源文件编译一次。链接器将所有重复都作为最终构建步骤进行分类。 – 2009-12-14 16:53:58
是的。编译器处理“翻译单元”。一个翻译单元是一个.cpp文件的结果,并且复制/粘贴所有'#inc'并评估所有的宏。所以编译器看到的基本上是一个.cpp文件,并附有所有头文件。但它从不编译头文件* *。 – jalf 2009-12-14 17:42:14
make工具构建make文件中指定的依赖项的有向非循环图。这通常会说可执行文件取决于一些目标文件。目标文件依赖于源文件,每个源文件都依赖于头文件等等。
这基本上生成一个多路树。该树将以可执行文件为根,并且通常主要包含叶节点的标题(尽管如果您使用的是某种代码生成器,它也可以将该代码生成器的输入文件作为叶)。
然后,它走过那棵从叶节点到根节点的树,然后继续建筑。说“无关紧要”的答案基本上指出,它可以选择树的任何一个分支来构建第一个分支。但是,当它选择一个分支时,它会按照为该分支指定的顺序进行构建。
- 1. .NET命令行编译器在哪里?
- 2. Android库在哪里编译?
- 3. 快速问题:位于Windows中的C++编译器在哪里?
- 4. 我可以在哪里阅读C#编译器的功能?
- 5. 从哪里下载Turbo或Borland C/C++编译器+ IDE?
- 6. 哪里可以找到Eclipse编译器?
- 7. Linux C++编译器(和链接器)如何决定将typeinfo放在哪里?
- 8. zip.so在哪里编译安装php 5.3.9
- 9. 在哪里编码启发式?
- 10. 从哪里启动AlarmManager?
- 11. .NET中编译C#程序后的MSIL文件在哪里?
- 12. 无需Visual Studio 2010,我可以在哪里下载C#4.0的编译器?
- 13. 在哪里以及如何在根启动器主题中添加/编辑css
- 14. java编译器的源代码在哪里?
- 15. Visual Studio的编译器在哪里搜索#includes?
- 16. 指定Maven编译器使用的JDK版本在哪里?
- 17. Flex编译器将.aso文件放在哪里?
- 18. 在哪里可以找到VisualC++ x64命令行编译器?
- 19. CSC编译器在哪里生成PE文件?
- 20. 告诉TypeScript编译器在哪里查找非相关模块
- 21. 如何在C++中编译编译器?
- 22. Tomcat无法启动。我错在哪里?
- 23. 终端:shell启动文件在哪里?
- 24. Python启动横幅在哪里定义?
- 25. 启动现代编译器时出错
- 26. 用C++编译器编译c代码
- 27. 不能在eclipse里编译C++
- 28. 为什么C#编译器第二次启动?
- 29. Avada(WordPress主题)编译CSS:它从哪里编译?
- 30. 启动服务启动后的位置在哪里?
@Daniel:您还可以添加每个头还应该包含它所依赖的内容,以便即使它是模块包含的第一个头也会进行编译。 – quamrana 2009-12-14 13:29:31
谢谢@quamrana,我试图将你的评论纳入我的答案。 – 2009-12-14 13:44:19
我的方式是:只包含一个'#include'的源文件应该始终编译(到.o文件)而不会出错。我使用了一个“hcheck”脚本,它创建了一个.c或.cc文件,它包含在命令行中指定的文件,然后尝试编译它,并删除临时.c/.cc文件完成。 – 2009-12-14 14:15:02