4

我有两个文件: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

不过,您不必对标准库执行此操作。它有什么不同?更改包含路径 via-I没有明显的效果。

4

2 回答 2

5

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

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

当你使用 dmd 而不传递它-cor-lib时,它会同时进行编译和链接,所以你必须提供你打算编译的所有模块,或者当它到达链接步骤时,它会抱怨未定义的符号。它不会神奇地编译您要求它编译的模块导入的所有模块。如果您想要这种行为,您需要使用诸如 rdmd 之类的工具。

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

于 2011-10-11T04:49:58.147 回答
4

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

于 2011-10-11T01:23:41.157 回答