为什么没有编译其他模块?

时间:2011-10-11 01:01:55

标签: command-line module compilation d dmd

我有两个文件:Main.dImportMe.d。他们的目的应该是不言自明的。它们位于同一目录中,没有明确的模块声明。但是,当我尝试编译Main.d时,我收到“找不到符号”错误!

$ dmd Main.d -I.

Undefined symbols:
  "_D8ImportMe12__ModuleInfoZ", referenced from:
      _D4Main12__ModuleInfoZ in Main.o
  "_D8ImportMe8SayHelloFxAyaZv", referenced from:
      __Dmain in Main.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
--- errorlevel 1

同时编译这两个文件的效果很好。

$ dmd Main.d ImportMe.d

但是,您不必使用标准库执行此操作。它有什么不同的做法?通过-I更改包含路径没有明显效果。

2 个答案:

答案 0 :(得分:5)

编译模块时,dmd必须具有该模块在其导入路径中所需的所有模块的.d或.di文件。 -I允许您添加导入路径的路径。但是,这并不构建那些其他模块。它只是为dmd提供了构建您请求它构建的模块所需的内容。当你链接时,dmd需要程序中使用的所有模块的目标文件或库二进制文件,否则它会抱怨未定义的符号(-L可以用于链接器标志,如果你想图书馆中的链接)。链接步骤使用C链接器,因此它根本不是D-aware,并且对模块一无所知。

因此,如果您分两步编译和链接,则首先单独编译每个模块或与其他模块一起编译,生成目标文件或库文件,具体取决于您传递编译器的标志(目标文件是默认值) 。然后,在链接阶段将这些目标文件和库链接在一起,生成可执行文件。

当您使用dmd而不传递它-c-lib时,它将同时进行编译和链接,因此您必须提供您要编译的所有模块,或者当它进入链接步骤时,它会抱怨未定义的符号。它并没有神奇地去编译你要求它编译导入的模块的所有模块。如果您想要这种行为,则需要使用rdmd等工具。

dmd能够找到druntime和Phobos而无需指定它们,因为dmd.conf(在Posix上)或sc.ini(在Windows上)。该配置文件将相应的.d和.di文件添加到导入路径,并将libphobos.a或phobos.lib(取决于平台)添加到DFLAGS,以便dmd可以在编译模块时找到这些模块,并且可以在链接阶段链接到库中。它还添加了标准库需要工作的任何其他标志(例如在Linux上的librt中链接)。如果将这些文件移动到非标准位置,则需要更改该配置文件以使dmd仍能找到它们。

答案 1 :(得分:4)

您不必从标准库中指定模块,因为编译器会将预编译的标准库.lib文件隐式传递给链接器。对于您自己的项目,请考虑使用rdmd或其他构建工具。