我一直在阅读C++模块提案(latest draft),但我不完全理解它旨在解决什么问题。
它的目的是允许由一个编译器构建的模块被任何其他编译器使用(当然,在相同的OS/体系结构上)?也就是说,该提案是否等同于标准化C++ ABI?
如果没有,是否有其他提案正在考虑中,以标准化C++ ABI并允许编译器互操作?
发布于 2012-01-31 08:44:27
预编译头文件是某些编译器可以为.cpp文件生成的特殊文件。它们就是:预编译的源代码。它们是通过编译器输入的源代码,并内置于依赖于编译器的格式中。
PCH通常用于加速编译。您将常用的标头放入PCH中,然后只包含PCH。当您在PCH上执行包含时,您的编译器实际上不会执行通常的# #include工作。相反,它将这些预编译的符号直接加载到编译器中。不运行C++预处理器。不运行C++编译器。没有#包括一百万个不同的文件。一个文件被加载,符号直接显示在编译器的工作区中。
我之所以提到这一切,是因为模块是PCH的完美形式。PCH基本上是建立在一个不允许实际模块的系统之上的一个巨大的黑客。模块的最终目的是能够获取一个文件,生成一个包含符号的编译器特定的模块文件,然后一些其他文件根据需要加载该模块。符号是预编译的,所以再说一次,不需要#include一堆东西,运行编译器等等。你的代码说,import thing.foo,它就会出现。
看看任何从STL派生的标准库头。以<map>为例。这个文件很有可能是巨大的,或者包含大量其他文件的#inclusions,这使得结果文件变得巨大。这需要进行大量的C++解析。对于其中包含#include <map>的每个.cpp文件,都必须发生这种情况。每次编译源文件时,编译器都必须重新编译相同的内容。完毕。再来一遍。一遍又一遍。
<map>会在不同的编译之间发生变化吗?没有,但是你的编译器不能知道这一点。所以它必须不断地重新编译它。每次接触.cpp文件时,它都必须编译此.cpp文件包含的每个头文件。即使您没有接触那些头文件或影响这些头文件的源文件。
PCH文件是解决此问题的一种方法。但它们是有限的,因为它们只是一个黑客。每个.cpp文件只能包含一个,因为它必须是.cpp文件包含的第一个内容。由于只有一个PCH,如果您更改了PCH (如向其添加新的标头),则必须重新编译该PCH中的所有内容。
模块本质上与交叉编译器ABI没有任何关系(尽管拥有一个这样的模块会更好,而且模块会让定义一个模块变得更容易)。它们的基本目的是加速编译时间。
发布于 2012-01-31 08:20:08
模块是Java、C#和许多其他现代语言所提供的。它们极大地减少了编译时间,因为今天的头中的代码不需要一遍又一遍地解析,每次都要包含它。当您说#include <vector>时,<vector>的内容将被复制到当前文件中。#include实际上就是复制和粘贴。
在模块世界中,您只需简单地输入import std.vector;,编译器就会加载该模块的查询/符号表。模块文件的格式使编译器可以轻松地解析和使用它。当模块被编译时,它也只被解析一次。在此之后,只需在编译器生成的模块文件中查询所需的信息。
因为模块文件是由编译器生成的,所以它们将与编译器的C++代码的内部表示紧密地联系在一起,因此很可能是不可移植的(就像今天的.o/.so/.a文件一样,因为名称混乱等原因)。
发布于 2012-07-21 04:28:28
当一个库由一个*.so文件和*.h文件组成时,C++中的模块必须首先比现在的解决方案更好。他们必须用#includes来解决今天的问题,也就是:
不管Xeo怎么说,模块在Java或C#中是不存在的。事实上,在这些语言中,“加载模块”依赖于"ok,在这里你有CLASSPATH并搜索它,以找到任何可能提供源文件实际使用的符号的模块“。Java语言中的"import“声明根本不是”模块请求“--与C++中的"using”相同( Java中的“import ns.ns2.*”与C++中的"using namespace ns::ns2“相同)。我不认为这样的解决方案可以在C++中使用。我能想象到的最接近的情况是Vala中的包或Tcl中的模块(从8.5版本开始)。
我认为C++模块不可能是跨平台的,也不可能是动态加载的(需要专用的C++动态模块加载器-这不是不可能的,但现在很难定义)。它们肯定是与平台相关的,并且在请求时也应该是可配置的。但稳定的C++ ABI实际上只需要在一个系统的范围内,就像现在的C++ ABI一样。
https://stackoverflow.com/questions/9072645
复制相似问题