我有两个文件:Main.d
和ImportMe.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
更改包含路径没有明显效果。
答案 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或其他构建工具。